17370845950

解决Sonarqube中JaCoCo代码覆盖率显示0%的问题

本文旨在解决在Sonarqube中Spring Boot应用使用JaCoCo和Maven进行代码覆盖率分析时,覆盖率始终显示0%的常见问题。核心在于JaCoCo和Surefire插件之间关于执行数据文件(.exec)和报告文件(.xml)路径及格式配置不一致。通过统一Maven pom.xml中的配置,确保JaCoCo代理正确生成数据,并将其转换为Sonarqube可识别的XML报告,即可实现正确的覆盖率展示。

1. 问题背景与现象分析

在使用Jenkins、Maven、JaCoCo和Sonarqube构建Spring Boot项目的CI/CD流水线时,一个常见的问题是Sonarqube上代码覆盖率始终显示为0%。这通常伴随着Maven构建日志中出现类似 [INFO] Skipping JaCoCo execution due to missing execution data file. 的警告信息。尽管单元测试已成功运行,但JaCoCo未能正确生成或找到其执行数据文件(通常是.exec文件),或者生成的报告文件(.xml)路径与Sonarqube期望的路径不符。

导致此问题的根本原因通常是JaCoCo Maven插件和Maven Surefire插件之间的配置不一致,特别是在以下几个方面:

  • JaCoCo代理数据文件路径不一致: JaCoCo prepare-agent 目标生成.exec文件的位置与JaCoCo report 目标期望读取的位置不一致。
  • Surefire插件未传递JaCoCo代理参数: Surefire插件在执行测试时,未能将JaCoCo代理所需的JVM参数传递给JVM。
  • JaCoCo XML报告路径不一致: JaCoCo report 目标生成XML报告的路径与Sonarqube扫描器通过 sonar.coverage.jacoco.xmlReportPaths 属性配置的路径不一致。

2. 解决方案:统一Maven pom.xml 配置

解决此问题的关键在于确保所有相关插件和属性在 pom.xml 中保持高度一致性。

2.1 核心Maven pom.xml 属性配置

首先,在 pom.xml 的 块中,定义Sonarqube扫描器所需的报告路径。这些路径将指导Sonarqube在哪里查找单元测试报告和JaCoCo生成的代码覆盖率XML报告。


    1.8
    3.1.0
    UTF-8

    
    ${basedir}/target/surefire-reports
    
    ${basedir}/target/jacoco_report/jacoco.xml

注意事项:

  • sonar.coverage.jacoco.xmlReportPaths 必须指向JaCoCo最终生成的XML报告文件,而不是其二进制.exec文件。
  • 路径应使用绝对路径或基于项目根目录的相对路径。

2.2 JaCoCo Maven 插件配置

JaCoCo插件负责在测试运行期间收集代码覆盖率数据,并将其转换为XML报告。其配置通常包含两个主要执行(execution):prepare-agent 和 report。


    org.jacoco
    jacoco-maven-plugin
    0.8.6 
    
        
        
            prepare-agent
            
                prepare-agent
            
            
                
                ${project.build.directory}/coverage-reports/jacoco-ut.exec
                
                surefireArgLine
            
        

        
        
            report
            test 
            
                report
            
            
                
                ${project.build.directory}/coverage-reports/jacoco-ut.exec
                
                ${project.build.directory}/jacoco_report
                
                jacoco.xml 
            
        
    

注意事项:

  • 在 prepare-agent 中定义了JaCoCo代理生成.exec文件的位置。
  • 在 report 中定义了JaCoCo报告生成器读取.exec文件的位置。这两个路径必须完全一致
  • 在 report 中定义了XML报告的输出目录。结合 jacoco.xml,确保最终报告文件为 target/jacoco_report/jacoco.xml,这与 sonar.coverage.jacoco.xmlReportPaths 的配置相匹配。
  • propertyName surefireArgLine 是为了将JaCoCo代理参数传递给Surefire插件。

2.3 Maven Surefire 插件配置

Maven Surefire插件负责执行单元测试。它需要配置以接收并应用JaCoCo代理传递的JVM参数。


    org.apache.maven.plugins
    maven-surefire-plugin
    2.22.2 
    
        
        ${surefireArgLine}
        
        ${sonar.surefire.reportsPath}
    

注意事项:

  • ${surefireArgLine} 是关键,它确保JaCoCo代理在测试执行时被激活并收集数据。
  • 应该与 sonar.surefire.reportsPath 保持一致。

3. Jenkins 流水线配置

在Jenkins流水线中,需要确保Maven构建命令正确执行了JaCoCo的 prepare-agent 和 report 目标,并且Sonarqube扫描器能够找到生成的JaCoCo XML报告。

pipeline {
    agent any
    stages {
        stage('Build and Test') {
            steps {
                // 清理、编译、运行测试并生成JaCoCo报告
                // `mvn clean verify` 会触发 prepare-agent (在validate阶段), test (运行测试), report (在test阶段)
                sh 'mvn clean verify' 
                // 或者,如果report目标绑定到test阶段,`mvn clean test` 也可以
                // sh 'mvn clean test' 
            }
        }
        stage('SonarQube Analysis') {
            steps {
                // SonarQube扫描器将自动读取pom.xml中定义的sonar.*属性
                // 确保不要在命令行中覆盖pom.xml中的sonar.coverage.jacoco.xmlReportPaths
                withSonarQubeEnv('Your SonarQube Server') { // 'Your SonarQube Server' 是Jenkins中配置的SonarQube服务器名称
                    sh 'mvn sonar:sonar'
                    // 如果pom.xml中未定义sonar.coverage.jacoco.xmlReportPaths,则可以在此处指定
                    // sh 'mvn sonar:sonar -Dsonar.coverage.jacoco.xmlReportPaths=target/jacoco_report/jacoco.xml'
                }
            }
        }
    }
}

注意事项:

  • mvn clean verify 命令通常比 mvn clean test 更为完整,因为它会执行Maven的整个生命周期,包括 prepare-agent (通常绑定到 validate 阶段) 和 report (绑定到 test 或 verify 阶段)。
  • withSonarQubeEnv 步骤确保SonarQube环境变量被正确设置。
  • 如果 pom.xml 中已正确配置 sonar.coverage.jacoco.xmlReportPaths,则 mvn sonar:sonar 命令会自动读取该属性,无需在命令行中重复 -D 参数,以避免潜在的冲突。

4. 验证与故障排除

完成上述配置后,执行Jenkins流水线。

  1. 检查Maven构建日志: 确保没有 Skipping JaCoCo execution due to missing execution data file 警告。
  2. 检查项目 target 目录:
    • 在 target/coverage-reports/ 目录下,应该能找到 jacoco-ut.exec 文件。
    • 在 target/jacoco_report/ 目录下,应该能找到 jacoco.xml 文件。
    • 在 target/surefire-reports/ 目录下,应该能找到单元测试的XML报告。
  3. 检查Sonarqube分析日志: 在Jenkins的SonarQube分析步骤中,查看日志输出,确认Sonarqube扫描器是否成功读取了JaCoCo XML报告。日志中应包含类似 INFO: Sensor JaCoCo XML Report Sensor [jacoco] (done) ... 的信息,并且会列出它处理的XML报告路径。
  4. 查看Sonarqube界面: 登录Sonarqube,检查项目的代码覆盖率是否已正确显示。

如果仍然遇到问题,请仔细核对所有路径和文件名是否完全一致,并确保Maven插件的版本兼容。

5. 总结

在Sonarqube中实现JaCoCo代码覆盖率的正确显示,核心在于JaCoCo、Surefire插件以及Sonarqube扫描器之间关于报告文件路径和格式的配置一致性。通过在Maven pom.xml 中统一 和插件配置,特别是确保 .exec 文件的生成和读取路径一致,以及 .xml 报告的输出路径与Sonarqube期望的路径匹配,可以有效解决代码覆盖率为0%的问题。遵循本教程的步骤,将有助于构建一个健壮且准确的代码质量分析流水线。