欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

Jacoco的一种基本用法和两种高阶用法,它通过javaage

来源: javaer 分享于  点击 30883 次 点评:235

Jacoco的一种基本用法和两种高阶用法,它通过javaage


简介

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

前置知识

Jacoco 支持的覆盖率类型

  1. 行覆盖率(Line Coverage)
  • 含义:代码中每行是否被至少执行一次。
  • 计算方式:已覆盖的行数 / 总行数
  • 示例:若一个方法有 10 行代码,其中 8 行被执行过,则行覆盖率为 80%。
  1. 分支覆盖率(Branch Coverage)
  • 含义:每个条件语句(如 ifswitch)的分支是否都被覆盖。
  • 计算方式:已覆盖的分支数 / 总分支数
  • 示例:if (a && b) 会产生 4 种分支组合(TT, TF, FT, FF),若只覆盖了 TT 和 TF,则分支覆盖率为 50%。
  1. 方法覆盖率(Method Coverage)
  • 含义:类中的每个方法是否被至少调用一次。
  • 计算方式:已覆盖的方法数 / 总方法数
  • 示例:一个类有 5 个方法,其中 3 个被调用过,则方法覆盖率为 60%。
  1. 类覆盖率(Class Coverage)
  • 含义:项目中的每个类是否被至少加载一次。
  • 计算方式:已覆盖的类数 / 总类数
  • 示例:项目有 20 个类,其中 15 个被加载过,则类覆盖率为 75%。
  1. 指令覆盖率(Instruction Coverage)
  • 含义:字节码指令的执行情况(JaCoCo 基于字节码插桩)。
  • 计算方式:已覆盖的指令数 / 总指令数
  • 用途:更细粒度的覆盖分析,通常开发者较少直接关注。
  1. 圈复杂度覆盖率(Cyclomatic Complexity Coverage)
  • 含义:基于代码的圈复杂度(条件分支复杂度)计算覆盖率。
  • 用途:帮助识别代码中复杂且未被覆盖的逻辑路径。

Jacoco的调用方式

有两种调用jacoco的方式:

  • 一是使用 maven插件。这个适用于单元测试场景。
  • 二是直接使用二进制包。这个适用于迭代测试场景、老项目重构场景。

二进制包下载地址:https://www.eclemma.org/jacoco/index.html

它里采用最新版本的, 0.8.12。

解压二进制包,找到 lib/jacocoagent.jar。

兼容性及注意事项

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

经过测试,jacoco 0.8.12在 jdk8和jdk17这两个LTS版本下可以正常运行。

注意事项:jacoco为了保证兼容性,使用的是jdk5编译,这导致它在解析中文路径时会出错,要知道jdk直到jdk8才解决了中文路径问题。因此,不要在中文路径下使用jacoco,jacoco参数中也不要出现中文路径

基本用法:检查单元测试覆盖率

  • 在src/test 下编写测试用例
  • 在pom.xml中配置如下:
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.12</version>
    <executions>
        <execution>
            <id>default-prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>default-report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

上面的配置有两个关键点,

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

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

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

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

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

痛点

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

解决方案

通过在java程序启动时,加入jacoco-agent,可以采集测试期间被【测试人员】执行到的代码。通过分析【代码覆盖数据文件】 jacoco.exec,可以查看到哪些代码有被执行,哪些代码没有被执行。

java -javaagent:jacocoagent.jar  -jar app.jar

测试用例及验证

构建一个最简的springboot web应用,暴露两个接口;

    http://localhost:8080/test1
    http://localhost:8080/test2

编译程序,然后使用 -javaagent:jacocoagent.jar 参数来启动程序。

在程序运行起来之后,访问以下url:

    http://localhost:8080/test2

验证

  • 关闭java应用,可以看到目录下生成了一个名为jacoco.exec的文件。

  • IDEA中加载这个文件。 点击:菜单 Run > Show Coverage Data

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

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

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

痛点

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

解决方案

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

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

如何删除无用的代码

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

用户点评