【测试】代码覆盖率工具 JaCoCo

JaCoCo 是面向 Java 的开源代码覆盖率工具,JaCoCo 以 Java 代理模式运行,它负责在运行测试时检测字节码。JaCoCo 会深入研究每个指令,并显示每个测试过程中要执行的行。为了收集覆盖率数据,JaCoCo 使用 ASM 即时进行代码检测,并在此过程中从 JVM Tool Interface 接收事件,最终生成代码覆盖率报告。

在这里插入图片描述
JaCoCo 运行有 离线offline)、在线on the fly)模式之说,所谓在线模式就是在应用启动时加入 jacoco agent 进行 插桩,在开发、测试人员使用应用期间实时地进行代码覆盖率分析。相信很多的 Java 项目开发人员并不会去写单元测试代码的,因此覆盖率统计就要把手工测试或接口测试覆盖的情况作为重要依据,显然在线模式更符合实际需求,本文以在线模式为例进行演示。

1.Jacoco 安装

官网下载最新版本并解压到指定目录。

在这里插入图片描述

主要用到如下两个 jar 包:

在这里插入图片描述
在线模式 Jacoco 覆盖率统计包含三个步骤:

  • 启动应用增加 jacoco agent 进行插桩,该步骤会启动 TCP Server。
  • 从 TCP Server dump 生成代码覆盖率文件,生成的文件格式为 .exec 格式的二进制文件。
  • 解析 .exec 格式文件生成 html 格式代码覆盖率报告。

2.准备 Java 示例代码

事先需要创建 Java 示例代码,本文不聚焦 Java 代码相关的内容,大家可以使用自己的 Java 项目代码进行验证,或者直接 clone 本文提供的 Spring Boot 示例代码仓库:https://gitee.com/pepperpapa/jacoco_demo

注意:在线模式使用的代码一定要是类似 Web 应用这种永远不会退出的程序为例,因为收集 jacoco agent 要启用 TCP Server,如果程序执行完就退出了 TCP Server 也就无法关闭了。

在这里插入图片描述

示例代码就是提供两个简单的 URL 访问,访问截图如下:

  • http://127.0.0.1:8080/hello
    在这里插入图片描述
  • http://127.0.0.1:8080/byebye
    在这里插入图片描述

执行构建命令 mvn clean package 后,会在 target 目录生成可运行的 jar 包。

在这里插入图片描述

3.启动 jacoco agent 进行插桩

打开 cmdcd 到示例代码的 target 目录,执行如下命令:

java -javaagent:C:\工具\jacoco-0.8.6\lib\jacocoagent.jar=includes=*,output=tcpserver,port=6300,address=localhost,append=true -jar demo-0.0.1-SNAPSHOT.jar

关键参数说明:

  • -javaagent:C:\工具\jacoco-0.8.6\lib\jacocoagent.jar=includes=*,这个参数就是启用 Jacoco 代理参数,其中 C:\工具\jacoco-0.8.6\lib\jacocoagent.jar 就是之前下载 Jacoco 解压后的 jacocoagent.jar 的绝对路径,includes 表示对要插桩的包进行过滤,* 代表所有的 class 都要进行插桩,也可以根据情况进行过滤,如 includes=com.mycompany.*
  • output=tcpserver,这里不需要改动,表示以 TCP Server 方式启动应用并插桩。
  • port=6300,Jacoco 开启的 TCP Server 的端口,不能被占用。
  • address=localhost,对外开放的地址,也可以指定 IP 地址。
  • demo-0.0.1-SNAPSHOT.jar,就是示例代码构建后 target 目录生成的 jar 包,需要根据实际情况更新。

执行后就会启动 Web 服务,截图如下:

在这里插入图片描述

特别提醒:为了对比实时统计代码覆盖率的效果,此时请先不要请求上面提到的任何一个 URL,切记!

4.dump 生成覆盖率文件

保持服务启动,再打开一个 cmd 窗口同样 cdtarget 目录,执行如下命令从上一步开启的 TCP Server 中 dump 出覆盖率文件:

java -jar C:\工具\jacoco-0.8.6\lib\jacococli.jar dump --address localhost --port 6300 --destfile ./jacoco_tcp_01.exec

参数说明:

  • --destfile ./jacoco_tcp.exec,其中 ./jacoco_tcp.exec 为生成 exec 文件名,表示在当前目录生成。
  • 其他参数和上一步类似,不再特别说明,注意需要更新 jacococli.jar 的绝对路径。

执行成功后,会在 target 目录生成相应的 .exec 文件。

在这里插入图片描述
接下来,我们在浏览器中访问该web示例应用提供的两个 URL,http://127.0.0.1:8080/hellohttp://127.0.0.1:8080/byebye,应用会调用相应的方法并正常返回结果。

然后,我们再次执行 dump 命令再生成一个 .exec 文件,命名为 jacoco_tcp_02.exec

java -jar C:\工具\jacoco-0.8.6\lib\jacococli.jar dump --address localhost --port 6300 --destfile ./jacoco_tcp_02.exec

5.分析 exec 文件生成 html 报告

dump 命令生成的 .exec 文件为二进制文件,需要进行解析,以生成 html 报告为例,执行如下的命令分别将两个 .exec 文件解析成 html 报告。

java -jar C:\工具\jacoco-0.8.6\lib\jacococli.jar report ./jacoco_tcp_01.exec --classfiles .\classes --sourcefiles ..\src\main\java --html report01
java -jar C:\工具\jacoco-0.8.6\lib\jacococli.jar report ./jacoco_tcp_02.exec --classfiles .\classes --sourcefiles ..\src\main\java --html report02

参数说明:

  • ./jacoco_tcp_01.exec,表示要解析的 exec 文件的相对路径。
  • --classfiles .\classes,需要指定生成的 classes 文件目录,参见下图。
  • --sourcefiles ..\src\main\java,需要指定源码的文件目录,参见下图。

在这里插入图片描述

最终,target 目录会生成 report01report02 两个目录,分别打开其中的 index.html 查看代码覆盖率结果。

我们发现 report01 中的代码覆盖率为 73 % 73\% 73%,其中 say()bybye() 两个方法没有被覆盖:

在这里插入图片描述
在这里插入图片描述
而我们访问了对应的服务之后生成的 report02 覆盖率报告为 100%,say()bybye() 这两个方法都覆盖到了:

在这里插入图片描述
在这里插入图片描述

6.覆盖率指标说明

  • Instructions:Java 字节 指令的覆盖率。执行的最小单位,和代码的格式无关。
  • Branches分支覆盖率。注意,异常处理不算做分支。
  • CxtyCyclomatic Complexity):圈复杂度,Jacoco 会为每一个非抽象方法计算圈复杂度,并为类、包以及组(groups)计算复杂度。圈复杂度简单地说就是为了覆盖所有路径,所需要执行单元测试数量,圈复杂度大说明程序代码可能质量低且难于测试和维护。
  • Lines行覆盖率,只要本行有一条指令被执行,则本行则被标记为被执行。
  • Methods方法覆盖率,任何非抽象的方法,只要有一条指令被执行,则该方法就会被计为被执行。
  • Classes类覆盖率,所有类,包括接口,只要其中有一个方法被执行,则标记为被执行。注意:构造函数和静态初始化块也算作方法。
  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

G皮T

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值