JaCoCo 代码覆盖率:覆盖率不等于代码质量
覆盖率是衡量测试完整度的指标,但不是质量本身。
用覆盖率做 KPI 的团队,往往会陷入"刷覆盖率"的怪圈:写一堆无关紧要的 assertEquals(1, 1),只是为了提高行覆盖率。
覆盖率是工具,不是目的。
覆盖率指标
| 指标 | 含义 | 建议值 |
|---|---|---|
| 行覆盖率 | 被测试执行的代码行占比 | > 70% |
| 分支覆盖率 | if/switch 分支被覆盖的比例 | > 60% |
| 方法覆盖率 | 被测试的方法占比 | > 80% |
覆盖率只是告诉你"哪些代码被执行过",不告诉你"执行的结果对不对"。代码跑过了 but assert 没写对,覆盖率还是 100%。
Maven 集成
xml
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<executions>
<!-- prepare-agent:记录覆盖率数据到 jacoco.exec -->
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<!-- report:生成 HTML 报告 -->
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>配置好之后,运行测试时会自动生成覆盖率数据:
bash
mvn clean test
# 报告位置:target/site/jacoco/index.html设置覆盖率阈值
CI 里设置覆盖率必须达到某个百分比,否则构建失败:
xml
<execution>
<id>check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.70</minimum> <!-- 至少 70% 行覆盖率 -->
</limit>
<limit>
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>0.60</minimum> <!-- 至少 60% 分支覆盖率 -->
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>Gradle 配置
groovy
plugins {
id 'jacoco'
}
jacoco {
toolVersion = "0.8.8"
}
jacocoTestReport {
reports {
html.destination = layout.buildDirectory.file('reports/jacoco')
}
}
jacocoTestCoverageVerification {
rules {
rule {
element = 'BUNDLE'
limit {
counter = 'LINE'
value = 'COVEREDRATIO'
minimum = 0.70
}
}
}
}覆盖率的使用建议
| 场景 | 建议 |
|---|---|
| 核心业务代码 | 覆盖率 > 80% |
| 工具类 / 公共方法 | 覆盖率 > 70% |
| Controller(API 端点) | 可以低一些(需要集成测试) |
| 配置类 | 覆盖率低一点也没关系 |
覆盖率报告解读
打开 target/site/jacoco/index.html 后:
- 红色行:未被测试覆盖
- 黄色分支:if 分支只覆盖了一部分
- 绿色行:已被覆盖
关注红色区域集中在哪里,那是测试的盲区。
总结
- 覆盖率是下限,不是上限:100% 覆盖率不等于 0 bug
- 关注覆盖率,也要关注 assert 的质量:测了不等于测对了
- 核心业务代码追求高覆盖率:关键路径不能有测试盲区
覆盖率报告是地图,告诉你哪里没去过,但不会告诉你去的地方对不对。
