第3章:JaCoCo插件配置(Maven)——绑定生命周期阶段

你想想看,光下载个 JaCoCo 的 jar 包肯定不够用。真正要在项目里跑起来,得把插件挂到 Maven 的生命周期上。说白了,就是告诉 Maven:「什么时候准备 agent,什么时候收集数据,什么时候生成报告」。这步要是没配好,后面增量覆盖率全是空谈。

我在之前一个微服务项目里就踩过坑。团队里新人把 prepare-agent 挂在了 compile 阶段,结果单元测试跑完数据是空的——因为 agent 还没初始化呢。从那以后,我对绑定阶段这事儿就特别上心。

3.1 核心配置:jacoco-maven-plugin

我个人习惯在 pom.xml 的 <build><plugins> 里直接定义。下面这个模板,我在好几个生产项目里都验证过,靠谱。

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.11</version> <!-- 当前稳定版,我建议用最新 -->
    <executions>
        <execution>
            <id>prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

这里有两个关键执行块:prepare-agent 和 report。前者负责启动 Java Agent 并记录执行数据,后者在测试完成后生成覆盖率报告。嗯,要注意——prepare-agent 默认绑定在 initialize 阶段,report 默认绑定在 prepare-package 阶段。但我个人建议显式指定 report 的 phase 为 test,原因?你想想看,单元测试结束后立刻生成报告,逻辑上最顺畅。

个人经验:如果项目里同时有单元测试和集成测试,可以复制一份 execution,将 id 改为 report-integration,并绑定到 verify 阶段。这样能分别拿到不同阶段的覆盖率。

3.2 必须绑定的三个核心执行阶段

别被网上五花八门的配置搞晕。其实核心就这么几个,我做了个表格,一目了然。

执行 ID 默认绑定阶段 我推荐的阶段 说明
prepare-agent initialize initialize(不变) 启动 JaCoCo 运行时 agent,必须最早执行
report prepare-package test 或 verify 生成 .exec 数据文件的 HTML/XML 报告
check verify verify(不变) 覆盖率检查规则,常用于 CI 门禁

避坑指南:我曾经把一个项目的 report 绑定到了 compile 阶段,结果编译完就生成报告,测试还没跑呢。报告里覆盖率永远为 0%。切记:报告一定在测试执行 之后 的阶段生成。

3.3 理解 Maven 阶段与 JaCoCo 的协作流程

为了让你更直观地理解整个流程,我画了张图。从编译开始,到最终报告生成,每个节点都对应 Maven 的一个阶段。看图说话:

Maven 生命周期与 JaCoCo 插件协作流程 compile initialize prepare-agent process-classes test (单元测试) prepare-package report (建议绑定到test) verify check (规则检查) 关键说明 红色阶段为 JaCoCo 插件绑定点。建议 report 绑定到 test 阶段后,确保覆盖率数据已完整收集

3.4 进阶:增量场景下的多执行配置

如果你的项目需要同时支持全量报告和增量报告,可以定义两套 execution。我在做技术债分析时就这么配的:

<execution>
    <id>default-prepare</id>
    <goals><goal>prepare-agent</goal></goals>
</execution>
<execution>
    <id>full-report</id>
    <phase>test</phase>
    <goals><goal>report</goal></goals>
    <!-- 默认输出到 target/site/jacoco -->
</execution>
<execution>
    <id>incremental-report</id>
    <phase>test</phase>
    <goals><goal>report</goal></goals>
    <configuration>
        <dataFile>${project.build.directory}/jacoco-incremental.exec</dataFile>
        <outputDirectory>${project.reporting.outputDirectory}/jacoco-incremental</outputDirectory>
        <!-- 使用增量 exec 文件 -->
    </configuration>
</execution>

注意:增量覆盖率依赖 jacoco-incremental.exec 数据文件。这个文件需要通过 代码变更分析工具 提前生成,不是 JaCoCo 原生自带的。第 5 章我会专门讲如何生成增量 exec 文件。

3.5 常见误区与个人经验总结

  • 误区一: 忘记绑定 report 的阶段。有人只配了 prepare-agent,结果 Maven 默认不生成报告,还以为 JaCoCo 没工作。我建议新手先跑 mvn clean test jacoco:report 验证一次。
  • 误区二: 多个 execution 的 id 重复。Maven 会报错,我曾经排查了一下午才发现是 id 撞了。
  • 误区三: 在 properties 里用 <jacoco.version>0.8.11</jacoco.version> 统一版本,但不同模块的插件版本不一致。别图省事,直接在 parent 的 pluginManagement 里统一。

嗯,配置这块其实不难。核心就是记住:agent 要在测试前启动,报告要在测试后生成。把这句口诀刻在脑子里,出不了大错。至于更多高级配置(比如排除类、合并报告),我们后面章节慢慢聊。