在面试过程中,遇到过面试官询问测试覆盖率的问题。
我说没统计过(完结撒花)。
开个玩笑。
通常测试覆盖率是用来「衡量测试的充分性和完整性」。
从广义的角度来讲,测试覆盖率主要分为「两大类」,一类是「面向项目的需求覆盖率」,另一类是「更偏向技术的代码覆盖率」。
一、需求覆盖率
需求覆盖率,是指测试「对需求的覆盖程度」。
通常的做法是将每一条分解后的软件需求和对应的测试建立一对多的映射关系,最终目标是保证测试可以覆盖每个需求,以保证软件产品的质量。
但是,在如今敏捷开发模式下,互联网项目中很少直接基于需求来衡量测试覆盖率了,而是「将软件需求转换成测试需求」,然后基于测试需求再来设计测试点。
所以,现在所说的测试覆盖率,通常默认指「代码覆盖率」,而不是需求覆盖率。
二、代码覆盖率
代码覆盖率,通常是指「至少被执行了一次的条目数」占整个条目数的百分比。
这里的“条目数”,可以是代码语句,也可以是函数,还可以是路径,来对应不同的代码覆盖率类型的定义。
1. 最常用的三种代码覆盖率指标
「行覆盖率」 又称为语句覆盖率。指已经被执行到的语句占总可执行语句(不包含类似 C++ 的头文件声明、代码注释、空行等等)的百分比。
这是最常用也是要求最低的覆盖率指标。实际项目中通常会「结合判定覆盖率或者条件覆盖率一起使用」。
2. 判定覆盖
又称分支覆盖。用以度量代码中「每个判断」的「取真分支」和「取假分支」是否各被覆盖「至少各一次」。
比如语句if(a>0 && b>0),需要覆盖a>0 && b>0为 True 和 False各一次。
3. 条件覆盖
条件覆盖,是指判定中的每个条件的可能取值至少满足一次。度量判定中的每个条件的结果 True 和 False 是否都被测试到了。
比如语句if(a>0 && b>0),这里有2个条件输入,分别是a>0和b>0。那么就需要有a>0取True 和 False 各一次,同时要求b>0取True 和 False 各一次。
三、代码覆盖率的价值
· 根本目的是找出「潜在的遗漏测试用例」,并有针对性的进行补充。
· 还可以识别出代码中那些由于需求变更等原因造成的「不可达的废弃代码」。
通常我们希望代码覆盖率越高越好,代码覆盖率越高越能说明你的测试用例设计是充分且完备的。
「但是,也不能盲目追求过高的代码覆盖率,因为后面对于测试的投入成本会呈指数上升」。
目前,主要是在单元测试阶段对代码覆盖率有较高的要求。因为很多测试条件在集成或者页面测试的时候不方便模拟,远不如在单元测试的时候用mock、打桩来实现。
四、代码覆盖率的局限
那么 100% 的代码覆盖率,是否就说明项目质量一定没问题呢?
回答当然是:否。
因为代码覆盖率的计算是「基于现有代码」的,并不能发现那些「未考虑某些输入」以及「未处理某些情况」而引发的问题。
所以,它能反映的仅仅是「已有代码的哪些逻辑被执行过了,哪些逻辑还没有被执行过」。
然后,我们依此为依据,可以补充测试用例,也可以去测试那些还没有覆盖到的执行路径等等。
「总结:高的代码覆盖率不一定能保证软件的质量,但是低的代码覆盖率一定不能保证软件的质量」。
五、代码覆盖率工具
通常,对于不同的语言,会有对应的一些工具。最常见的java,就有一个工具叫 JaCoCo。
JaCoCo 是一款 Java 代码的主流开源覆盖率工具,可以很方便地嵌入到 Ant、Maven 中,并且和很多主流的持续集成工具以及代码静态检查工具,比如 Jekins 和 Sonar 等,都有很好的集成。
1. JaCoCo 代码覆盖率报告
2. JaCoCo 详细代码覆盖率实例
· 绿色的行表示已经被覆盖。
· 红色的行表示尚未被覆盖。
· 黄色的行表示部分覆盖。
· 左侧绿色菱形块表示该分支已经被完全覆盖。
· 左侧黄色菱形块表示该分支仅被部分覆盖。
通过这个详尽的报告,你就可以知道代码真实的执行情况、哪些代码未被覆盖。以此为基础,再去设计测试用例就会更有针对性了。
这里对工具暂时仅做了解即可。