jacoco 和 gradle 多模块项目的跨模块代码覆盖率

问题描述 投票:0回答:3

我们使用 gradle 3.3 和 jacoco 工具版本 0.7.6.201602180812。 我们有一个像这样的 gradle 多项目:

  • 家长
    • 产品1
    • 产品2
    • 产品3
    • int测试

我们使用单元测试来测试项目源,并在所有生成 test.exec 文件的子项目上使用 jacoco。我们在 int-test 项目中进行了额外的集成测试,将 jacoco 结果添加到 int-test 项目中的 test-exec 中。我们在父项目上使用 sonarqube gradle 插件 (2.2.1) 来收集 SonarQube 服务器 v6.2 的所有内容。

在自己的项目中测试源代码的测试一切都运行良好:代码覆盖率在 jacoco 报告以及 SonarQube 上进行测量。

只有产品项目(单个进程)中源的集成测试(int-test 项目)覆盖率既不会在包含测试的项目的覆盖率报告中进行测量,也不会在包含类的项目中进行测量。

可能需要以某种方式合并顶级项目的覆盖数据 - 有人知道如何做到这一点吗?最好的情况是 SonarQube 仍然显示单个模块级别的覆盖范围。

编辑 这是一个小测试项目:https://github.com/MichaelZett/coveragetest 运行
'build SmokeTest sonarqube' 会导致:

  • 运行所有测试
  • 在所有子项目中生成 jacoco/test.exec 和 test-results/test/... 文件
  • 在 sonarqube 中解析这些
  • 正确测量在自己项目中测试源的测试的覆盖率
  • 缺少在另一个项目中测试源的测试的覆盖范围
gradle sonarqube jacoco multi-module
3个回答
12
投票

如评论中所述,您必须首先合并 Jacoco 执行数据,然后告诉 sonarqube 使用该数据,而不是每个子模块生成的单独

exec
文件。

我在这里添加一个示例,因为接受的答案中提供的链接有点误导。它们中的大多数为您提供了不同的解决方法来合并 Jacoco 报告,而不是合并执行数据,这正是您想要的。

它的样子是这样的:

def allTestCoverageFile = "$buildDir/jacoco/allTestCoverage.exec"

sonarqube {
    properties {
        property "sonar.projectKey", "your.org:YourProject"
        property "sonar.projectName", "YourProject"
        property "sonar.jacoco.reportPaths", allTestCoverageFile
    }
}

task jacocoMergeTest(type: JacocoMerge) {
    destinationFile = file(allTestCoverageFile)
    executionData = project.fileTree(dir: '.', include:'**/build/jacoco/test.exec')
}

task jacocoMerge(dependsOn: ['jacocoMergeTest']) {
    // used to run the other merge tasks
}

subprojects {
    sonarqube {
        properties {
            property "sonar.jacoco.reportPaths", allTestCoverageFile
        }
    }
}

简而言之:

  • 首先,我们为测试报告定义一个全局覆盖文件输出 (
    allTestCoverageFile
    )。
  • 然后我们需要告诉 Sonarqube 使用该文件(使用
    sonar.jacoco.reportPaths
    )。但请注意,我们还必须在子项目关闭中执行此操作。这一点非常重要。不要错过哦。
  • 最后,我们创建一个从
    JacocoMerge
    (Jacoco 插件的孵化类)扩展的自定义任务,它将所有项目 (
    executionData
    ) 的所有测试覆盖率报告合并到我们的
    allTestCoverageFile
    中。

如果您使用 6.2 之前的 SonarQube 版本,请使用 sonar.jacoco.reportPath 属性


6
投票

谈到 SonarQube:您可以通过在所有模块中使用

jacoco.exec
的相同位置来获取聚合报告。确保在构建之前删除该文件并将其附加到所有模块中。

仅谈论 Gradle:看看


2
投票
subprojects {
    apply(plugin: 'org.jetbrains.kotlin.jvm')

    repositories {
        jcenter()
        mavenCentral()
   }
}

task codeCoverageReport(type: JacocoReport) {

    // Gather execution data from all subprojects
    executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec")

    // Add all relevant sourcesets from the subprojects
    subprojects.each {
        sourceSets it.sourceSets.main
    }

    reports {
        xml.enabled true
        html.enabled true
        csv.enabled false
    }
}

// always run the tests before generating the report
codeCoverageReport.dependsOn {
    subprojects*.test
}

sonarqube {
    properties {
        property "sonar.projectKey", "your_project_key"
        property "sonar.verbose", true
        property "sonar.projectName", "Your project name"
        property "sonar.coverage.jacoco.xmlReportPaths", "${rootDir}/build/reports/jacoco/codeCoverageReport/codeCoverageReport.xml"
    }
}

运行覆盖率测试的命令:

./gradlew codeCoverageReport
./gradlew sonarqube -x test (test is excluded since already run and sonarqube by default executes test)

要使其发挥作用,需要注意两件事:

  1. 为了使所有模块的源集可用,循环子项目并累积源集是可行的。 subprojects.sourceSets.main.allSource.srcDirs 不起作用。
  2. sonar.jacoco.reportPaths 已弃用。我们需要usesonar.coverage.jacoco.xmlReportPaths。检查这里的文档

© www.soinside.com 2019 - 2024. All rights reserved.