Gradle jacoco coverage report with more than one submodule(s)?

18,872

Solution 1

Finally I found this plugin: https://github.com/palantir/gradle-jacoco-coverage that did the job for me:

root gradle.build

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        // see https://jcenter.bintray.com/com/android/tools/build/gradle/
        classpath 'com.android.tools.build:gradle:2.1.0'
        // classpath 'com.android.tools.build:gradle:2.2.0-alpha1'

        // https://github.com/palantir/gradle-jacoco-coverage
        classpath 'com.palantir:jacoco-coverage:0.4.0'      
    }
}

// https://github.com/palantir/gradle-jacoco-coverage
apply plugin: 'com.palantir.jacoco-full-report'

all subprojects that has

apply plugin: 'jacoco'

are included in the report.

Solution 2

This works for me

plugins {
    id 'org.kordamp.gradle.jacoco' version '0.43.0'
}

config {
    coverage {
        jacoco {
            enabled
            aggregateExecFile
            aggregateReportHtmlFile
            aggregateReportXmlFile
            additionalSourceDirs
            additionalClassDirs
        }
    }
}

https://kordamp.org/kordamp-gradle-plugins/#_org_kordamp_gradle_jacoco

Solution 3

One possible solution (with some sonar specific parts):

def getJacocoMergeTask(Project proj){
    def jmClosure =  {
        doFirst {
            logger.info "${path} started"
            executionData.each { ed ->
                logger.info "${path} data: ${ed}"
            }
        }
        onlyIf {
            executionData != null && !executionData.isEmpty()
        }
    }

    def jacocoMerge = null
    if(!proj.tasks.findByName('jacocoMerge')){

        jacocoMerge = proj.tasks.create('jacocoMerge', JacocoMerge.class)
        jacocoMerge.configure jmClosure

        // sonar specific part
        proj.rootProject.tasks["sonarqube"].mustRunAfter jacocoMerge

        proj.sonarqube {
            properties {
                property "sonar.jacoco.reportPaths", jacocoMerge.destinationFile.absolutePath
            }
        }
        // end of sonar specific part

        logger.info "${jacocoMerge.path} created"
    } else {
        jacocoMerge = proj.tasks["jacocoMerge"]
    }
    jacocoMerge
}


afterEvaluate { project ->
    def jacocoMerge = getJacocoMergeTask(project)

    project.tasks.withType(Test) { task ->
        logger.info "${jacocoMerge.path} cfg: ${task.path}"

        task.finalizedBy jacocoMerge
        jacocoMerge.dependsOn task

        task.doLast {
            logger.info "${jacocoMerge.path} executionData ${task.path}"
            jacocoMerge.executionData task
        }

        def cfg = configurations.getByName("${task.name}Runtime")
        logger.info "${project.path} process config: ${cfg.name}"

        cfg.getAllDependencies().withType(ProjectDependency.class).each { pd ->
            def depProj = pd.dependencyProject
            logger.info "${task.path} dependsOn ${depProj.path}"
            def jm = getJacocoMergeTask(depProj)

            task.finalizedBy jm
            jm.dependsOn task

            task.doLast {
                logger.info "${jm.path} executionData ${task.path}"
                jm.executionData task
            }
        }
    }
}

This will merge all the executionData from all the projects, that used a certain project during testing as a dependency.

Share:
18,872

Related videos on Youtube

k3b
Author by

k3b

Main intrest currently [java] development for [android] and the hybris platform; also [c#], [tdd], [bdd] ([gherkin], [specflow]) , [agile] ([scrum])

Updated on June 04, 2022

Comments

  • k3b
    k3b almost 2 years

    Does anybody know how to configure a gradle file for java jacoco report that contain codecoverage of more than one gradle submodule?

    my current approach only shows codecoverage of the current submodule but not codecoverage of a sibling-submodul.

    I have this project structure

    - build.gradle (1)
    - corelib/
        - build.gradle (2)
        - src/main/java/package/Core.java
    - extlib/
        - build.gradle (3)
        - src/main/java/package/Ext.java
        - src/test/java/package/Integrationtest.java
    

    when i execute gradlew :extlib:check :extlib:jacocoTestReport the junit-test "Integrationtest.java" is executed and a codecoverage report is generated that does not contain codecoverage for corelib classes like Core.java

    The result should include the codecoverage of Ext.java and Core.java

    I already read

    but found no clues

    here is content of the gradle files

    // root build.gradle (1)
    // Top-level build file where you can add configuration options 
    // common to all sub-projects/modules.
    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.1.0'
        }
    }
    allprojects {
        repositories {
            jcenter()
        }
    }
    

    // build.gradle (2) subproject build file for corelib.
    apply plugin: 'java'
    apply plugin: 'jacoco'
    
    dependencies {
    }
    
    jacocoTestReport {
        reports {
            xml.enabled true
            html.enabled true
        }
    }
    

    // build.gradle (3) subproject build file for extlib.
    apply plugin: 'java'
    apply plugin: 'jacoco'
    
    dependencies {
        compile project(':corelib')
        testCompile 'junit:junit:4.11'
    
        // this does not compile
        // jacocoTestReport project(':pixymeta-core-lib')
    }
    
    jacocoTestReport {
        reports {
            xml.enabled true
            html.enabled true
        }
    }
    
    // workaround because android-studio does not make the test resources available
    // see https://code.google.com/p/android/issues/detail?id=64887#c13
    task copyTestResources(type: Copy) {
        from sourceSets.test.resources
        into sourceSets.test.output.classesDir
    }
    processTestResources.dependsOn copyTestResources
    

    [Update 2016-08-01]

    thanks to @Benjamin Muschko i also tried in the root gradle file

    // https://discuss.gradle.org/t/merge-jacoco-coverage-reports-for-multiproject-setups/12100/6
    // https://docs.gradle.org/current/dsl/org.gradle.testing.jacoco.tasks.JacocoMerge.html
    task jacocoMerge(type: JacocoMerge) {
       subprojects.each { subproject ->
          executionData subproject.tasks.withType(Test)
       } 
    
    }
    

    but got error message (with gradle-2.14)

    * What went wrong:
    Some problems were found with the configuration of task ':jacocoMerge'.
    > No value has been specified for property 'jacocoClasspath'.
    > No value has been specified for property 'executionData'.
    > No value has been specified for property 'destinationFile'.
    

    there is also the gradle plugin https://github.com/paveldudka/JacocoEverywhere where i have asked for mulit-submodule support https://github.com/paveldudka/JacocoEverywhere/issues/16

    [update 2016-08-01] i found a working solution based on https://github.com/palantir/gradle-jacoco-coverage

    See my own answer below

  • Daniel Ocampo
    Daniel Ocampo about 7 years
    Thanks for posting the solution. So far seems to be working well, but I have one issue: for some reason is not working for my app module. Did it happen to you? How did you configure the app module? I applied the jacoco plugin but it won't appear in the report. Thanks
  • José Andias
    José Andias about 6 years
    According to the README, this plugin seems to be considered obsolete as of Gradle 3.4.
  • Ravirajsinh Vaghela
    Ravirajsinh Vaghela almost 4 years
    but from gradle 6+ some of the JacocoReport properties are read only like additionalClassDirs, additionalSourceDirs, classDirectories, executionData ect. So in gradle 6+ it wont work. See docs.gradle.org/6.0/dsl/…
  • aarbor
    aarbor about 3 years
    This plugin was long overdue and has made my setup much simpler! Note to viewers, the syntax has slightly changed from the above, so check latest documentation
  • Wei Yuan
    Wei Yuan about 3 years
    @aarbor thanks for that, I've made the changes to reflect latest version
  • Edna Krabappel
    Edna Krabappel about 2 years
    In my case also JaCoCo works for app module, but not for all the other lib modules. After adding a task jacocoMerge(type: JacocoMerge){} to my app level build gradle, how can I trigger this?