Cross-module jacoco 和 gradle multi-module 项目的代码覆盖率
Cross-module code coverage with jacoco and gradle multi-module project
我们使用 gradle 3.3 和 jacoco 工具版本 0.7.6.201602180812。
我们有一个 gradle multi-project 这样的:
- parent
- 产品1
- 产品2
- prod3
- int-test
我们使用 unit-tests 测试所有 child-projects 生成的 test.exec 文件的项目源和 jacoco。我们在 int-test 项目中有额外的 integration-tests,将 jacoco 结果添加到 int-test 项目中的 test-exec。我们在 parent 项目上使用 sonarqube gradle 插件 (2.2.1) 来收集 SonarQube 服务器 v6.2 的所有内容。
在他们自己的项目中测试源的测试一切都运行良好:代码覆盖率在 jacoco 报告和 SonarQube 上测量。
只有集成测试(int-test 项目)对 prod-projects(单个进程)中源的覆盖率未在带有测试的项目和带有 [=70 的项目的覆盖率报告中测量=].
可能需要以某种方式组合顶级项目的覆盖率数据——有人知道该怎么做吗?充其量 SonarQube 仍然显示单个模块级别的覆盖范围。
编辑
这是一个小测试项目:https://github.com/MichaelZett/coveragetest
运行宁
'build smokeTest sonarqube'导致:
- 运行 所有测试
- 在所有 child 个项目中生成 jacoco/test.exec 和 test-results/test/... 文件
- 在 sonarqube 中解析这些
- 正确测量在自己的项目中测试源代码的测试的覆盖率
- 在另一个项目中测试源的测试缺少覆盖范围
关于 SonarQube:您可以通过在所有模块中对 jacoco.exec
使用相同的位置来获取汇总报告。确保在构建之前删除该文件并将其附加到所有模块中。
只谈Gradle:看看
如评论中所述,您必须首先 merge the Jacoco execution 数据,然后告诉 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 插件的孵化 class),它合并了所有项目的所有测试覆盖率报告(executionData
) 到我们的 allTestCoverageFile
.
If you are using a version of SonarQube prior to 6.2 please use sonar.jacoco.reportPath property
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)
使它起作用的两点需要注意:
- 为了使所有模块的源集可用,遍历子项目和累积源集是可行的。 subprojects.sourceSets.main.allSource.srcDirs 无效。
- sonar.jacoco.reportPaths 已 弃用 。我们需要使用sonar.coverage.jacoco.xmlReportPaths。在此处查看文档
我们使用 gradle 3.3 和 jacoco 工具版本 0.7.6.201602180812。 我们有一个 gradle multi-project 这样的:
- parent
- 产品1
- 产品2
- prod3
- int-test
我们使用 unit-tests 测试所有 child-projects 生成的 test.exec 文件的项目源和 jacoco。我们在 int-test 项目中有额外的 integration-tests,将 jacoco 结果添加到 int-test 项目中的 test-exec。我们在 parent 项目上使用 sonarqube gradle 插件 (2.2.1) 来收集 SonarQube 服务器 v6.2 的所有内容。
在他们自己的项目中测试源的测试一切都运行良好:代码覆盖率在 jacoco 报告和 SonarQube 上测量。 只有集成测试(int-test 项目)对 prod-projects(单个进程)中源的覆盖率未在带有测试的项目和带有 [=70 的项目的覆盖率报告中测量=]. 可能需要以某种方式组合顶级项目的覆盖率数据——有人知道该怎么做吗?充其量 SonarQube 仍然显示单个模块级别的覆盖范围。编辑
这是一个小测试项目:https://github.com/MichaelZett/coveragetest
运行宁
'build smokeTest sonarqube'导致:
- 运行 所有测试
- 在所有 child 个项目中生成 jacoco/test.exec 和 test-results/test/... 文件
- 在 sonarqube 中解析这些
- 正确测量在自己的项目中测试源代码的测试的覆盖率
- 在另一个项目中测试源的测试缺少覆盖范围
关于 SonarQube:您可以通过在所有模块中对 jacoco.exec
使用相同的位置来获取汇总报告。确保在构建之前删除该文件并将其附加到所有模块中。
只谈Gradle:看看
如评论中所述,您必须首先 merge the Jacoco execution 数据,然后告诉 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 插件的孵化 class),它合并了所有项目的所有测试覆盖率报告(executionData
) 到我们的allTestCoverageFile
.
If you are using a version of SonarQube prior to 6.2 please use sonar.jacoco.reportPath property
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)
使它起作用的两点需要注意:
- 为了使所有模块的源集可用,遍历子项目和累积源集是可行的。 subprojects.sourceSets.main.allSource.srcDirs 无效。
- sonar.jacoco.reportPaths 已 弃用 。我们需要使用sonar.coverage.jacoco.xmlReportPaths。在此处查看文档