Gradle 6, Jacoco and allJvmArgs don't go well togheter

2020-05-04

Recently, I had to migrate a Gradle 4 project to the newer Gradle 6. One problem that I found was that the Test Coverage Plugin for Jacoco did not work anymore. After some debugging in the Gradle source code, I found out that Jacoco uses the org.gradle.process.internal.DefaultJavaForkOptions which is used to create the startup parameters for the JVM process that handles the execution of Jacoco. Unfortuantely, the tests set also JVM options, e.g. for increasing heap, using the setter allJVMargs. The following example build.gradle of a gradle multi-project illustrates this:

group 'org.example'
version '1.0-SNAPSHOT'

allprojects {
    apply plugin: 'java'
    apply plugin: 'eclipse'
    apply plugin: 'maven'
    apply plugin: 'jacoco'
    apply plugin: 'maven-publish'
    apply plugin: 'java-library'
    dependencies {
        testImplementation 'org.junit.jupiter:junit-jupiter:5.5.2'
        testImplementation 'org.junit.vintage:junit-vintage-engine:5.5.2'
        testImplementation 'org.junit.platform:junit-platform-launcher:1.5.2'
    }

    jacoco {
        reportsDir = file("$buildDir/reports/jacoco")
    }

    jacocoTestReport {
        reports {
            html.enabled = true
            xml.enabled = true
            csv.enabled = true
            html.destination file("${buildDir}/jacocoHtml")
        }
    }

    test {
        useJUnitPlatform()
        allJvmArgs = ["-Xmx1024m"]
        jacoco {
        }

        finalizedBy 'jacocoTestReport'
    }
}

Actually allJVMArgs seems to clear DefaultJavaForkOptions that have been set before by the Jacoco Gradle plugin. This results in the execution of the JUnit test without generating the Jacoco exec files, which are needed to create the Jacoco reports.

This behavior seems to be new, maybe already introduced in Gradle 5, which is a non-intuitive behavior.

The remedy for this problem is to use jvmArgs instead of allJvmArgs which acutally appends the arguments instead of deleting them. Thus, the above code would look something like this:

group 'org.example'
version '1.0-SNAPSHOT'

allprojects {
    ...

    test {
        useJUnitPlatform()
        jvmArgs = ["-Xmx1024m"]
        jacoco {
        }

        finalizedBy 'jacocoTestReport'
    }
}

Published First Version of Timetracker application