http://www.oecp.cn/hi/wenzhizhong/blog/2484
100%代码测试覆盖率就代表了我们的软件100%测试完毕了吗?我们就能对测试放心了吗?代码测试覆盖率到底给了我们什么确定性的结论呢? 节选自微软技术丛书《完美软件:缺陷预防最佳实践》软件测量与度量一章:“较高的代码覆盖率与较高质量的代码不存在相关性,较高的代码覆盖率反映了测试宽度,不是测试深度,Pareto原理客户关心的缺陷80%可能存在于20%的代码。”
该书微软的作者提出了这样的一种观点:测试宽度和测试深度。我对测试宽度的理解是测试宽度代表实现软件的函数有多少比例被测试调用验证过,如果还有部分实现的函数从未被测试调用验证过,难免在这些函数中会有遗留的缺陷,这是我们追求单元测试覆盖率100%的原始动力。
哪什么是测试深度呢? 先举一个例子:某模块有A(),B(),C() ,D(),E()5个函数。正常的处理流程是A并行依赖B和C, B并行依赖D和E,C依赖E; 如果在实际业务中E()函数的调用失败了(原因有:CPU忙OS调用E超时或E依赖的某个资源不足),那么对原来的函数调用序列的影响是什么呢?则是我们传统的函数接口测试或函数单元测试中难反应的场景,这类函数间的多层次调用序列和相互间的调用交互关系这就是我们的测试深度。传统模式下我们一般在集成黑盒测试的条件下发现这类深层次的测试深度问题。
这也是为什么一直以来单元测试代码做到了100%覆盖了,还是能在系统测试环节发现不少埋藏深难通过人脑静态检视而发现的bug。既然代码测试覆盖率不能代表测试对需求实现覆盖的完整性(包含测试宽度和测试深度),那么我们如何度量测试对需求实现覆盖的完整性呢?
在此我提出了一个设计路径测试覆盖率的概念,鉴于blog表达机制的约束,我就先简单文字描写一下什么是设计路径测试覆盖率—— 任何原始需求的实现都有一个内部状态迁移图,这个迁移图中包含了所有软件运行的路径(成功路径和失效路径)。我们针对状态图的所有路径分段用不同的测试用例来覆盖,并以此目标来设计我们的用例(可以使用单元测试工具手段和可测试性手段来实现),这样我们的测试用例就一定是覆盖了所有的需求实现成功路径和失效路径,并且我们没有多余用例。
当然以上做法的不足是:由于需要测试设计人员对模块实现的设计逻辑要100%清晰理解,耗时会比较多。因此可以只针对20%对客户所关注的高风险模块进行设计路径测试覆盖率的测试设计活动。
G1|G&~7aq0
最后总结2个建议:
1、代码覆盖率可以作为需求实现测试完整度的宽度参考,但不能作为决定测试投入结束的标准。
2、如果测试组织内测试人力和时间不够(大多数情况下),则参考Pareto原理在20%的高风险模块进行设计路径测试覆盖代替进行函数级的代码测试覆盖,用100%的设计路径覆盖用例代替代码测试覆盖率更具真正的测试深度完整性。