Code Coverage
我们平时开发过程中,有多少同学有纠结过这些问题:
- 我们写的代码或功能,测试同学有没有测试过呢?
- 测试同学是否把所有case都跑过了呢?
- 测试同学有没有漏测了什么功能呢?
- 我们设计的代码有没有多余的?
其实这些疑问不是怀疑自己或他人的工作能力,只是我们希望自己的代码能够被全部测试,从而不会出现线上的故障,一个体量庞大的App若在线上出现一个故障,影响面有多广可想而知。
像之前苹果没有封杀热修复的时候,若我们的代码覆盖率能够做到100%(假设,虽然很难),那么热修复就没有那么的重要了,甚至可以说没有必要了。
代码覆盖是软件测试中的一种度量,描述程式中源代码被测试的比例和程度,所得比例称为代码覆盖率。
常用度量方式
- 函数覆盖率(Function coverage)
- 语句覆盖率(Statement coverage):又称行覆盖
- 判断覆盖率(Decision coverage)
- 条件覆盖率(Condition coverage)
- 路径覆盖率(Path Coverage)
举个例子
1.函数覆盖与语句覆盖,应该很好理解,函数覆盖就是这个函数有没有被调用过;语句/行覆盖就是这行有没有被调用过
2.判断覆盖:这个很容易与下面的条件覆盖弄混淆
func add(int a , int b) { if (a < 15 || b > 20) { print('a'); } } //test case //a = 5, b = 10 //其实不管a与b是什么值,这个if判断都会执行,所以这个判断覆盖率是100%
3.条件覆盖:使用上面同一个add函数
//test case 1 //a = 5, b = 10 因为a小于15已经成立,不管b是什么值,都会打印a,b的判断不会被执行,所以此时条件覆盖率只有50% //test case 2 //a = 15, b = 30 此时2个判断都会被执行,所以此时条件覆盖率是100%
4.路径覆盖率:这个也比较好理解,代表这个函数内所有是否都被执行过,还是以上面的add函数为例
这个函数总共有4条路径,想要达到100%覆盖率,那么就需要4个测试用例
- a = 5, b = 5
- a = 30, b = 5
- a = 30, b = 30
- a = 5, b = 30
这样才能达到100%的路径覆盖率
覆盖率高低
代码被测试覆盖了,并不能代表这个代码是无缺陷的,也不能代表这个代码被测试完成了,所以我们不能以是否覆盖也考量测试的质量,覆盖率高≠测试质量好,覆盖率低≠测试质量不好
路径覆盖率 > 判定覆盖 > 语句覆盖
虽说不能太相信覆盖率数据,但至少可以作为一个参考,下来我们来看看一个iOS工程如何实现覆盖率统计。
XCode & Coverage
在XCode 7上,支持了Code Coverage
覆盖率场景
- 单元测试覆盖率:统计case的覆盖率
- 远程多设备测试覆盖率:大量测试设备将覆盖统计汇总,生成一份总的覆盖率报告
今天我们这两种场景都会介绍一下,单测相对简单,负责的远程统计分析,也是本章的重点。
单元测试覆盖率
首先开启覆盖率:Edit Scheme -> Test -> Options -> Code Coverage for xxx (这个xxx可以自行配置需要的target)
我们来写一个简单的UnitCase,先创建一个CoverageManager
#import "CoverageManager.h" @implementation CoverageManager - (instancetype)init { self = [super init]; if (self) { } return self; } - (void)test { NSLog(@"test execute"); } @end
然后写一个Case,执行
执行成功后,在Show The Report里面可以看到如下
点击Coverage就可以看到本次Case的覆盖情况(如果需要看所有case的覆盖情况,就执行 Product -> Test)
OK,单元测试的覆盖率是不是很简单,不过它缺点很明显,只能在本机执行Case的时候才能看到报告,也只能统计单测的覆盖了,对于客户端而言,可能更多的是关注提测后代码的测试覆盖率,下一章节就来重点来讲讲远程多端测试覆盖率