Java代码覆盖率历史发展轨迹

2020-05-27 10:01:59 浏览数 (1)

目录

  • 0 覆盖率定义
  • 1 EMMA
    • 1.1 maven 集成
    • 1.2 与jenkins集成
    • 1.3 插桩
  • 总结
  • 2 jacoco
    • JaCoCo优势
    • JaCoCo基本概念
    • JaCoCo 原理
      • 注入方式
    • JaCoCo同时支持on-the-fly和offline的两种插桩模式
      • On-the-fly插桩:
      • Offline模式:
      • On-the-fly和offline比较:
    • 使用
      • ant
      • maven 项目插件
  • 3 总结
  • 参考

0 覆盖率定义

作为一个测试人员,保证产品的软件质量是其工作首要目标,为了这个目标,测试人员常常会通过很多手段或工具来加以保证,覆盖率就是其中一环比较重要的环节。

我们通常会将测试覆盖率分为两个部分,即“需求覆盖率”和“代码覆盖率”。

  • 需求覆盖:指的是测试人员对需求的了解程度,根据需求的可测试性来拆分成各个子需求点,来编写相应的测试用例,最终建立一个需求和用例的映射关系,以用例的测试结果来验证需求的实现,可以理解为黑盒覆盖。
  • 代码覆盖:为了更加全面的覆盖,我们可能还需要理解被测程序的逻辑,需要考虑到每个函数的输入与输出,逻辑分支代码的执行情况,这个时候我们的测试执行情况就以代码覆盖率来衡量,可以理解为白盒覆盖。

以上两者完全可以相辅相成,用代码覆盖结果反向的检查需求覆盖(用例)的测试是否充分完整。

java中比较流行的代码覆盖率工具有EMMA,Cobertura,jacoco等。其实以现在情况来看,使用jacoco的人群是比较多的,有点大势所趋的感觉。

1 EMMA

本来以前用EMMA的人很多,但是开发这个工具的坑爹团队自从2006年后就再也没更新过了

可以理解为EMMA已die。

  • maven 仓库也没啥更新了

以后肯定会被淘汰的 不过EMMA使用起来确实太简单了,新手首选。 通过查询古籍,发现此前 IDEA 也是支持的,现在已不再支持.

1.1 maven 集成

java项目大多都是用maven管理的,如果我们想统计单元测试的覆盖率的话,通过emma与maven集成是最简单不过的。不像jacoco那么麻烦,配置emma十分简单。只需要添加如下依赖:

代码语言:javascript复制
<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。这个服务就会监控被测的工程了。插桩的例子如下。具体的命令参数大家参照官网就好。

代码语言:javascript复制
java emma instr -m overwrite -cp simba-1.0.jar -out coverage.em

最后就是收集报告了。这里需要两个命令,一个是收集数据,一个是生成报告。例子如下。着重说一下几个参数。-sp是你源代码的路径,这样emma才能获取代码信息展示更详细的报告。-in是生成报告需要的元数据信息。是在插桩和收集数据生成的中间文件。-r是report的格式。这几个参数是常用的。

代码语言:javascript复制
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%,那不可能。
  • 保持一个覆盖率的平衡:单元测试50p%,接口20@%,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

0 人点赞