0 覆盖率定义
作为一个测试人员,保证产品的软件质量是其工作首要目标,为了这个目标,测试人员常常会通过很多手段或工具来加以保证,覆盖率就是其中一环比较重要的环节。
我们通常会将测试覆盖率分为两个部分,即“需求覆盖率”和“代码覆盖率”。
需求覆盖:指的是测试人员对需求的了解程度,根据需求的可测试性来拆分成各个子需求点,来编写相应的测试用例,最终建立一个需求和用例的映射关系,以用例的测试结果来验证需求的实现,可以理解为黑盒覆盖。
代码覆盖:为了更加全面的覆盖,我们可能还需要理解被测程序的逻辑,需要考虑到每个函数的输入与输出,逻辑分支代码的执行情况,这个时候我们的测试执行情况就以代码覆盖率来衡量,可以理解为白盒覆盖。
以上两者完全可以相辅相成,用代码覆盖结果反向的检查需求覆盖(用例)的测试是否充分完整。
java中比较流行的代码覆盖率工具有EMMA,Cobertura,jacoco等。其实以现在情况来看,使用jacoco的人群是比较多的,有点大势所趋的感觉。
1 EMMA
本来以前用EMMA的人很多,但是开发这个工具的坑爹团队自从2006年后就再也没更新过了
可以理解为EMMA已die。
- maven 仓库也没啥更新了
- 以后肯定会被淘汰的
不过EMMA使用起来确实太简单了,新手首选。
通过查询古籍,发现此前 IDEA 也是支持的,现在已不再支持.
1.1 maven 集成
java项目大多都是用maven管理的,如果我们想统计单元测试的覆盖率的话,通过emma与maven集成是最简单不过的。不像jacoco那么麻烦,配置emma十分简单。只需要添加如下依赖:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>emma-maven-plugin</artifactId> <version>1.0-alpha-3</version> <inherited>true</inherited> </plugin>
然后运行命令:mvn emma:emma。 之后你就可以看report了
1.2 与jenkins集成
如果你使用jenkins作为CI的工具的话,其实就更简单了。你都不用再pom文件中增加依赖,安装好EMMA的插件以后,直接运行上面的例子的命令就好了。
1.3 插桩
上面介绍的都只能统计项目本身的测试,也就是在工程中的src/test/java包下面的测试脚本。如果是我们的接口测试,UI测试呢?我们怎么做才能统计代码覆盖率呢?这就需要一些手段了。
首先,你需要从官网中下载emma.jar到你的测试环境中,然后copy到你的jre的ext文件夹中。这样就是扩展了java命令,以后你就可以直接以java emma的形式执行操作了。
然后你需要对被测的包进行插桩。然后emma会开启一个服务,默认端口47653。这个服务就会监控被测的工程了。插桩的例子如下。具体的命令参数大家参照官网就好。
java emma instr -m overwrite -cp simba-1.0.jar -out coverage.em
最后就是收集报告了。这里需要两个命令,一个是收集数据,一个是生成报告。例子如下。着重说一下几个参数。-sp是你源代码的路径,这样emma才能获取代码信息展示更详细的报告。-in是生成报告需要的元数据信息。是在插桩和收集数据生成的中间文件。-r是report的格式。这几个参数是常用的。
java emma ctl -connect localhost:47653 -command coverage.get,coverage.ec java emma report -r html -Dreport.out.encoding=utf-8 -sp /opt/web/simba/src/main/java -in coverage.em,coverage.ec
只要你不删除插桩和收集数据所产生的元数据文件的话。你都可以累计的生成报告。还有一个merge模式可以合并报告,详细的东西大家可以去官网看一下。EMMA的好处就是使用简单。最后我发一个生成的报告的图吧。
坑
EMMA有一个坑就是在jdk1.6以上的版本有可能出现一个问题,插桩之后运行会出现一个classformat异常。提示你参数数量不正确,大概是这个意思吧。其实这是jdk在1.7以后使用的验证器不一样了。而EMMA这个坑爹货太久没有更新了,根本没cover到新版本的JDK。所以需要我们在启动jvm的时候增加一个参数。-XX:-UseSplitVerifier。这样就可以了。这个坑当时着实坑了我俩小时。
总结
即使达到100%的覆盖率也不能保障你的产品质量
但是覆盖率过低的产品的质量一定是不能被保障的
真正重视代码覆盖率,把它加入到质量保证的流程中。否则很容易变成摆设
提高测试人员的代码水平,熟悉产品代码。否则也容易变成摆设
不要妄图做到100%,那不可能。
保持一个覆盖率的平衡:单元测试50%70%,接口20%40%,UI10%
尽可能劝说开发人员写单元测试。越是底层的测试,实现覆盖的成本越低。妄图在测试人员这边达到高覆盖率几乎是不可能的
如果没有单元测试。尽量在接口测试中提高覆盖率
2 jacoco
jacoco就是 EMMA 的团队开发的 他们已经全部转向jacoco
JaCoCo优势
- JaCoCo支持分支覆盖、引入了Agent
- EMMA官网已经不维护了,JaCoCo是其团队开发的,可以理解为一个升级版
- JaCoCo社区比较活跃,github 上也在不断的维护更新
- 它针对的开发语言是java,其使用方法很灵活,可以嵌入到Ant、Maven中;可以作为Eclipse插件,可以使用其JavaAgent技术监控Java程序等等。
很多第三方的工具提供了对JaCoCo的集成,如sonar、Jenkins等。
JaCoCo包含了多种尺度的覆盖率计数器,包含指令级覆盖(Instructions,C0coverage),分支(Branches,C1coverage)、圈复杂度(CyclomaticComplexity)、行覆盖(Lines)、方法覆盖(non-abstract methods)、类覆盖(classes)
JaCoCo基本概念
行覆盖率:度量被测程序的每行代码是否被执行,判断标准行中是否至少有一个指令被执行。
类覆盖率:度量计算class类文件是否被执行。
分支覆盖率:度量if和switch语句的分支覆盖情况,计算一个方法里面的
总分支数,确定执行和不执行的 分支数量。
方法覆盖率:度量被测程序的方法执行情况,是否执行取决于方法中是否有至少一个指令被执行。
指令覆盖:计数单元是单个java二进制代码指令,指令覆盖率提供了代码是否被执行的信息,度量完全 独立源码格式。
圈复杂度:在(线性)组合中,计算在一个方法里面所有可能路径的最小数目
JaCoCo 原理
只针对 class 文件,并不需要源文件
注入方式
JaCoCo在Byte Code时使用的ASM技术修改字节码方法,可以修改Jar文件、class文件字节码文件。
JaCoCo同时支持on-the-fly和offline的两种插桩模式
On-the-fly插桩:
JVM中通过-javaagent参数指定特定的jar文件启动Instrumentation的代理程序,代理程序在通过Class Loader装载一个class前判断是否转换修改class文件,将统计代码插入class,测试覆盖率分析可以在JVM执行测试代码的过程中完成。
Offline模式:
在测试前先对文件进行插桩,然后生成插过桩的class或jar包,测试插过桩 的class和jar包后,会生成动态覆盖信息到文件,最后统一对覆盖信息进行处理,并生成报告。
On-the-fly和offline比较:
On-the-fly模式更方便简单进行代码覆盖分析,无需提前进行字节码插桩,无需考虑classpath 的设置。
存在如下情况不适合on-the-fly,需要采用offline提前对字节码插桩:
(1)运行环境不支持java agent。
(2)部署环境不允许设置JVM参数。
(3)字节码需要被转换成其他的虚拟机如Android Dalvik VM。
(4)动态修改字节码过程中和其他agent冲突。
(5)无法自定义用户加载类。
JaCoCo执行最小需要Java5
JaCoCo通过注入来修改和生成java字节码,使用的是ASM库。
使用
ant
不再赘述
maven 项目插件
这种方式适合Maven的项目。
调用流程:
(1) 项目已jar包方式打包,引入junit和jacoco。
(2) Build时执行instrument、report、check。
(3) 覆盖率生成到target/jacoco.exec
3 总结
推荐链接
http://openclover.org/doc/manual/latest/general–comparison-of-code-coverage-tools.html
参考
https://cloud.tencent.com/developer/article/1038055