今天在家翻了翻以前的文档,偶然看到了以前用 emma 统计代码覆盖率时总结的一些东西。便突然有了兴致来讨论一下。相信大家都知道有 code coverage 这东西,也研究过。 但大部分公司基本都没有使用 code coverage 或者 code coverage 变成了没什么卵用的 KPI 产物。我总结了一下如果你想最大的发挥 code coverage 这种策略的威力,需要做的几个比较重要的点。
再讲这些点之前,我们讨论一下 code coverage 能带来什么好处吧。
想搞代码覆盖率,第一个前提是你的项目有能力用自动化的方式把覆盖率提高到一个量级。额,这个应该是个共识吧,除非你人力多到没地方用了。
为了实现高覆盖率,必须要有单元测试。实际上,提升覆盖率的主力就是在单元测试这边。如果项目中的开发人员没有编写单元测试的习惯的话,几乎是注定了在覆盖率方面有很大的缺陷了。从实现成本上看,单元测试的 mock 技术是提高覆盖率的不二利器。想只靠测试人员在接口和 UI 级别将覆盖率提高到一定量级是需要极其庞大的成本的。而且有很多逻辑在测试环境中是根本覆盖不了的,所以我们才需要 mock。《Google 软件测试之道》一书中推荐的单元测试的覆盖率在 50%~70% 之间,可惜实际上我没听过几个国内的公司能再单元测试上把覆盖率提高到这个份上
导致代码覆盖率变成 KPI 产物的最大一个原因就是测试人员不熟悉产品代码,甚至根本看不懂覆盖率报告。这样根本无法根据报告补充 case,定位 bug。 代码覆盖率也就变成了摆设。
java 中比较流行的代码覆盖率工具有 EMMA,Cobertura,jacoco 等。其实以现在情况来看,使用 jacoco 的人群是比较多的,有点大势所趋的感觉。本来以前用 EMMA 的人很多,但是开发这个工具的坑爹团队自从 2005 年以后就再也没更新过了。可以理解为 EMMA 已经是一个 dead project。但是我从以前就再用 EMMA,所以也一直没换,反正能满足需求就行了。至于到底哪个工具更高大上,我倒不是很在意。不过我还是建议刚搞代码覆盖率的同学直接去搞 jacoco 吧。毕竟 EMMA 都停止更新了,以后肯定会被淘汰的。不过其实所有代码覆盖率的原理都是差不多的,我们说一下 EMMA 的使用也并无不可,而且说实话 EMMA 使用起来确实太简单了,新手首选。
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 了
如果你使用 jenkins 作为 CI 的工具的话,其实就更简单了。你都不用再 pom 文件中增加依赖,安装好 EMMA 的插件以后,直接运行上面的例子的命令就好了。
上面介绍的都只能统计项目本身的测试,也就是在工程中的 src/test/java 包下面的测试脚本。如果是我们的接口测试,UI 测试呢?我们怎么做才能统计代码覆盖率呢?这就需要一些手段了。
java emma instr -m overwrite -cp simba-1.0.jar -out coverage.em
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 的好处就是使用简单。最后我发一个生成的报告的图吧。
OK 就说这么多吧。想把代码覆盖率利用起来真的很难。因为遇到的都是非技术性原因。劝说开发写单元测试,劝说老大把覆盖率加入到质量流程中,劝说产品和其他 QA 关注覆盖率等等。这些哪一个都不容易。即便过了这几关你还要为了提高覆盖率做很大的努力。毕竟项目不会再一开始就开展自动化测试。等自动化测试人员加入到项目中的时候,没准已经遗留了成百上千的接口。这个技术债可能需要以年为单位去还。大家努力吧。
EMMA 有一个坑就是在 jdk1.6 以上的版本有可能出现一个问题,插桩之后运行会出现一个 classformat 异常。提示你参数数量不正确,大概是这个意思吧。其实这是 jdk 在 1.7 以后使用的验证器不一样了。而 EMMA 这个坑爹货太久没有更新了,根本没 cover 到新版本的 JDK。所以需要我们在启动 jvm 的时候增加一个参数。-XX:-UseSplitVerifier。这样就可以了。这个坑当时着实坑了我俩小时。