JaCoCo Configuration using Gradle’s Kotlin DSL
Recently I used Kotlin DSL for writing Gradle scripts in a spring boot project. As Gradle’s Kotlin DSL is quite new, the documentation and community support was less compared to the default Groovy DSL. So I found it hard to configure JaCoCo for test coverage. In this blog I will share how I added test coverage in my project:
Before getting into the implementation let me put down the requirements:
- A
test
task to run all unit tests - A
testCoverage
task that runs all unit tests, generate coverage report and run verification - A way to ignore classes and files from coverage verification
1. A test
task to run all unit tests
When using a JVM language plugin like Java in Gradle, a task called test is automatically provided. This task runs all tests under src/test by default.
We just have to add a config to run the tests using a test runner (JUnit in my case):
val test by tasks.getting(Test::class) {
useJUnitPlatform { }
}
2. A testCoverage
task that runs all unit tests, generate coverage report and verify the report
First, we need to add the JaCoCo library by adding it in the plugins section:
plugins {
...
jacoco
}
By default, JaCoCo gives two tasks called jacocoTestReport and jacocoTestCoverageVerification for generating coverage report and running verification respectively.
As I need only HTML report I added a jacocoTestReport config like this:
tasks.jacocoTestReport {
reports {
xml.isEnabled = false
csv.isEnabled = false
html.isEnabled = true
html.destination = file("$buildDir/reports/coverage")
}
}
And I want to fail the task when the coverage falls below 90%. So I added a jacocoTestCoverageVerification like this:
tasks.jacocoTestCoverageVerification {
violationRules {
rule {
limit {
minimum = "0.9".toBigDecimal()
}
}
}
}
We can generate coverage report and run verification by doing:
./gradlew test jacocoTestReport jacocoTestCoverageVerification
It will be good if we have a wrapper task called testCoverage
that runs test
, jacocoTestReport
, and jacocoTestCoverageVerification
. Let's add this new task:
val testCoverage by tasks.registering {
group = "verification"
description = "Runs the unit tests with coverage."
dependsOn(":test", ":jacocoTestReport", ":jacocoTestCoverageVerification")
val jacocoTestReport = tasks.findByName("jacocoTestReport")
jacocoTestReport?.mustRunAfter(tasks.findByName("test"))
tasks.findByName("jacocoTestCoverageVerification")?.mustRunAfter(jacocoTestReport)
}
Now to run we just have to do:
./gradlew testCoverage
3. A way to ignore classes and files from coverage verification
I want to ignore certain files and classes from the JaCoCo verification. To do that we can modify the classDirectories
or sourceDirectories
used by jacocoTestCoverageVerification
task like this:
tasks.jacocoTestCoverageVerification {
violationRules {
rule {
limit {
minimum = "0.9".toBigDecimal()
}
}
}
classDirectories.setFrom(
sourceSets.main.get().output.asFileTree.matching {
// exclude main()
exclude("com/example/helloworld/ApplicationKt.class")
}
)
}
Now if we run ./gradlew testCoverage
, main()
function will be excluded from verification.
A full gradle script containing similar implementation is available here: spring-boot-helloworld.