问题
I am new to gradle. I am using the below code. But it generates coverage for unit test cases. But it didn't generate for integration test cases. I have my test classes in the package src/test/java.
test {
dependsOn jettyRunWar
ignoreFailures true
finalizedBy jettyStop
}
apply plugin: 'jacoco'
jacocoTestReport {
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
additionalSourceDirs = files(sourceSets.main.allJava.srcDirs)
}
回答1:
Using Gradle 5.4.1 (and now 5.5.1), I was able to get a report after any test task, currently I have both test
and integrationTest
tasks.
EDIT2: The solution is the same, I just tweaked
- the reports destination to use
jacoco.reportsDir
, - the executionData now takes
tasks.withType(Test)
instead of just[test, integrationTest]
- setting
executionData
is done in thedoFirst
block instead ofdoLast
EDIT: After looking at the documentation of JacocoReport
, there's a variant JacocoReport:executionData that take Gradle tasks directly. It works because the JaCoCo plugin adds a JacocoTaskExtension extension to all tasks of type Test. Which is then less error prone. The report task then become :
jacocoTestReport {
doFirst {
// The JaCoCo plugin adds a JacocoTaskExtension extension to all tasks of type Test.
// Use task state to include or not task execution data
// https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/TaskState.html
executionData(tasks.withType(Test).findAll { it.state.executed })
}
reports {
xml.enabled true
xml.destination(file("${jacoco.reportsDir}/all-tests/jacocoAllTestReport.xml"))
html.enabled true
html.destination(file("${jacoco.reportsDir}/all-tests/html"))
}
}
And the same trick can be applied to sonarqube
task :
sonarqube {
group = "verification"
properties {
// https://jira.sonarsource.com/browse/MMF-1651
property "sonar.coverage.jacoco.xmlReportPaths", jacocoTestReport.reports.xml.destination
properties["sonar.junit.reportPaths"] += integrationTest.reports.junitXml.destination
properties["sonar.tests"] += sourceSets.integrationTest.allSource.srcDirs
// ... other properties
}
}
Older but very working answer. Also using the knowledge above (that Test
s task are extended by JacocoTaskExtension
) it's possible to replace the manual file
configuration of executionData
by test.jacoco.destinationFile
and integrationTest.jacoco.destinationFile
.
// Without it, the only data is the binary data,
// but I need the XML and HTML report after any test task
tasks.withType(Test) {
finalizedBy jacocoTestReport
}
// Configure the report to look for executionData generated during the test and integrationTest task
jacocoTestReport {
executionData(file("${project.buildDir}/jacoco/test.exec"),
file("${project.buildDir}/jacoco/integrationTest.exec"))
reports {
// for sonarqube
xml.enabled true
xml.destination(file("${project.buildDir}/reports/jacoco/all-tests/jacocoAllTestReport.xml"))
// for devs
html.enabled true
html.destination file("${project.buildDir}/reports/jacoco/all-tests/html")
}
}
sonarqube {
group = "verification"
properties {
// https://jira.sonarsource.com/browse/MMF-1651
property "sonar.coverage.jacoco.xmlReportPaths", ${project.buildDir}/test-results/integrationTest"
properties["sonar.junit.reportPaths"] += "${project.buildDir}/test-results/integrationTest"
properties["sonar.tests"] += sourceSets.integrationTest.allSource.srcDirs
// ... other properties
}
}
project.tasks["sonarqube"].dependsOn "jacocoTestReport"
回答2:
It seems like, what you need to tell build.gradle is where are your Intergration tests (i.e. folder containing those IT tests) using sourceSets. In my case, i have source under src/java (instead of src/main/java - gradle default).. my unit tests (Junit) under test/java folder, and my integration tests under src/java-test folder.
sourceSets {
main {
java {
srcDir 'src/java'
}
}
test {
java {
srcDir 'test/java'
}
resources {
srcDir 'test/resources'
srcDir 'conf'
}
}
integrationTest {
java {
srcDir 'src/java-test'
}
}
}
Then, I have integrationTest task as ... which you can tweak as you might not have cleanTest (custom task that i have created), so you can ignore that dependsOn... i think in your case you'll use something like jettyStart as you're using that for IT tests (starting the container for running IT tests and then finalizedBy feature to stop jetty .. jetty plugin)
task integrationTest( type: Test, dependsOn: cleanTest ) {
jacoco {
//destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
destinationFile = file("$buildDir/jacoco/integrationTest.exec")
//classDumpFile = file("$buildDir/jacoco/classpathdumps")
classDumpFile = file("$buildDir/classes/integrationTest")
}
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
}
SEE this post for more detailed output structure and script that I have at my end. Im getting the .exec for both Unit tests (test.exec) and IT tests intergrationTest.exec.. but Im not getting the jacoco.xml/jacocoHtml reports for both tests. I also found that, if I run "gradle clean build" (which includes call to "test" task) and "gradle clean build integrationTest" then, later one overwrites unit tests data in build/test-results folder and build/reports/tests folder.
Jacoco Unit and Integration Tests coverage - individual and overall
NOTE: in my case, jacocoTestReport is defined in the global gradle init.d folder in one of the common gradle file. This will help us not to include the same code in all / at project level build.gradle file.
回答3:
I believe the most full answer will look like:
tasks.withType(Test) {
finalizedBy jacocoTestReport
}
project.jacocoTestReport {
getExecutionData().setFrom(fileTree(buildDir).include("/jacoco/*.exec"))
reports {
csv.enabled true
}
}
At least it's fully suited for my needs with integration and functional testing.
来源:https://stackoverflow.com/questions/19025138/gradle-how-to-generate-coverage-report-for-integration-test-using-jacoco