《Unit Testing》1.3 使用覆盖率指标来度量测试套件的好坏

使用覆盖率来度量测试套件(Test Suite)的质量

有两种比较流行的测试覆盖率的度量方法:

  • 代码覆盖率

  • 分支覆盖率

覆盖率度量会显示一个测试套件(Test Suite)会执行多少代码,范围从 0 100%

除了上述两种方法之外,还有很多其它的度量方法。它们都是被用来评估一个测试套件的质量的。

 

通常人们会认为,这个覆盖率越高越好。不幸的是,这没那么简单,覆盖率度量确实能提供非常有价值的反馈,但是它们无法有效的评估出测试套件的质量。这一点与代码可进行单元测试的能力一样:覆盖率度量是一个非常好的负向指示(能评估出测试套件是否较差),但它无法评估出测试套件是否很好。

 

代码覆盖率度量

第一种,也是使用最多的度量方式就是代码覆盖率(code coverage,也叫测试覆盖率 test coverage)。它的公式如下:

 

 

例如:

 

 

该测试对上面的有效代码(共 5 行,89101213)的覆盖率达到了 80%891213)。

 

如果我重构一下代码,如下图所示呢:

可以看到有效代码行数变成了 3 行(8910),它们都是绿色,说明都被覆盖了。从工具也可以看到覆盖率变成了 100%

 

所以,代码覆盖率确实变化了,达到了 100%。但是测试套件的质量提高了吗?当然没有,我只是在方法内部重新罗列了一下代码,而测试仍然只验证了相同数量的可能结果。

 

分支覆盖率度量

另一种覆盖率度量方法是分支覆盖率。其公式如下:

 

 

想要使用复制覆盖率,你得想办法把代码里所有可能的分支求和,然后再检测测试走了多少分支。

 

例子:

还是之前的例子,IsStringLong 方法里面一共有两种情况,也就是两个分支。而测试只会运行小于等于 5 这种情况,所以分支覆盖率为 50%

 

注意:分支覆盖率里面只考虑分支数量,并不考虑所执行的代码行数。

 

覆盖率度量的问题

尽管分支覆盖率的结果比代码覆盖率更有用一些,但是仍然无法依赖它们中的任何一个来决定测试套件的质量:

  • 无法保证测试会验证被测试系统SUT,System Under Test)所有可能的结果

  • 没有一种覆盖率度量法可以测试外部库的代码路径

 

为了让代码路径真正被测试,而不仅仅是路过执行,单元测试必须有适当的断言。

 

例子:

这段代码其实产生了两个结果,分别是 13 15 行,只有第 15 行的结果被测试了,而第 13 行的结果(第 7 行的属性)并没有被验证。

而两种测试覆盖率的结果仍然没有变化,还是 100% 50%

所以说,覆盖率度量无法保证代码会被测试,只能保证代码会被执行而已。

 

但是,如果你确实考虑了每种可能,同时结合分支覆盖率,那么是否能够提供一个可靠的机制,来判断测试套件的质量呢?很不幸,不能。

因为没有任何覆盖率度量方法能考虑外部库中的代码路径。

 

例如:

这个测试里,分支覆盖率达到了 100%,但是它没考虑 .NET 提供的 int.Parse 这个方法的可能结果。对于 int.Parse 至少有以下几种可能:

而我们只考虑了其中一种。所以您可能会遇到许多极端情况,并且无法查看测试是否将所有情况都考虑在内。

 

这并不是说覆盖率度量应该考虑外部库的代码路径(它们不应该),而是说明你不能指望这些度量来评估单元测试的质量好坏。覆盖率度量无法判断您的测试是否详尽无遗; 也不能说明是否有足够的测试。

 

特定的覆盖率数字

要把覆盖率度量当成一个指标,而不是一个目标。

就如同生病住院的病人,体温高可能表示发烧,它是一个有用的观察。但是医院不能把不择手段降低病人的体温当成治病的目标。

 

通常,如果系统核心某块的测试的覆盖率较高的话是很好的,但是如果把高覆盖率当成目标就不好了。

 

就个人而言:我认为覆盖率低于 60% 肯定不好,这说明有大量的代码未测试。但是更高的覆盖率数字并不能代表什么。所以度量覆盖率只是验证测试套件质量的第一步而已。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值