Skip to content

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 分支只覆盖了一部分
  • 绿色行:已被覆盖

关注红色区域集中在哪里,那是测试的盲区。

总结

  1. 覆盖率是下限,不是上限:100% 覆盖率不等于 0 bug
  2. 关注覆盖率,也要关注 assert 的质量:测了不等于测对了
  3. 核心业务代码追求高覆盖率:关键路径不能有测试盲区

覆盖率报告是地图,告诉你哪里没去过,但不会告诉你去的地方对不对。

基于 VitePress 构建