06 你真的懂测试覆盖率吗?
测试覆盖率通常被用来衡量测试的充分性和完整性
从广义的角度来讲,主要分为两大类:
- 面向项目的需求覆盖率
- 更偏向技术的代码覆盖率
需求覆盖率
需求覆盖率是指测试对需求的覆盖程度,通常的做法是将每一条分解后的软件需求和对应的测试建立一对多的映射关系,最终目标是保证测试可以覆盖每个需求,以保证软件产品的质量。
需求覆盖率的统计方法属于传统瀑布模型下的实践,而在当前敏捷研发模式下,很少有项目直接基于需求来衡量测试覆盖率,而是将软件需求转换成测试需求,然后基于测试需求再来设计测试点:
![](https://img.haomeiwen.com/i19080397/2f45d113407d30c6.png)
因此,现在人们口中的测试覆盖率,通常默认指代码覆盖率,而不是需求覆盖率。
代码覆盖率
代码覆盖率是指,至少被执行了一次的条目数占整个条目数的百分比。
- 如果“条目数”是语句,对应的就是代码行覆盖率;
- 如果“条目数”是函数,对应的就是函数覆盖率;
- 如果“条目数”是路径,那么对应的就是路径覆盖率;
......
常见覆盖率指标
- 行覆盖率,又称代码覆盖率。指已经被执行到的语句占总可执行语句的百分比。
- 判定覆盖,又称分支覆盖,用以度量程序中每一个判定的分支是否都被测试到了。
- 条件覆盖,指判定中的每个条件的可能取值至少满足一次。
代码覆盖率的价值
统计代码覆盖率的根本目的是找出潜在的遗漏测试用例,并有针对性的进行补充,同时还可以识别出代码中那些由于需求变更等原因造成的不可达的废弃代码。
通常我们希望代码覆盖率越高越好,代码覆盖率越高说明测试用例设计是充分且完备的,但测试的成本会随着代码覆盖率的提高迅速增加。
结合我们前面所学习到的测试不可穷进性和测试对象的可测试性来看,在单元测试对核心代码实施较高的代码覆盖率要求可以获得较高的收益。
所以在软件企业中,只有单元测试阶段对代码覆盖率有较高的要求。
局限性
代码覆盖率的计算是基于现有代码的,并不能发现那些“未考虑某些输入”以及“未处理某些情况”形成的缺陷。
如果一个被测函数里面只有一行代码,只要这个函数被调用过,那么覆盖率指标就是 100%,但是仅这一行代码真的实现了需求吗?
function myFunction() {
return 0;
}
显然,这个函数并不能实现任何需求,除非你的需求就是要函数返回一个0。
但反过来想,如果代码覆盖率不够甚至低到连核心业务的主要函数都没有覆盖完全,那么这些代码的质量又该如何去保证呢?
所以,高的代码覆盖率不一定能保证软件的质量,但是低的代码覆盖率一定不能保证软件的质量。
工具
JaCoCo:一款 Java 代码的主流开源覆盖率工具,可以很方便地嵌入到 Ant、Maven 中,并且和很多主流的持续集成工具以及代码静态检查工具,比如 Jekins 和 Sonar 等,都有很好的集成。
总结
实际项目中高的代码覆盖率不仅成本高昂且不一定有好的质量保障,我们应当以需求为导向而不是片面追求覆盖率来提高代码质量。
在实际的测试用例中,正向用例一般比较容易写,难的是可能存在的异常情况和异常场景,这需要测试人员在非功能性上有广泛的认识和测试经验。
思考
笔者在实际工作中未接触到代码覆盖率工具,学生时代倒是接触过Junit框架和它自带的覆盖率统计功能
![](https://img.haomeiwen.com/i19080397/6dbe0b88fe169e4d.png)
同时笔者在学习这章内容中,也注意到了敏捷研发模式和瀑布模式对于测试有不同的要求,所以测试人员要融入敏捷模式并做好质量工作的推进还需要有更多的理念支撑,比如敏捷测试四象限等相关概念。
在此笔者推荐一本书《敏捷软件测试》,希望能有所帮助。
![](https://img.haomeiwen.com/i19080397/d0ef5f8ccdf65277.png)