Recently I’ve been trying to configure code coverage with Gradle and Jacoco. I started on the official docs page here:
https://docs.gradle.org/current/userguide/jacoco_plugin.html
However, this page wasn’t that helpful. One key requirement I have is that I want to be able to enable and disable Jacoco. For many Gradle plugins you can specify “apply false” when you add them to your Gradle build file, like this:
plugins { id 'java-platform' id 'maven-publish' id 'org.jetbrains.gradle.plugin.idea-ext' version '1.0' id 'org.owasp.dependencycheck' version '5.3.2.1' apply false id 'com.github.spotbugs' version '4.5.0' apply false id 'com.intershop.gradle.jaxb' version '4.4.2' apply false }
This doesn’t work for the Jacoco plugin! The Jacoco plugin is a “built in” one, which means that as soon as it is on the classpath, it will instrument your class files, even if you don’t specify to run the Jacoco coverage report. Thankfully I found a good blog post here:
https://poetengineer.postach.io/post/how-to-conditionally-enable-disable-jacoco-in-gradle-build
I largely followed those steps to add a separate jacoco.gradle file, with my contents being:
apply plugin: 'jacoco' jacoco { toolVersion = '0.8.6' } test { jacoco { // we have to exclude some classes from byte code instrumentation // the standard instrumentation adds a boolean array to a class called $jacocoData excludes += ['**/SomeClass', '**/AnotherClass' ] } }
Then in the main build.gradle file I enabled this on required sub-projects with:
ext.jacocoEnabled = System.properties.getProperty("jacocoEnabled") ?: "false" subprojects { if (some logic here) { // only apply JaCoCo code coverage if the -PjacocoEnabled flag has been set. if (jacocoEnabled.toBoolean()) { apply from: rootProject.file("jacoco.gradle") }
After this I was able to run Jacoco and get a coverage report with:
./gradlew build jacocoTestReport -DjacocoEnabled
You may need to exclude some files from instrumentation. e.g. tests / code that use reflection to inspect objects may not run correctly if the code is instrumented. I found it very useful to be able to rerun a single test in a single sub-module after updating the excludes list in the jacoco.gradle file. You can do that with a command like this:
./gradlew :module-name:sub-module-name:clean :module-name:sub-module-name:test --tests="com.orgname.YourTest" -PjacocoEnabled=true