找回密码
 立即注册
首页 资源区 代码 Jacoco的一种基本用法和两种高阶用法

Jacoco的一种基本用法和两种高阶用法

劳怡月 2025-6-4 21:50:53
简介

JaCoCo(Java Code Coverage)是一个Java代码覆盖率工具,用于分析单元测试或集成测试对代码的覆盖情况。它通过java agent 技术统计测试过程中执行的代码行、分支、方法等,帮助开发者评估测试的有效性并发现未被覆盖的代码区域。它一般被用来做检查单元测试的代码覆盖率,除此之外,在实践中我还总结出了两种高阶用法。
前置知识

Jacoco 支持的覆盖率类型


  • 行覆盖率(Line Coverage)


  • 含义:代码中每行是否被至少执行一次。
  • 计算方式:已覆盖的行数 / 总行数
  • 示例:若一个方法有 10 行代码,其中 8 行被执行过,则行覆盖率为 80%。

  • 分支覆盖率(Branch Coverage)


  • 含义:每个条件语句(如 if、switch)的分支是否都被覆盖。
  • 计算方式:已覆盖的分支数 / 总分支数
  • 示例:if (a && b) 会产生 4 种分支组合(TT, TF, FT, FF),若只覆盖了 TT 和 TF,则分支覆盖率为 50%。

  • 方法覆盖率(Method Coverage)


  • 含义:类中的每个方法是否被至少调用一次。
  • 计算方式:已覆盖的方法数 / 总方法数
  • 示例:一个类有 5 个方法,其中 3 个被调用过,则方法覆盖率为 60%。

  • 类覆盖率(Class Coverage)


  • 含义:项目中的每个类是否被至少加载一次。
  • 计算方式:已覆盖的类数 / 总类数
  • 示例:项目有 20 个类,其中 15 个被加载过,则类覆盖率为 75%。

  • 指令覆盖率(Instruction Coverage)


  • 含义:字节码指令的执行情况(JaCoCo 基于字节码插桩)。
  • 计算方式:已覆盖的指令数 / 总指令数
  • 用途:更细粒度的覆盖分析,通常开发者较少直接关注。

  • 圈复杂度覆盖率(Cyclomatic Complexity Coverage)


  • 含义:基于代码的圈复杂度(条件分支复杂度)计算覆盖率。
  • 用途:帮助识别代码中复杂且未被覆盖的逻辑路径。
Jacoco的调用方式

有两种调用jacoco的方式:

  • 一是使用 maven插件。这个适用于单元测试场景。
  • 二是直接使用二进制包。这个适用于迭代测试场景、老项目重构场景。
二进制包下载地址:https://www.eclemma.org/jacoco/index.html
它里采用最新版本的, 0.8.12。
解压二进制包,找到 lib/jacocoagent.jar。
兼容性及注意事项

通过反编译jacocoagent.jar中的类文件,我们发现它是使用jdk5编译的,这个保证它可以支持 jdk5及以上。
1.png

经过测试,jacoco 0.8.12在 jdk8和jdk17这两个LTS版本下可以正常运行。
注意事项:jacoco为了保证兼容性,使用的是jdk5编译,这导致它在解析中文路径时会出错,要知道jdk直到jdk8才解决了中文路径问题。因此,不要在中文路径下使用jacoco,jacoco参数中也不要出现中文路径
基本用法:检查单元测试覆盖率


  • 在src/test 下编写测试用例
  • 在pom.xml中配置如下:
  1. <plugin>
  2.     <groupId>org.jacoco</groupId>
  3.     jacoco-maven-plugin</artifactId>
  4.     <version>0.8.12</version>
  5.     <executions>
  6.         <execution>
  7.             <id>default-prepare-agent</id>
  8.             <goals>
  9.                 <goal>prepare-agent</goal>
  10.             </goals>
  11.         </execution>
  12.         <execution>
  13.             <id>default-report</id>
  14.             <phase>test</phase>
  15.             <goals>
  16.                 <goal>report</goal>
  17.             </goals>
  18.         </execution>
  19.     </executions>
  20. </plugin>
复制代码
上面的配置有两个关键点,

  • 目标(goal) prepare-agent是注入 jacoco-agent.jar,如下:
2.png


  • 目标(goal)report则是生成报告,它会利用 jacoco.exec数据文件来生成 site文件。
3.png

执行: mvn clean test, 可以在target下看到生成了jacoco.exec,以及 /site/jacoco目录。如下图所示:
4.png

用浏览器打开 /site/jacoco/index.html,可以看到详细的测试报告,如下图所示:
5.png

高阶用法一:在迭代测试中验证测试团队的用例的覆盖率

痛点

测试团队使用的是黑盒测试,测试完成之后,不知道哪些代码有被覆盖到(执行到),哪些没有被覆盖到(执行到),可能会出现遗漏的情况。
解决方案

通过在java程序启动时,加入jacoco-agent,可以采集测试期间被【测试人员】执行到的代码。通过分析【代码覆盖数据文件】 jacoco.exec,可以查看到哪些代码有被执行,哪些代码没有被执行。
  1. java -javaagent:jacocoagent.jar  -jar app.jar
复制代码
测试用例及验证

构建一个最简的springboot web应用,暴露两个接口;
  1.     http://localhost:8080/test1
  2.     http://localhost:8080/test2
复制代码
编译程序,然后使用 -javaagent:jacocoagent.jar 参数来启动程序。
在程序运行起来之后,访问以下url:
  1.     http://localhost:8080/test2
复制代码
验证


  • 关闭java应用,可以看到目录下生成了一个名为jacoco.exec的文件。
  • 在IDEA中加载这个文件。 点击:菜单 Run > Show Coverage Data。
    6.png

  • 点击 + 号,选择之前复制过来的 .exec文件,然后点击 Show selected。
    7.png

可以看到 TestController下共有3个方法,但只有两个被覆盖到。绿色表示有被执行,红色表示没有被执行。
8.png

高阶用法二:老项目重构场景下找出无用的代码

痛点

部门有许多5年+的项目,这些项目在经历组织架构变更、功能变更之后,很多代码都没有用了。 在项目中大家都知道有很多代码没用,但不确定是哪些,不敢删,结果无用的代码越聚越多,严重影响开发效率。新人加入项目,要在一堆无用的代码中找到有用的代码
解决方案


  • 通过在java程序启动时,加入jacoco-agent,可以采集到代码上线期间被【用户】执行的代码。
  1. java -javaagent:jacocoagent.jar  -jar app.jar
复制代码

  • 让程序运行1个月,即采集1个月的使用数据。
  • 分析【代码覆盖数据文件】 jacoco.exec(方法同高阶用法一),可以查看到哪些代码有被执行,哪些代码没有被执行。以下是覆盖率统计的示例:
    9.png

如何删除无用的代码


  • 保险起见,不要直接删除,可以先注释掉,等过一段时间(比如1-2个月)再删除代码。
  • 优先删除整个类没有被使用的,接着是没有被使用的方法。方法内某些没有被使用的代码行就没有必要管了。
  • 清理之后,上线一个新版本,再收集一波数据,再看一下行覆盖率情况,然后再处理。依次循环,直到覆盖率数据达到比较理想的情况,比如90%。
  • 在采集【代码覆盖数据】如果觉得1个月不够,可以再延长1-2个月。1个功能如果3个月没有用,那么这个功能大概率是没人用了。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册