Testing Principles of software development
• • ☕️ 1 min read
- 你可以从本文了解到
- 107 依据需求跟踪测试
- 108 在测试之前早做测试计划
- 109 不要测试自己开发的软件
- 110 不要为自己的软件做测试计划
- 111 测试只能揭示缺陷的存在
- 112 虽然大量的错误可证明毫无价值,但是零错误并不能说明软件的价值
- 113 成功的测试应发现错误
- 114 半数的错误出现在 15% 的模块中
- 115 使用黑盒测试和白盒测试
- 116 测试用例应包含期望的结果
- 117 测试不正确的输入
- 118 压力测试必不可少
- 119 大爆炸理论不适用
- 120 使用 McCabe 复杂度指标
- 121 使用有效的测试完成度标准
- 122 达成有效的测试覆盖
- 123 不要在单元测试之前集成
- 124 测量你的软件
- 125 分析错误的原因
- 126 对“错”不对人
你可以从本文了解到
本文是对《软件设计的 201 个原则》的第6章——软件开发的测试原则的学习
测试是包含以下行为的集合:
对独立的软件组件执行测试(即:单元测试,Unit Testing),以确保其行为与组件设计规格说明中的定义足够的接近
对执行过单元测试的组件集合执行测试(即:集成测试,Integration Testing),以确保这些组件一起工作时的行为足够接近设计中的说明。
对集成测试过的所有组件进行测试(即:软件系统级测试,Software Systems-level Testing),以确保它们可以作为一个系统来运行,且行为足够接近软件需求规格说明中的定义。
制定软件系统级测试的测试计划。
制定软件集成测试的测试计划。
制定单元测试的测试计划。
建立测试装置(test harness)和测试环境(test environment)。
107 依据需求跟踪测试
理解哪些测试可以验证哪些需求是很重要的。有如下两个原因:(1)在生成测试时,你会发现,了解是否所有需求都在被测试是很有用的。(2)在执行测试时,你会发现,了解正在验证哪些需求是很有用的。
此外,如果你的需求已经排了优先级(原则 50),可以很容易得出测试的相对优先级;也就是说,一个测试的优先级是其所有对应需求的优先级的最大值。
维护一个大二进制表,其中行对应于所有软件测试,列对应于软件需求规格说明中的每个需求。任何位置的 1 表示此测试有助于验证此需求。
注意,一整行都没有被置 1 表示此测试没有目的,一整列都没有被置 1 表示该需求漏测。能够成功地创建这样一个表,取决于你唯一地引用每个需求的能力(原则 52)。
108 在测试之前早做测试计划
109 不要测试自己开发的软件
软件开发人员永远不应成为自己软件的主要测试者。开发人员比较适合进行初始调试(译者注:自测)和单元测试。 [相反的观点,可参见Mills, H., et al., "Cleanroom Software Engineering",in IEEE Software, 4, 5 (September 1987), pp. 19–25.]
PS,目前确实有新的倾向,由程序员来测试自己的代码。但本原则提到的因素依然值得考虑。一个能够充分对自己代码进行测试的程序员,需要能够把自己的视角切换到一个测试人员,并且有发现bug的足够欲望。
110 不要为自己的软件做测试计划
你不仅不应该测试自己的软件(原则 109),而且也不应该负责为软件生成测试数据、测试方案或测试计划。如果你负责了,那么你可能会在测试生成中犯与软件创建中相同的错误。例如,如果你在设计软件时对合法输入的范围做了一个错误的假设,那么在生成测试计划时,你很可能会做出同样的假设。
111 测试只能揭示缺陷的存在
无论多么彻底和深入,测试只能揭示程序中缺陷的存在,而并不能确保程序没有缺陷。它可以增加你对程序正确性的信心,但它不能证明程序的正确性。为了获得真正的正确性,必须使用完全不同的方法,即正确性证明。
112 虽然大量的错误可证明毫无价值,但是零错误并不能说明软件的价值
这是杰拉尔德·温伯格(Gerald Weinberg)的“无差错谬论”(Absence of Errors Fallacy)。它真正地将测试纳入了视野。它还将所有的软件工程和管理纳入视野。本原则的第一部分显然是正确的,有很多错误的软件是没用的。第二部分则发人深省。它表达的是:无论你多么努力地消除错误,除非你在开发正确的系统,否则你都是在浪费时间。
Akao 的《质量功能部署》(Quality Function Deployment, Cambridge, Mass.: Productivity Press, 1990)详细介绍了一种方法,用于确保你在整个软件生命周期中开发正确的系统。本原则的一个推论是,如果你在开发错误的系统,那么世界上所有的形式化方法、所有的测试和所有的产品保证都将于事无补。
113 成功的测试应发现错误
114 半数的错误出现在 15% 的模块中
保守估算,在大型系统中,大约所有软件错误的半数出现在 15% 的模块中,80% 的软件错误出现在 50% 的模块中。Gary Okimoto 和 Gerald Weinberg 的结论更引人注目,所有错误的 80% 是在仅仅 2% 的模块中发现的(参见 Weinberg 的《质量软件管理》: Quality Software Managetnent, Vol. 1: Systems Thinking, New York: Dorset House, 1992)。因此,在测试软件时,你可以这样认为,在发现错误的地方,很可能会发现更多错误。
要维护日志(译者注:指测试日志),不仅记录在项目的每个时间段内发现了多少错误,还要记录每个模块发现了多少错误。当历史表明一个模块非常容易出错时,你最好从头开始重写它,强调简单性(原则67),而不是聪明。
115 使用黑盒测试和白盒测试
116 测试用例应包含期望的结果
117 测试不正确的输入
118 压力测试必不可少
119 大爆炸理论不适用
你不能通过忽略单元测试和集成测试来节省时间。
120 使用 McCabe 复杂度指标
121 使用有效的测试完成度标准
有效度量测试进度的两个想法是:
每周发现新错误的比率。
暗中在软件中埋下已知的 bug ( Tom Gilb 管这个叫 bebugging )后,这些 bug 到目前为止被发现的百分比。
对于测试进度的一个无效指标是测试用例通过的百分比(当然除非你确定测试用例很好地覆盖了需求)。
122 达成有效的测试覆盖
在测试计划生成或测试执行阶段,有一些指标可以用来确定代码执行测试的全面程度。
行覆盖率,用于衡量至少执行一次的语句的百分比。
分支覆盖率,用于衡量程序中被执行的分支的百分比。
路径覆盖率,用于衡量所有可能路径(通常是无限的)覆盖程度
123 不要在单元测试之前集成
124 测量你的软件
一个发现原因的方法是测量你的软件,也就是,嵌入特殊的指令到软件中,来报告执行轨迹、异常状况、过程调用等等
125 分析错误的原因
错误在软件中是很常见的。我们会花费大量的资源来发现和修复它们。
从一开始就防止它们的发生,从而降低它们的影响,是更划算的。
为此的一个方法是,当检测到错误的时候,分析它们的原因。
126 对“错”不对人
当你或他人在你的代码中发现错误时,公开坦诚得讨论它。与其责骂自己,不如将它当作自己和他人的学习经历(更多信息见原则 125)。