JaCoCo
JaCoCo(Java Code Coverage)是 Java 主流的代码覆盖率工具,通过字节码插桩统计测试执行了哪些代码,生成行覆盖、分支覆盖等报告,并可在 CI 中强制最低覆盖率阈值。
覆盖率指标
| 指标 | 含义 |
|---|---|
| 行覆盖(Line) | 被执行的源码行占总行数的比例 |
| 分支覆盖(Branch) | if/switch 分支被覆盖的比例(最能反映逻辑完整性) |
| 指令覆盖(Instruction) | JVM 字节码指令粒度,最细 |
| 方法覆盖(Method) | 被调用方法占总方法数 |
| 类覆盖(Class) | 被实例化/调用的类 |
| 圈复杂度(Complexity) | 独立执行路径数,等于最少测试用例数 |
Maven 集成
<!-- pom.xml -->
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.11</version>
<executions>
<!-- 绑定 prepare-agent:在测试前注入 JaCoCo Agent -->
<execution>
<id>prepare-agent</id>
<goals><goal>prepare-agent</goal></goals>
</execution>
<!-- 绑定 report:测试后生成 HTML/XML 报告 -->
<execution>
<id>report</id>
<phase>verify</phase>
<goals><goal>report</goal></goals>
</execution>
<!-- 绑定 check:低于阈值则构建失败 -->
<execution>
<id>check</id>
<phase>verify</phase>
<goals><goal>check</goal></goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element> <!-- 整个项目维度 -->
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum> <!-- 最低 80% 行覆盖 -->
</limit>
<limit>
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>0.70</minimum> <!-- 最低 70% 分支覆盖 -->
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>常用命令:
mvn test # 运行测试,生成 target/jacoco.exec 数据文件
mvn verify # 运行测试 + 生成报告 + 覆盖率检查
mvn jacoco:report # 单独生成报告(target/site/jacoco/index.html)
mvn jacoco:check # 单独检查阈值Gradle 集成
// build.gradle.kts
plugins {
jacoco
}
jacoco {
toolVersion = "0.8.11"
}
tasks.test {
finalizedBy(tasks.jacocoTestReport) // 测试完自动生成报告
}
tasks.jacocoTestReport {
dependsOn(tasks.test)
reports {
xml.required = true // CI 用 XML(SonarQube、Codecov 读取)
html.required = true // 本地查看 HTML
csv.required = false
}
}
tasks.jacocoTestCoverageVerification {
violationRules {
rule {
limit {
counter = "LINE"
value = "COVEREDRATIO"
minimum = "0.80".toBigDecimal()
}
}
rule {
limit {
counter = "BRANCH"
value = "COVEREDRATIO"
minimum = "0.70".toBigDecimal()
}
}
}
}
// check 任务依赖覆盖率验证(执行 ./gradlew check 时自动触发)
tasks.check {
dependsOn(tasks.jacocoTestCoverageVerification)
}排除不需要统计的类
配置文件、实体类、枚举、自动生成的代码通常不计入覆盖率:
<!-- Maven:在 report 和 check 的 configuration 中添加 -->
<configuration>
<excludes>
<!-- Lombok 生成的代码 -->
<exclude>**/*$*.class</exclude>
<!-- 配置类 -->
<exclude>com/example/config/**</exclude>
<!-- 实体 / VO -->
<exclude>com/example/entity/**</exclude>
<exclude>com/example/vo/**</exclude>
<!-- MyBatis Mapper 接口 -->
<exclude>com/example/mapper/**</exclude>
<!-- 启动类 -->
<exclude>com/example/Application.class</exclude>
<!-- 枚举 -->
<exclude>com/example/enums/**</exclude>
</excludes>
</configuration>// Gradle
tasks.jacocoTestReport {
classDirectories.setFrom(
files(classDirectories.files.map {
fileTree(it) {
exclude(
"**/config/**",
"**/entity/**",
"**/vo/**",
"**/mapper/**",
"**/enums/**",
"**/*Application.class"
)
}
})
)
}查看 HTML 报告
target/site/jacoco/index.html # Maven
build/reports/jacoco/test/html/index.html # Gradle
报告颜色含义:
| 颜色 | 含义 |
|---|---|
| 绿色 | 行/分支已覆盖 |
| 黄色 | 分支部分覆盖(如 if 只测了 true,没测 false) |
| 红色 | 完全未覆盖 |
多模块项目聚合报告
多模块项目各子模块有独立报告,需在父模块聚合:
<!-- 父 pom.xml:新增聚合 report 模块或在父模块执行聚合 -->
<execution>
<id>report-aggregate</id>
<phase>verify</phase>
<goals><goal>report-aggregate</goal></goals>
<configuration>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-aggregate</outputDirectory>
</configuration>
</execution>CI 集成(GitHub Actions)
# .github/workflows/test.yml
- name: Run tests with coverage
run: mvn verify
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: target/site/jacoco/jacoco.xml
fail_ci_if_error: true
# 或上传到 SonarQube
- name: SonarQube Scan
run: mvn sonar:sonar
-Dsonar.projectKey=my-project
-Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml与 Spring Boot 测试联动
Spring Boot 测试中 JaCoCo 无需额外配置,只要 mvn test / gradle test 执行了测试,JaCoCo Agent 会自动收集所有 @SpringBootTest、@WebMvcTest、@DataJpaTest 等的覆盖率数据并合并到同一份报告。
测试执行
├── @SpringBootTest(集成测试)
├── @WebMvcTest(Controller 层)
├── @DataJpaTest(Repository 层)
└── 无 Context 单元测试
│
JaCoCo Agent 收集 → jacoco.exec
│
jacoco:report → HTML / XML 报告
│
jacoco:check → 低于阈值则 BUILD FAILURE