应用编程/测试
软件测试中有多种方法可用。审查、演练或检查被称为静态测试,而使用给定的一组测试用例执行已编程的代码则被称为动态测试。[1][2]
静态测试通常是隐式的,例如校对,以及当编程工具/文本编辑器检查源代码结构或编译器(预编译器)检查语法和数据流作为静态程序分析时。动态测试是在程序本身运行时进行的。为了测试代码的特定部分,动态测试可以在程序 100% 完成之前开始,并应用于离散函数或模块。[1][2] 这些的典型技术是使用存根/驱动程序或从调试器环境执行。[2]
静态测试涉及验证,而动态测试还涉及确认。[2]
被动测试是指在不与软件产品进行任何交互的情况下验证系统行为。与主动测试相反,测试人员不提供任何测试数据,而是查看系统日志和跟踪。他们挖掘模式和特定行为以做出某种决定。[3] 这与离线运行时验证和日志分析有关。
探索式测试是一种软件测试方法,简要描述为同时学习、测试设计和测试执行。Cem Kaner 在 1984 年创造了这个词,[4]:2 将探索式测试定义为“一种软件测试风格,强调个人测试人员的自由和责任,通过将与测试相关的学习、测试设计、测试执行和测试结果解释视为在整个项目中相互支持的并行活动来不断优化其工作质量”。[4]:36
软件测试方法传统上分为白盒测试和黑盒测试。这两种方法用于描述测试人员在设计测试用例时所持的观点。一种称为灰盒测试的混合方法也可以应用于软件测试方法。[5][6] 随着灰盒测试(从特定设计元素开发测试)的概念日益突出,黑盒测试和白盒测试之间的“任意区分”在一定程度上消失了。[7]
白盒测试(也称为清晰盒测试、玻璃盒测试、透明盒测试和结构测试)验证程序的内部结构或工作原理,而不是暴露给最终用户的功能。在白盒测试中,使用对系统的内部视角(源代码)以及编程技能来设计测试用例。测试人员选择输入来练习代码中的路径并确定适当的输出。[5][6] 这类似于测试电路中的节点,例如在线测试(ICT)。
虽然白盒测试可以在软件测试过程的单元、集成和系统级别应用,但它通常是在单元级别完成的。[7] 它可以测试单元内的路径、集成期间单元之间的路径以及系统级别测试期间子系统之间的路径。虽然这种测试设计方法可以发现许多错误或问题,但它可能无法检测到未实现的规范部分或缺失的要求。
- API 测试 - 使用公共和私有 API(应用程序编程接口)测试应用程序
- 代码覆盖率 - 创建测试以满足代码覆盖率的某些标准(例如,测试设计人员可以创建测试以导致程序中的所有语句至少执行一次)
- 故障注入方法 - 有意地引入故障以衡量测试策略的有效性
- 变异测试方法
- 静态测试方法
代码覆盖率工具可以评估使用任何方法(包括黑盒测试)创建的测试套件的完整性。这使软件团队能够检查很少测试的系统部分,并确保测试了最重要的功能点。[9] 代码覆盖率作为软件指标,可以报告为以下内容的百分比:[5][9][10]
- 函数覆盖率,它报告执行的函数
- 语句覆盖率,它报告执行完成测试的行数
- 判定覆盖率,它报告给定测试的 True 和 False 分支是否都已执行
100% 语句覆盖率确保所有代码路径或分支(在控制流方面)至少执行一次。这有助于确保功能正确,但还不够,因为相同的代码可能会正确或错误地处理不同的输入。[11] 伪测试的函数和方法是那些被覆盖但未指定的函数和方法(可以删除其主体而不会破坏任何测试用例)。[12]
黑盒测试(也称为功能测试)将软件视为“黑盒”,在不知道内部实现的情况下检查功能,不查看源代码。测试人员只知道软件应该做什么,而不是它如何做。[13] 黑盒测试方法包括:等价类划分、边界值分析、全对测试、状态转换表、决策表测试、模糊测试、基于模型的测试、用例测试、探索性测试和基于规范的测试。[5][6][10]
基于规范的测试旨在根据适用的需求测试软件的功能。[14] 这种级别的测试通常需要提供详细的测试用例给测试人员,然后测试人员可以简单地验证,对于给定的输入,输出值(或行为)是否与测试用例中指定的预期值相同。测试用例围绕规范和需求构建,即应用程序应该做什么。它使用软件的外部描述,包括规范、需求和设计来推导出测试用例。这些测试可以是功能性的或非功能性的,尽管通常是功能性的。
基于规范的测试可能需要确保功能正确,但不足以防范复杂或高风险情况。[15]
黑盒技术的一个优点是它不需要任何编程知识。无论程序员可能有什么偏见,测试人员可能拥有不同的偏见,并且可能强调不同的功能区域。另一方面,有人说黑盒测试“就像在没有手电筒的黑暗迷宫中行走”。[16] 因为他们不检查源代码,所以有些情况下,测试人员会编写许多测试用例来检查某些东西,而这些东西本来可以用一个测试用例来测试,或者会留下程序的某些部分未经测试。
这种测试方法可以应用于所有级别的软件测试:单元、集成、系统和验收。[7] 它通常包括大多数(如果不是全部)较高级别的测试,但也可能主导单元测试。
组件接口测试
组件接口测试是黑盒测试的一种变体,重点是数据值,而不仅仅是子系统组件的相关操作。[17] 组件接口测试的实践可用于检查在各个单元或子系统组件之间传递的数据处理,超出了这些单元之间的完全集成测试。[18][19] 传递的数据可以被认为是“消息包”,可以检查数据范围或数据类型,对于从一个单元生成的数据,在传递到另一个单元之前测试其有效性。接口测试的一种选择是为传递的数据项保留一个单独的日志文件,通常还会记录时间戳,以便分析数天或数周内在单元之间传递的数据的数千个案例。测试可以包括检查一些极端数据值在其他接口变量作为正常值传递时的处理方式。[18] 接口中的异常数据值可以帮助解释下一个单元中的意外性能。
视觉测试
[edit | edit source]视觉测试的目的是让开发人员能够通过以开发人员可以轻松找到所需信息的方式呈现数据来检查软件故障发生时的状况,并且信息表达清晰。[20][21]
视觉测试的核心思想是,向某人展示一个问题(或测试失败),而不是仅仅描述它,这会大大提高清晰度和理解力。因此,视觉测试需要记录整个测试过程——以视频格式捕获测试系统上发生的所有内容。输出视频通过画中画网络摄像头提供的实时测试人员输入和麦克风提供的音频评论进行补充。
视觉测试提供了许多优势。沟通质量大大提高,因为测试人员可以向开发人员展示问题(以及导致问题的事件),而不是仅仅描述它,并且在许多情况下,不再需要复制测试失败。开发人员将拥有所有她或他需要的测试失败的证据,并且可以专注于故障的原因以及如何修复它。
随机测试和探索性测试是检查软件完整性的重要方法,因为它们需要更少的准备时间来实施,而重要错误可以很快找到。[22] 在随机测试中,测试以即兴、即兴的方式进行,测试人员能够根据记录的方法进行测试,然后即兴发挥这些测试的变体,从而对缺陷修复进行更严格的检查。[22] 然而,除非严格记录程序,否则随机测试的局限性之一就是缺乏可重复性。[22]
灰盒测试
[edit | edit source]灰盒测试(美式拼写:gray-box testing)是指了解内部数据结构和算法,以便设计测试,同时在用户或黑盒级别执行这些测试。测试人员通常可以访问“源代码和可执行二进制文件”。[23] 灰盒测试还可以包括逆向工程(使用动态代码分析)来确定边界值或错误消息等。[23] 操作输入数据和格式化输出不属于灰盒测试,因为输入和输出显然位于我们称为被测系统的“黑盒”之外。这种区别在对两个不同开发人员编写的两个代码模块进行集成测试时尤其重要,在这种情况下,只有接口暴露给测试。
通过了解软件工作原理的基本概念,测试人员在从外部测试软件时可以做出更明智的测试选择。通常情况下,灰盒测试人员被允许设置一个隔离的测试环境,进行诸如播种数据库之类的活动。测试人员可以观察测试产品的状态,在执行某些操作(例如,对数据库执行 SQL 语句,然后执行查询以确保反映了预期的更改)后,测试人员可以观察测试产品的状态。灰盒测试基于有限的信息实施智能测试场景。这将特别适用于数据类型处理、异常处理等。[24]
测试级别
[edit | edit source]软件测试中主要有 4 个级别:[25]
1. 单元测试 - 这检查软件组件是否满足功能。它是系统或应用程序中最小的可测试部分,可以编译、链接、加载和执行。这种测试有助于分别测试每个模块。目标是通过分离来测试软件的每个部分。它检查组件是否满足功能。这种测试由开发人员执行。
2. 集成测试 - 这检查数据从一个模块到另一个模块的流程。集成意味着组合。例如,在这个测试阶段,不同的软件模块被组合在一起并作为一个组进行测试,以确保集成后的系统已准备好进行系统测试。集成测试检查数据从一个模块到另一个模块的流程。这种测试由测试人员执行。
3. 系统测试 - 这评估测试的功能需求和非功能需求。系统测试是在完整的集成系统上执行的。它允许检查系统是否符合要求。它测试组件的整体交互。它包括负载、性能、可靠性和安全性测试。系统测试通常是验证系统是否满足规范的最终测试。它评估测试的功能需求和非功能需求。
4. 验收测试 - 这检查规格或合同的要求是否按其交付方式满足。验收测试是为找出规格或合同的要求是否按其交付方式满足而进行的测试。验收测试通常由用户或客户进行。但是,其他利益相关者也可以参与此过程。
测试技术和策略
[edit | edit source]有 5 种重要的软件测试技术和策略:[26]
1. 边界值分析 (BVA) - 基于对分区边界进行测试。它包括最大值、最小值、边界内或边界外、典型值和错误值。通常认为,在定义的输入值的边界处比在中心处出现更多错误。它也称为 BVA,并提供了一组用于测试边界值的测试用例。这种黑盒测试技术是对等价类划分的补充。这种软件测试技术基于以下原则:如果系统对这些特定值运行良好,那么它将对这两个边界值之间的所有值运行良好。
边界值分析指南
- 如果输入条件限制在值 x 和 y 之间,则应设计包含值 x 和 y 以及高于和低于 x 和 y 的值的测试用例。
- 如果输入条件是大量值,则应开发需要测试最小值和最大值的测试用例。在此,还测试了最小值和最大值之上的值和之下的值。
- 将指南 1 和 2 应用于输出条件。它提供反映最小值和最大值的预期输出。它还测试了以下值或以上值。
2. 等价类划分 - 这使您可以将测试条件集划分为应被视为相同的分区。这种软件测试方法将程序的输入域划分为数据类别,从中应设计测试用例。这种技术背后的概念是,每个类别的代表值的测试用例等同于同一类别任何其他值的测试。它允许您识别有效和无效的等价类。
3. 基于决策表的测试 - 也称为因果表。这种软件测试技术用于响应输入或事件组合的功能。例如,如果用户已输入所有必填字段,则应启用提交按钮。第一步是识别输出取决于输入组合的功能。如果输入组合集很大,则将其划分为较小的子集,这有助于管理决策表。对于每个函数,您都需要创建一个表并列出所有类型的输入组合及其相应的输出。这有助于识别测试人员忽略的条件。
以下是创建决策表的步骤
- 在行中列出输入。
- 在列中输入所有规则。
- 用不同的输入组合填充表格。
- 在最后一行,记下与输入组合对应的输出。
4. 状态转换 - 这种技术在输入条件更改时更改被测应用程序 (AUT) 的状态。这种测试技术允许测试人员测试 AUT 的行为。测试人员可以通过按顺序输入各种输入条件来执行此操作。在状态转换技术中,测试团队提供正负输入测试值来评估系统行为。
状态转换指南
- 当测试团队为有限的输入值集测试应用程序时,应使用状态转换。
- 当测试团队想要测试被测应用程序中发生的事件序列时,应使用该技术。
5. 错误猜测 - 这是一种软件测试技术,基于猜测代码中可能存在的错误。该技术严重依赖经验,其中测试分析师利用他们的经验来猜测测试应用程序存在问题的部分。因此,测试分析师必须熟练且经验丰富才能更好地进行错误猜测。该技术统计了可能发生的错误或容易出错情况的列表。然后测试人员编写一个测试用例来暴露这些错误。为了根据这种软件测试技术设计测试用例,分析师可以使用过去的经验来识别条件。
错误猜测指南
- 测试应使用以前测试类似应用程序的经验。
- 了解被测系统。
- 了解典型的实现错误。
- 记住以前出现问题的区域。
- 评估历史数据和测试结果。
测试流程
[edit | edit source]单元测试
[edit | edit source]优点和局限性
[edit | edit source]- 验证您的工作 - 通过编写测试,您可以仔细检查您所做的事情。单元测试在开发周期的早期发现问题。这包括程序员实现中的错误以及单元规范中的缺陷或缺失部分。编写完整的测试集的过程迫使作者考虑输入、输出和错误条件,从而更清晰地定义单元的预期行为。
- 将代码中的关注点分离 - 对代码进行单元测试需要您使其可测试。使代码可测试通常意味着预先声明依赖项。这种代码结构通常会导致更简洁的设计和更好的关注点分离。对于未经测试的代码,更容易错过隐式依赖关系,并且类会默默地承担多种责任。
- 始终最新的文档 - 虽然文档会过时,除非您更新它,但与代码一起运行并通过的测试不会过时。如果您编写干净的测试,这些测试可以作为代码的常青文档。单元测试提供了系统的一种“活文档”。想要了解单元提供了哪些功能以及如何使用它的开发人员可以查看单元测试,以了解单元接口 (API) 的基本知识。
- 更少的回归 - 只要单元测试在代码库中,它们就能有效地捕获回归。
- 重构的安全网 - 虽然单元测试可以捕获小更改的回归,但它们在大型重构中大放异彩。在具有高测试覆盖率和良好测试的代码库中,重构的工作具有更高的信心。单元测试允许程序员在以后重构代码或升级系统库,并确保模块仍然正常工作(例如,在回归测试中)。该过程是为所有函数和方法编写测试用例,以便每当更改导致错误时,都可以快速识别它。单元测试检测可能破坏设计契约的更改。
以下是使用单元测试的局限性或缺点:[29]
- 使用单元测试,您必须增加需要编写的代码量。通常,您需要编写一个或多个单元测试,具体取决于事物有多复杂。建议至少要有三个,这样您就不会只得到相互矛盾的“是”和“否”。对于编写的每一行代码,程序员通常需要 3 到 5 行测试代码。这显然需要时间,并且投资可能不值得付出努力。虽然测试代码应该相当简单,但这种测试方法仍然需要更多工作和更多代码,这意味着更多时间和更多成本。
- 单元测试不能也不会捕获程序中的所有错误。它不可能测试每条执行路径或发现集成错误和完整的系统问题。单元测试应该与其他软件测试活动一起完成,因为它们只能显示特定错误的存在或不存在;它们不能证明完全不存在错误。为了保证每个执行路径和每个可能输入的正确行为,并确保不存在错误,需要其他技术,即应用形式方法来证明软件组件没有意外行为。
- 单元测试必须是现实的。您希望您正在测试的单元能够像它作为完整系统的一部分那样起作用。如果这种情况没有发生,则测试值和准确性就会受到损害。
应用
[edit | edit source]测试驱动开发
[edit | edit source]测试驱动开发 (TDD) 使用测试作为设计代码的方式,先创建测试,然后再编写任何实际的生产代码。然后,您尝试通过创建满足测试的生产代码来使测试通过。这通常是一个五步过程
- 编写测试(有些人也称其为规范)。
- 运行测试并显示它失败。(红色)
- 编写满足测试需求的最少生产代码。
- 运行测试直到它通过。(绿色)
- 重构。
此过程有时称为红绿重构。红色象征着失败,绿色代表通过。[[30]]
优点和局限性
[edit | edit source]活动
[edit | edit source]关键词
[edit | edit source]验收测试 - 检查规范或合同的要求是否按其交付方式满足。[31]
Alpha 测试 - 在开发结束时进行的测试,专注于模拟真实用户的体验。
断言 - 一个谓词……与程序中的一个点相关联,在代码执行的该点始终应评估为真。[32]
Beta 测试 - 由软件应用程序的“真实用户”在“真实环境”中执行。[33]
伙伴测试 - 两个伙伴相互合作,在同一个模块中识别缺陷。通常,一个伙伴来自开发团队,另一个来自测试团队。伙伴测试有助于测试人员开发更好的测试用例,而开发团队也可以尽早进行设计更改。这种测试通常在单元测试完成后进行。[34]
覆盖率 - 用于描述在特定测试套件运行时程序源代码执行程度的度量。[35]
集成测试 - 检查数据从一个模块到其他模块的流动。[31]
手动测试 - 一种软件测试类型,其中测试用例由测试人员手动执行,不使用任何自动化工具。[36]
Pytest - 一个测试框架,允许用户使用 Python 编程语言编写测试代码。[37]
Pytest 覆盖率 - PyTest 的一个覆盖率插件,用于衡量 Python 程序的代码覆盖率。
重构 - 重构现有代码。
回归测试 - 重新运行功能性和非功能性测试,以确保在更改后先前开发和测试的软件仍然可以正常运行。[38]
系统测试 - 评估测试的功能性和非功能性需求。[31]
单元测试 - 检查软件组件是否满足功能要求。[31]
- ↑ a b Graham, D.; Van Veenendaal, E.; Evans, I. (2008). 软件测试基础. Cengage Learning. pp. 57–58. ISBN 9781844809899.
- ↑ a b c d Oberkampf, W.L.; Roy, C.J. (2010). 科学计算中的验证和确认. Cambridge University Press. pp. 154–5. ISBN 9781139491761.
- ↑ Lee, D.; Netravali, A.N.; Sabnani, K.K.; Sugla, B.; John, A. (1997). "被动测试及其在网络管理中的应用". 1997 年国际网络协议会议论文集. IEEE Comput. Soc: 113–122. doi:10.1109/icnp.1997.643699. ISBN 081868061X. S2CID 42596126.
- ↑ a b Cem Kaner (2008), 探索性测试教程 (PDF)
- ↑ a b c d Limaye, M.G. (2009). 软件测试. Tata McGraw-Hill Education. pp. 108–11. ISBN 9780070139909.
- ↑ a b c d Saleh, K.A. (2009). 软件工程. J. Ross Publishing. pp. 224–41. ISBN 9781932159943.
- ↑ a b c Ammann, P.; Offutt, J. (2016). 软件测试入门. Cambridge University Press. p. 26. ISBN 9781316773123.
- ↑ Everatt, G.D.; McLeod Jr., R. (2007). "第七章:功能测试". 软件测试:贯穿整个软件开发生命周期的测试. John Wiley & Sons. pp. 99–121. ISBN 9780470146347.
- ↑ a b Cornett, Steve (c. 1996). "代码覆盖率分析". Bullseye Testing Technology. 简介. 检索于 2017 年 11 月 21 日.
- ↑ a b Black, R. (2011). 实用软件测试:成为高效且有效的测试专业人员. John Wiley & Sons. pp. 44–6. ISBN 9781118079386.
- ↑ 举个简单的例子,C 函数
int f(int x){return x*x-6*x+8;}
只有一个语句。所有针对规范f(x)>=0
的测试都将成功,除非恰好选择了x=3
。 - ↑ Vera-Pérez, Oscar Luis; Danglot, Benjamin; Monperrus, Martin; Baudry, Benoit (2018). "伪测试方法的全面研究". Empirical Software Engineering. 24 (3): 1195–1225. arXiv:1807.05030. Bibcode:2018arXiv180705030V. doi:10.1007/s10664-018-9653-2. S2CID 49744829.
- ↑ Patton, Ron (2005). 软件测试 (第二版). Indianapolis: Sams Publishing. ISBN 978-0672327988.
- ↑ Laycock, Gilbert T. (1993). 基于规范的软件测试的理论与实践 (PDF) (论文). 计算机科学系, 谢菲尔德大学. 检索于 2018 年 1 月 2 日.
- ↑ 巴赫,詹姆斯 (1999 年 6 月). "基于风险和需求的测试" (PDF). Computer. 32 (6): 113–114. 检索于 2008 年 8 月 19 日.
- ↑ Savenkov, Roman (2008). 如何成为一名软件测试人员. Roman Savenkov Consulting. p. 159. ISBN 978-0-615-23372-7.
- ↑ Mathur, A.P. (2011). 软件测试基础. Pearson Education India. p. 63. ISBN 9788131759080.
- ↑ a b Clapp, Judith A. (1995). 软件质量控制、错误分析和测试. p. 313. ISBN 978-0815513636. 检索于 2018 年 1 月 5 日.
- ↑ Mathur, Aditya P. (2007). 软件测试基础. Pearson Education India. p. 18. ISBN 978-8131716601.
- ↑ Lönnberg, Jan (2003 年 10 月 7 日). 软件的视觉测试 (PDF) (硕士). 赫尔辛基理工大学. 检索于 2012 年 1 月 13 日.
- ↑ Chima, Raspal. "视觉测试". TEST Magazine. 存档自 原文 于 2012 年 7 月 24 日. 检索于 2012 年 1 月 13 日.
- ↑ a b c Lewis, W.E. (2016). 软件测试和持续质量改进 (第三版). CRC Press. pp. 68–73. ISBN 9781439834367.
- ↑ a b Ransome, J.; Misra, A. (2013). 核心软件安全:从源头开始的安全. CRC出版社. pp. 140–3. ISBN 9781466560956.
- ↑ "SOA测试工具:黑盒、白盒和灰盒" (白皮书). Crosscheck网络. 存档自 原始版本 于2018年10月1日. 检索于 2012年12月10日.
- ↑ https://www.guru99.com/levels-of-testing.html
- ↑ https://www.guru99.com/software-testing-techniques.html
- ↑ https://blog.pragmaticengineer.com/unit-testing-benefits-pyramid/
- ↑ 单元测试
- ↑ https://theqalead.com/topics/unit-testing/
- ↑ https://testguild.com/unit-tdd-and-bdd-testing-whats-the-difference/
- ↑ a b c d Guru99 - 测试级别
- ↑ w:断言_(软件开发)
- ↑ Guru99 - Alpha/Beta 测试
- ↑ Guru99 - 随机测试
- ↑ w:代码覆盖率
- ↑ Guru99 - 手动测试
- ↑ Guru99 - PyTest
- ↑ w:回归测试