2017-07-07 157 views
3

我目前正在使用具有良好覆盖率的gradle multi模块java项目和sonarqube 6.2与sonarJava插件4.10.0.1026。我正在使用Gradle 4.0.1,sonarqube插件2.5和jacoco 0.7.9!代码是java 8.Gradle多模块项目中sonarqube 6.2的覆盖率计算错误

由于API驱动的开发,API测试在API项目中被编写为抽象测试,并从提供测试构造函数的实现项目中调用。

在分析sonarqube服务器上的项目时,实施项目的覆盖率被正确测量,但IMPL项目测试中包含的API项目覆盖率为0.0%。这些项目的覆盖率结果被忽略。

当简单地使用jacoco插件时,我能够得到相同的行为。之后做一些研究,我发现一个解决方案,以获得适当的jacoco报道:

task codeCoverageReport(type: JacocoReport) { 
    description "Creates a unified JaCoCo test report for the project." 

    // Gather execution data from all subprojects 
    // (change this if you e.g. want to calculate unit test/integration test 
    coverage separately) 
    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 
    html.destination file("${buildDir}/reports/jacoco") 
    csv.enabled false 
    } 
} 

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

我现在的结果如下:

JaCoCo:

  1. JaCoCo(codeCoverageReport任务)
    • 73%指导覆盖范围
    • 91%分支覆盖范围
  2. 声纳
    • 43.1%线Coverage(仅〜30%线在计算中考虑!)
    • 82.1%条件覆盖(仅〜覆盖20%的条件!)

因此声纳的覆盖率结果是不可用的。我读过一篇帖子,宣布“sonar.jacoco.reportPaths”参数以sonar 6.2开头,我认为java-analyzer 4.4或者某些东西。像那样。将此参数添加到我的gradle构建脚本时,脚本不再编译。当通过声纳项目管理将jacoco.exe文件添加到声纳时,没有任何更改。

如果能够管理声纳来计算正确的覆盖范围,那将是非常好的选择。

回答

0

Thx @Lance Java!他推动我采取比以下更清晰的解决方案。如果所有的子项目都有jacoco报告,这也是有效的。如果像我一样,在少数项目中只有一个报告,原始解决方案似乎更好。

apply plugin: 'base' 
apply plugin: 'org.sonarqube' 
[...] 
allprojects { 
    apply plugin: 'java' 
    apply plugin: "jacoco" 
    [...] 
    test { 
    [...] 
    jacoco { 
     append=true 
    } 
    } 
} 
[...] 
task jacocoMerge(type: JacocoMerge) { 
    dependsOn(subprojects.jacocoTestReport.dependsOn) 
    mustRunAfter(subprojects.jacocoTestReport.mustRunAfter) 
    destinationFile = file("${buildDir}/jacoco/mergedTests.exec") 
    executionData = files(subprojects.jacocoTestReport.executionData) 
         .filter { jacocoReportFile -> jacocoReportFile.exists() } 
} 
tasks.sonarqube.dependsOn jacocoMerge 
[...] 
sonarqube { 
    properties { 
    [...] 
    property "sonar.jacoco.reportPath", "${buildDir}/jacoco/*.exec" 
    } 
} 

原来的答复:

花了一些时间来管理,以正确的数据覆盖到声纳。有多个问题需要解决。有时声纳记不清在班jacoco变化,所以测试所需要的参数:

append=true 

这并没有完成所有的工作。收集跨项目的覆盖面仍然存在问题。因此,最好的解决方案是强制jacoco将覆盖率数据写入单个.exec文件并将其传递给声纳。

最终的解决方案是这样的:

apply plugin: 'base' 
apply plugin: 'org.sonarqube' 
[...] 
allprojects { 
    apply plugin: 'java' 
    apply plugin: "jacoco" 
    [...] 
    test { 
    [...] 
    jacoco { 
     append=true 
     destinationFile = file("${rootProject.buildDir}/jacoco/jacocoTest.exec") 
    } 
    } 
} 
[...] 
sonarqube { 
    properties { 
    [...] 
    property "sonar.jacoco.reportPath", "${buildDir}/jacoco/*.exec" 
    } 
} 

现在声纳具有正确的覆盖率数据为我的项目。加入一些额外的测试后,这就是结果:

  • 总覆盖率91.6%
  • 线覆盖率91.7%
  • 条件覆盖91.3%
  • 揭秘线36
  • 揭秘条件11
  • 线覆盖433
  • 单元测试1,114
  • 单元测试错误0
  • 单元测试失败0
  • 跳过单元测试0
  • 单元测试成功(%)100.0%
  • 单位测试时间4S

希望这可以帮助一些你...;)

+0

有一个[JacocoMerge](https://docs.gradle.org/4.0/dsl/org.gradle.testing.jacoco.tasks.JacocoMerge.html)任务可以合并将多个执行文件合并为一个 –

+0

在接下来的几天内会再次尝试。第一次测试的最后几天没有正常工作。 –

+0

有一个例子[这里](https://github.com/gradle/gradle/blob/28fa962a330ea6085ea324381eec4f31dcf92d1c/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginMultiVersionIntegrationTest.groovy#L142)在Gradle测试中,它将单个项目中的多个“测试”任务合并并生成合并报告。您可以调整您的多项目设置 –

1

如果您的测试与您希望报道报道的来源不同,那么您需要设置additionalSourceDirsadditionalClassDirs。例如:

evaluationDependsOn ':foo' 
task codeCoverageReport(type: JacocoReport) { 
    additionalSourceDirs.add project(':foo').sourceSets.main.java.sourceDirectories 
    additionalClassDirs.add project(':foo').sourceSets.main.output.classesDirs 
    // etc 
} 
+0

THX。我会给这张支票。希望我能得到这个工作。将很快回复结果。 –

+0

我能够创建一个你的想法工作的样本。对我来说最好的解决方案是下面的aswer ... –

0

我不确定我明白为什么只有一些项目没有jacoco和其他项目才是问题。您可以使用Gradle丰富的API(例如TaskCollectionProject)来动态查找它们。

如:

[':project1', ':project3', ':project5'].each { 
    project(it) { 
     apply plugin: 'java' 
     apply plugin: 'jacoco' 
    } 
} 

project(':merger') { 
    Collection<Project> jacocoProjects = allprojects.findAll { it.plugins.hasPlugin('jacoco' } 
    evaluationDependsOn jacocoProjects 

    task jacocoMerge(type: JacocoMerge) { 
     dependsOn jacocoProjects*.tasks.withType(Test) 
     executionData jacocoProjects*.tasks.withType(Test) 
    } 

    task mergedReport(type: JacocoReport) { 
     dependsOn jacocoMerge 
     executionData jacocoMerge.destinationFile 
     sourceDirectories.add(files(jacocoProjects*.sourceSets*.java.srcDirs)) 
     classDirectories.add(files(jacocoProjects*.sourceSets*.output.classesDir)) 
    } 
}