DEV Community

Cover image for How to generate an aggregated code coverage report for all Gradle subprojects
Jakub Zalas
Jakub Zalas

Posted on

How to generate an aggregated code coverage report for all Gradle subprojects

When using Gradle's multi-project builds, test and coverage reports are generated separately in each build directory of every sub-project.

To make Azure Pipelines happy I needed to generate an index file for all coverage-reports:

// build.gradle.kts

plugins {
    base
    kotlin("jvm") version "1.3.72" apply false
}

allprojects {
    group = "com.kaffeinelabs"
    version = "1.0.0-SNAPSHOT"
    apply(plugin = "jacoco")
}
tasks.register<JacocoReport>("jacocoRootReport") {
    subprojects {
        this@subprojects.plugins.withType<JacocoPlugin>().configureEach {
            this@subprojects.tasks.matching {
                it.extensions.findByType<JacocoTaskExtension>() != null }
           .configureEach {
                sourceSets(this@subprojects.the<SourceSetContainer>().named("main").get())
                executionData(this)
            }
        }
    }

    reports {
        xml.isEnabled = true
        html.isEnabled = true
    }
}

Jacoco configuration for sub-projects should be done as per usual.

To generate the report the jacocoRootReport task needs to be added to the build:

./gradlew test jacocoRootReport

If you also need to aggregate test reports, I covered it in another article:

Discussion (1)

Collapse
niv_da profile image
NivDa • Edited on

Thanks! it works!!.
i needed to add the following block:

repositories {
mavenCentral()
}
in order to fix a missing dependency error.

it will be nice if you can add some details about what each part does and maybe how to exclude paths/modules from the coverage report.

I also added the same but for JacocoCoverageVerification as follows:

tasks.register< JacocoCoverageVerification >("jacocoRootVerification") {

violationRules {
    rule {
        limit {
            minimum = "0.8".toBigDecimal()
        }
    }

    rule {
        limit {
            counter = "BRANCH"
            minimum = "0.7".toBigDecimal()
        }
    }

    subprojects {
        this@subprojects.plugins.withType<JacocoPlugin>().configureEach {
            this@subprojects.tasks.matching {
                it.extensions.findByType<JacocoTaskExtension>() != null }
                    .configureEach {
                        sourceSets(this@subprojects.the<SourceSetContainer>().named("main").get())
                        executionData(this)
                    }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

}

still trying to figure out how to exclude some paths from the report and the coverage calculation.

And again, thank you very much!