技术开发 频道

代码覆盖率浅谈

  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. 测试人员不能盲目追求代码覆盖率,而应该想办法设计更多更好的案例,哪怕多设计出来的案例对覆盖率一点影响也没有。

0
相关文章