在做单元测试时,代码覆盖率常常被拿来作为衡量测试好坏的指标,甚至,用代码覆盖率来考核测试任务完成情况,比如,代码覆盖率必须达到80%或 90%。于是乎,测试人员费尽心思设计案例覆盖代码。用代码覆盖率来衡量,有利也有有弊。本文我们就代码覆盖率展开讨论,也欢迎同学们踊跃评论。
首先,让我们先来了解一下所谓的“代码覆盖率”。我找来了所谓的定义:
代码覆盖率 = 代码的覆盖程度,一种度量方式。
上面简短精悍的文字非常准确的描述了代码覆盖率的含义。而代码覆盖程度的度量方式是有很多种的,这里介绍一下最常用的几种:
1. 语句覆盖(StatementCoverage)
又称行覆盖(LineCoverage),段覆盖(SegmentCoverage),基本块覆盖(BasicBlockCoverage),这是最常用也是最常见的一种覆盖方式,就是度量被测代码中每个可执行语句是否被执行到了。这里说的是“可执行语句”,因此就不会包括像C++的头文件声明,代码注释,空行,等等。非常好理解,只统计能够执行的代码被执行了多少行。需要注意的是,单独一行的花括号{} 也常常被统计进去。语句覆盖常常被人指责为“最弱的覆盖”,它只管覆盖代码中的执行语句,却不考虑各种分支的组合等等。假如你的上司只要求你达到语句覆盖,那么你可以省下很多功夫,但是,换来的确实测试效果的不明显,很难更多地发现代码中的问题。
这里举一个不能再简单的例子,我们看下面的被测试代码:
int foo(int a, int b)
{
return a / b;
}
假如我们的测试人员编写如下测试案例:
TeseCase: a = 10, b = 5
测试人员的测试结果会告诉你,他的代码覆盖率达到了100%,并且所有测试案例都通过了。然而遗憾的是,我们的语句覆盖率达到了所谓的100%,但是却没有发现最简单的Bug,比如,当我让b=0时,会抛出一个除零异常。
正因如此,假如上面只要求测试人员语句覆盖率达到多少的话,测试人员只要钻钻空子,专门针对如何覆盖代码行编写测试案例,就很容易达到主管的要求。当然了,这同时说明了几个问题:
1.主管只使用语句覆盖率来考核测试人员本身就有问题。
2.测试人员的目的是为了测好代码,钻如此的空子是缺乏职业道德的。
3.是否应该采用更好的考核方式来考核测试人员的工作?
为了寻求更好的考核标准,我们必须先了解完代码覆盖率到底还有哪些,如果你的主管只知道语句覆盖,行覆盖,那么你应该主动向他介绍还有更多的覆盖方式。比如:
2. 判定覆盖(DecisionCoverage)
又称分支覆盖(BranchCoverage),所有边界覆盖(All-EdgesCoverage),基本路径覆盖(BasicPathCoverage),判定路径覆盖(Decision-Decision-Path)。它度量程序中每一个判定的分支是否都被测试到了。这句话是需要进一步理解的,应该非常容易和下面说到的条件覆盖混淆。因此我们直接介绍第三种覆盖方式,然后和判定覆盖一起来对比,就明白两者是怎么回事了。
3. 条件覆盖(ConditionCoverage)
它度量判定中的每个子表达式结果true和false是否被测试到了。为了说明判定覆盖和条件覆盖的区别,我们来举一个例子,假如我们的被测代码如下:
int foo(int a, int b)
{
if (a < 10 || b < 10) // 判定
{
return 0; // 分支一
}
else
{
return 1; // 分支二
}
}
设计判定覆盖案例时,我们只需要考虑判定结果为true和false两种情况,因此,我们设计如下的案例就能达到判定覆盖率100%:
TestCaes1: a = 5, b = 任意数字 覆盖了分支一
TestCaes2: a = 15, b = 15 覆盖了分支二
设计条件覆盖案例时,我们需要考虑判定中的每个条件表达式结果,为了覆盖率达到100%,我们设计了如下的案例:
TestCase1: a = 5, b = 5 true, true
TestCase4: a = 15, b = 15 false, false
通过上面的例子,我们应该很清楚了判定覆盖和条件覆盖的区别。需要特别注意的是:条件覆盖不是将判定中的每个条件表达式的结果进行排列组合,而是只要每个条件表达式的结果true和false测试到了就OK了。因此,我们可以这样推论:完全的条件覆盖并不能保证完全的判定覆盖。比如上面的例子,假如我设计的案例为:
TestCase1: a = 5, b = 15 true, false 分支一
TestCase1: a = 15, b = 5 false, true 分支一
我们看到,虽然我们完整的做到了条件覆盖,但是我们却没有做到完整的判定覆盖,我们只覆盖了分支一。上面的例子也可以看出,这两种覆盖方式看起来似乎都不咋滴。我们接下来看看第四种覆盖方式。
4. 路径覆盖(PathCoverage)
又称断言覆盖(PredicateCoverage)。它度量了是否函数的每一个分支都被执行了。 这句话也非常好理解,就是所有可能的分支都执行一遍,有多个分支嵌套时,需要对多个分支进行排列组合,可想而知,测试路径随着分支的数量指数级别增加。比如下面的测试代码中有两个判定分支:
int foo(int a, int b)
{
int nReturn = 0;
if (a < 10)
{// 分支一
nReturn += 1;
}
if (b < 10)
{// 分支二
nReturn += 10;
}
return nReturn;
}
对上面的代码,我们分别针对我们前三种覆盖方式来设计测试案例:
a. 语句覆盖
TestCase a = 5, b = 5 nReturn = 11
语句覆盖率100%
b. 判定覆盖
TestCase1 a = 5, b = 5 nReturn = 11
TestCase2 a = 15, b = 15 nReturn = 0
判定覆盖率100%
c. 条件覆盖
TestCase1 a = 5, b = 15 nReturn = 1
TestCase2 a = 15, b = 5 nReturn = 10
条件覆盖率100%
我们看到,上面三种覆盖率结果看起来都很酷!都达到了100%!主管可能会非常的开心,但是,让我们再去仔细的看看,上面被测代码中,nReturn的结果一共有四种可能的返回值:0,1,10,11,而我们上面的针对每种覆盖率设计的测试案例只覆盖了部分返回值,因此,可以说使用上面任一覆盖方式,虽然覆盖率达到了100%,但是并没有测试完全。接下来我们来看看针对路径覆盖设计出来的测试案例:
TestCase1 a = 5, b = 5 nReturn = 0
TestCase2 a = 15, b = 5 nReturn = 1
TestCase3 a = 5, b = 15 nReturn = 10
TestCase4 a = 15, b = 15 nReturn = 11
路径覆盖率100%
太棒了!路径覆盖将所有可能的返回值都测试到了。这也正是它被很多人认为是“最强的覆盖”的原因了。
还有一些其他的覆盖方式,如:循环覆盖(LoopCoverage),它度量是否对循环体执行了零次,一次和多余一次循环。剩下一些其他覆盖方式就不介绍了。
总结
通过上面的学习,我们再回头想想,覆盖率数据到底有多大意义。我总结了如下几个观点,欢迎大家讨论:
a. 覆盖率数据只能代表你测试过哪些代码,不能代表你是否测试好这些代码。(比如上面第一个除零Bug)
b. 不要过于相信覆盖率数据。
c. 不要只拿语句覆盖率(行覆盖率)来考核你的测试人员。
d. 路径覆盖率 > 判定覆盖 > 语句覆盖
e. 测试人员不能盲目追求代码覆盖率,而应该想办法设计更多更好的案例,哪怕多设计出来的案例对覆盖率一点影响也没有。
作者:CoderZh(CoderZh的技术博客 - 博客园)
微博:http://t.sina.com.cn/coderzh
出处:http://coderzh.cnblogs.com
文章地址:http://www.cnblogs.com/coderzh/archive/2009/03/29/1424344.html
分享到:
相关推荐
在Windows平台上进行C/C++开发时,代码覆盖率检查是一个重要的质量保证步骤,它能帮助开发者了解测试用例对源代码的覆盖程度。代码覆盖率通常包括行覆盖率、分支覆盖率等指标,能够评估测试的有效性,确保代码的健壮...
在Android开发中,JaCoCo是一个非常重要的工具,它用于计算和分析代码覆盖率,帮助开发者了解测试用例对代码的覆盖程度。JaCoCo不仅适用于Java项目,而且在Android项目中同样发挥着关键作用,尤其是在确保测试质量、...
代码覆盖率工具是软件开发过程中的重要辅助手段,主要用于评估测试代码对源代码的覆盖程度。在Java开发环境中,为了确保代码质量,单元测试是必不可少的环节。而代码覆盖率工具则可以帮助开发者了解测试用例对程序...
单元测试的代码覆盖率至少80%!一大早,一个年轻的程序员问大师:“我准备写一些单元测试用例。代码覆盖率应该达到多少为好?”大师回答道:“不要考虑代码覆盖率,只要写出一些好的测试用例即可。” 一大早,一个...
测试代码覆盖率是软件开发过程中的一个重要环节,它用于衡量测试用例执行时对源代码的覆盖程度。在标题中提到的“测试代码覆盖率”是指通过自动化测试来确定多少比例的代码被执行过,这对于确保软件质量、查找未被...
代码覆盖率驱动的测试是一种软件测试方法,其核心目标是通过测量代码执行过程中的覆盖率来指导测试活动,确保测试用例尽可能多地覆盖代码中的各种执行路径。代码覆盖率反映了在测试过程中执行到的代码行数与总代码...
**代码覆盖率Eclipse插件详解** 在软件开发过程中,代码覆盖率是衡量测试质量的一个重要指标。它能够帮助开发者了解测试代码对源代码的覆盖程度,从而确保代码的健壮性和可靠性。Eclipse作为一款广泛使用的Java集成...
"使用工具查看RTL代码覆盖率" 在数字芯片开发中,Verilog是一种常用的 Hardware Description Language(HDL),用于描述数字电路的行为。RTL(Register-Transfer Level)代码是Verilog的一个重要组成部分,用于描述...
lcov是一种广泛使用的工具,主要用于收集和生成C和C++项目的代码覆盖率报告。它与genhtml工具一起工作,提供了一种直观的方式来理解程序中的哪些部分被执行了,以及哪些部分未被执行,这对于软件测试和质量保证至关...
首先,代码覆盖率是衡量软件测试完整性的一个重要指标,它反映了测试用例执行时覆盖了多少源代码。对于C++代码,Android NDK提供了一种基于Clang的解决方案。Clang是LLVM项目的一部分,不仅是一个高效的C/C++/...
【基于Jacoco的代码覆盖率实时监控与精准测试实践】 在软件开发过程中,代码覆盖率是评估测试有效性的重要指标,它能够帮助我们了解测试用例对代码的覆盖程度。Jacoco是一款广泛使用的Java代码覆盖率工具,它提供了...
在软件开发过程中,代码覆盖率是一个至关重要的指标,它反映了测试用例对源代码的覆盖程度。本文将深入探讨“Super-jacoco”工具如何应用于统计代码覆盖率,并解决在此过程中可能遇到的问题。 首先,我们需要理解...
"在实时服务器上生成代码覆盖率报告"这一主题聚焦于一个实用的技术实践,即在服务器环境中实时监控和分析代码执行情况,从而获取代码覆盖率数据。这种做法有助于开发者了解测试覆盖的程度,发现未被测试到的代码区域...
而代码覆盖率则是衡量单元测试有效性的一个关键指标,它表示了被测试代码被执行的程度。JaCoCo是一款广泛使用的Java代码覆盖率工具,它可以方便地集成到各种构建工具和持续集成系统中,提供详细的覆盖率报告。 ...
EclEmma是一款强大的Java单元测试代码覆盖率工具,它为开发者提供了直观的方式来衡量和评估他们的单元测试的质量。在软件开发过程中,单元测试是确保代码正确性和可靠性的关键步骤,而EclEmma则帮助开发者确保测试...
【马可代码覆盖率平台】是专门针对前端质量监控和优化的一款工具,旨在解决在互联网技术开发过程中遇到的挑战,如代码冗余、测试覆盖率不足、自动化测试成本高等问题。该平台在2021年vivo开发者大会上被提及,特别...
Java代码覆盖率工具包Java代码覆盖率工具包Java代码覆盖率工具包Java代码覆盖率工具包Java代码覆盖率工具包Java代码覆盖率工具包Java代码覆盖率工具包Java代码覆盖率工具包Java代码覆盖率工具包Java代码覆盖率工具包...
Emma 进行代码覆盖率检查(命令行方式) Emma 是一款 Java 代码覆盖率检查工具,可以帮助开发者了解代码的覆盖率情况,从而提高代码的质量。在 Offline 模式下使用 Emma 进行代码覆盖率检查需要经过三个步骤:插桩...
Java代码覆盖率测试是软件开发过程中一个重要的质量保证环节,它能帮助开发者了解代码在测试中的执行情况,确保更多的代码被有效的测试覆盖。Clover是一款由Atlassian公司开发的高级代码覆盖率工具,它提供了详细的...