Jacoco与SonarQube代码覆盖率结果不一致问题排查
执行mvn clean verify时,Jacoco显示行覆盖率64%、分支覆盖率62%,但SonarQube中代码覆盖率显示为70%(截图如下):
我未在Jacoco或Sonar中排除任何类,且两者使用同一分支。以下是pom.xml配置快照:
<jacoco.version>0.8.8</jacoco.version> <properties-maven-plugin.version>1.1.0</properties-maven-plugin.version> <sonar-maven-plugin.version>3.9.1.2184</sonar-maven-plugin.version> <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin> <sonar.sources>src/main</sonar.sources> <sonar.tests>src/test</sonar.tests> <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis> <sonar.coverage.jacoco.xmlReportPaths>target/site/jacoco/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths> <sonar.language>java</sonar.language> <plugin> <groupId>org.sonarsource.scanner.maven</groupId> <artifactId>sonar-maven-plugin</artifactId> <version>${sonar-maven-plugin.version}</version> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>${jacoco.version}</version> <configuration> <rules> <rule> <element>BUNDLE</element> <limits> <limit> <counter>LINE</counter> <value>COVEREDRATIO</value> <minimum>60%</minimum> </limit> <limit> <counter>BRANCH</counter> <value>COVEREDRATIO</value> <minimum>60%</minimum> </limit> </limits> </rule> </rules> </configuration> <executions> <execution> <id>coverage-initialize</id> <goals> <goal>prepare-agent</goal> </goals> </execution> <execution> <id>coverage-report</id> <phase>post-integration-test</phase> <goals> <goal>report</goal> </goals> </execution> <execution> <id>coverage-check</id> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin> <profile> <id>sonar</id> <activation> <property> <name>env.V_TEMPLATE_TYPE</name> <value>CI</value> </property> <activeByDefault>false</activeByDefault> </activation> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>properties-maven-plugin</artifactId> <version>${properties-maven-plugin.version}</version> <executions> <execution> <phase>verify</phase> <goals> <goal>read-project-properties</goal> </goals> <configuration> <files> <file>sonar.properties</file> </files> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.sonarsource.scanner.maven</groupId> <artifactId>sonar-maven-plugin</artifactId> <version>${sonar-maven-plugin.version}</version> <executions> <execution> <phase>verify</phase> <goals> <goal>sonar</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </profile>
另外,添加排除规则时,Sonar的结果会受影响,但Jacoco的结果无变化。我尝试在以下代码的多个位置添加排除规则(认为最合理的位置是</limits>和</rule>之间),但完全无效:
<configuration> <rules> <rule> <element>BUNDLE</element> <limits> <limit> <counter>LINE</counter> <value>COVEREDRATIO</value> <minimum>70%</minimum> </limit> <limit> <counter>BRANCH</counter> <value>COVEREDRATIO</value> <minimum>70%</minimum> </limit> </limits> </rule> </rules> </configuration>
我还配置了用于GitHub与Sonar集成的sonar.properties文件(Sonar扫描仍在pom.xml中配置),内容如下:
sonar.projectKey= sonar.projectName= sonar.host.url= sonar.login= sonar.exclusions=OPTIONAL
一、Jacoco与SonarQube覆盖率差异的原因
- 统计范围不同
SonarQube默认会忽略部分代码,比如:
- Lombok自动生成的getter/setter、构造函数
- 抽象方法、接口方法
- 静态初始化块
- 无实际逻辑的空方法
而Jacoco会将这些代码纳入统计,导致Jacoco的覆盖率数值更低。
报告生成时机差异
你的Jacoco报告在post-integration-test阶段生成,但SonarQube在verify阶段扫描。如果单元测试和集成测试的执行范围、顺序有差异,可能导致SonarQube读取的覆盖率数据和Jacoco的统计范围不一致。SonarQube的覆盖率过滤逻辑
SonarQube会自动过滤标记为“生成代码”的未覆盖行,而Jacoco不会做这个处理。另外,SonarQube可能合并多阶段测试的覆盖率数据,若Jacoco报告只包含部分测试阶段结果,就会出现数值偏差。版本兼容性问题
你使用的Sonar Maven插件(3.9.1.2184)和Jacoco(0.8.8)版本可能存在兼容性问题,导致SonarQube解析Jacoco报告时出现偏差。建议升级Sonar Maven插件到4.0+版本,同时确保Jacoco版本与之匹配。
二、Jacoco排除规则无效的解决办法
你之前在<rules>标签里加排除规则是错误的——<rules>仅用于设置覆盖率阈值,不是排除类的配置项。正确的排除配置应该放在<configuration>下的<excludes>标签中,示例如下:
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>${jacoco.version}</version> <configuration> <!-- 排除不需要统计的类 --> <excludes> <exclude>com/example/dto/**/*</exclude> <exclude>com/example/entity/**/*</exclude> <exclude>com/example/constants/**/*</exclude> </excludes> <rules> <rule> <element>BUNDLE</element> <limits> <limit> <counter>LINE</counter> <value>COVEREDRATIO</value> <minimum>70%</minimum> </limit> <limit> <counter>BRANCH</counter> <value>COVEREDRATIO</value> <minimum>70%</minimum> </limit> </limits> </rule> </rules> </configuration> <!-- 执行配置保持不变 --> </plugin>
若要让SonarQube和Jacoco的统计范围一致,需要同时在Sonar配置(pom.xml或sonar.properties)中设置sonar.exclusions,确保两者排除规则匹配。
内容的提问来源于stack exchange,提问作者djasyfuj

