2017-07-07 158 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)) 
    } 
}