Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

build.gradle with Jacoco plugin doesn't generate coverage report for integration tests

I have a build.gradle file which can successfully run unit and integration tests separately or together (with a command like gradle test integrationTest for together). Both use Junit, I'm using Gradle 3, and this isn't an Android project. A report about the success is produced for each, in separate directories. I can also successfully generate a Jacoco report for unit test coverage with gradle test jacoco. I am unable to get a coverage report for my otherwise-working integration tests by using gradle integrationTest jacoco, though the test does successfully run and a integrationTest.exec file is generated.

To be more explicit, I get the unit test coverage report in build/reports/index.html, and the Junit reports in build/reports/test/index.html and build/reports/integrationTest/index.html. A build/reports/jacoco directory is created but contains only an empty "test" directory. build/ also contains a jacoco/ directory, which contains both .exec files and classpathdumps.

Here is my abbreviated build.gradle

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'jacoco'

repositories {
    mavenCentral()
}

sourceSets {
    main {
        java {
            srcDirs = ['src/java']
        }
        test {
            java {
                srcDirs = ['test/java']
            }
        }
        resources {
            srcDirs = ['src/java', 'conf', 'resource']
        }
    }

    integrationTest {
        java {
            compileClasspath += main.output + test.output
            runtimeClasspath += main.output + test.output
            srcDir file('integration_test/java')
        }
    }
}

test {
    jacoco {
        append = false
        destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
        classDumpFile = file("$buildDir/jacoco/classpathdumps")
    }
}

configurations {
    integrationTestCompile.extendsFrom testCompile
    integrationTestRuntime.extendsFrom testRuntime
}

/* SNIP */

task integrationTest(type: Test) {
    dependsOn startserver

    testClassesDir = sourceSets.integrationTest.output.classesDir
    classpath = sourceSets.integrationTest.runtimeClasspath
}
integrationTest.finalizedBy stopserver

check.dependsOn integrationTest
integrationTest.mustRunAfter test

tasks.withType(Test) {
    reports.html.destination = file("${reporting.baseDir}/${name}")
}

jacoco {
    toolVersion = "0.7.6.201602180812"
}

jacocoTestReport {
    reports {
        xml.enabled false
        csv.enabled false
        html.destination "$buildDir/reports"
    }
}

I've seen existing questions about merging two reports, generating the Junit integration test reports I already have, and similar but ultimately unhelpful questions about Maven and Ant. The closest thing I found was this, but nothing I've tried adapting from it has been fruitful. There does seem to be a similar question, but with less of their build.gradle, and the only reply is a 0-up-vote, not-accepted response by the author of the question in the previous link.

Since this is already pretty long, I didn't want to over-provide even more than is here but I'm happy to provide more if anything is unclear.

I've verified that nothing as silly as unit test results overwriting integration tests is happening - running integration tests and jacoco without regular tests doesn't even produce analogous files.

Is there anything I can do to get integration test coverage?

[First edit] I've created a small Github repo that has everything needed to reproduce this problem: https://github.com/micseydel-tile/gradle-jacoco-integration-test

like image 459
micseydel Avatar asked Oct 10 '16 22:10

micseydel


2 Answers

You can make both the test tasks write to the same destination file and they append to the existing file if any. This way you can run either of the test tasks and see the coverage individually in the HTML report. This code snippet is from your small github repo

`task integrationTest(type: Test) {jacoco {
    append = true
    destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
    classDumpFile = file("$buildDir/jacoco/classpathdumps")
}
 testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath}`

you can simply add the jacoco code block and turn on append.

like image 155
Krithika Baskaran Avatar answered Nov 08 '22 13:11

Krithika Baskaran


I finally could get aggregated report by the following approach: Root build.gradle -

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
}

Run gradle codeCoverageReport

like image 25
Ashwini Mutalik Desai Avatar answered Nov 08 '22 14:11

Ashwini Mutalik Desai