How do you enable JaCoCo code-coverage reporting in a Gradle build, and what does applying the jacoco plugin give you?
answer
- core plugin, apply by id
- no dependency needed
- agent attaches to Test task
- writes build/jacoco/test.exec
- registers jacocoTestReport
basics
~10 sAdd jacoco to the plugins {} block. Gradle then adds a jacocoTestReport task and a jacoco {} extension, and instruments your tests so coverage data is collected when you run test.
solid answer
~40 sJaCoCo is enabled by applying Gradle's built-in `jacoco` plugin in the `plugins {}` block — no external dependency or version is needed because it ships with Gradle. Applying it does three things: it adds the `jacoco {}` extension (where you can set `toolVersion`), it registers a `JacocoReport` task named `jacocoTestReport` for the `test` task, and it configures the `test` task so the JVM runs with the JaCoCo agent attached, writing execution data to `build/jacoco/test.exec`. The report task is *not* part of `check` by default and does not run automatically when you run `test`; you invoke `./gradlew test jacocoTestReport` or wire a dependency. You typically also pin `toolVersion` so the agent matches your JDK bytecode level.
code
kotlin · 10 linesplugins {
java
jacoco
}
jacoco {
toolVersion = "0.8.12"
}
// Run: ./gradlew test jacocoTestReportgo deeper
Know that you add jacoco to the plugins block and run jacocoTestReport to get coverage.
Explain the agent/exec-data vs report split and that the report task isn't run by test automatically.
Discuss toolVersion pinning against JDK bytecode levels and where outputs land for CI consumption.
Frame coverage as a build-policy concern: standardizing the plugin + version across modules via a convention plugin so every team reports consistently.
## What JaCoCo is JaCoCo ("Java Code Coverage") is a library that measures which lines, branches, and instructions of your code were exercised while tests ran. It works by **instrumenting** bytecode on the fly via a Java agent: when the test JVM starts, the agent records every executed instruction into a binary **execution-data file** (an `.exec` file). A separate **report** step reads that `.exec` file plus your compiled `.class` files and source files to produce human- and machine-readable coverage reports. ## The Gradle `jacoco` plugin Gradle ships a core plugin you apply by id — there is no Maven-style dependency to declare: ```kotlin plugins { java jacoco } ``` Applying it performs three jobs: 1. **Adds the `jacoco {}` extension** of type `JacocoPluginExtension`, where you configure the agent/tooling: most commonly `toolVersion = "0.8.12"` and optionally `reportsDirectory`. 2. **Configures every `Test` task** so the JaCoCo agent is attached. After a test run, execution data lands in `build/jacoco/<testTaskName>.exec` (e.g. `build/jacoco/test.exec`). 3. **Registers a `jacocoTestReport` task** of type `JacocoReport`, pre-wired to read the `test` task's execution data and the main source set's classes/sources. ## Pinning the tool version The JaCoCo agent must understand the bytecode your JDK produces. With newer JDKs you frequently bump `toolVersion` to a release that supports that class-file major version, otherwise instrumentation fails with an "Unsupported class file major version" error. Set it once in the extension: ```kotlin jacoco { toolVersion = "0.8.12" } ``` ## It does not run by itself A common surprise: `jacocoTestReport` is **not** a dependency of `check` and `test` does **not** trigger it. Running `./gradlew test` produces only the `.exec` data; you must also run the report task (or wire it — covered separately). The report task is also `UP-TO-DATE`/cacheable based on its inputs, so re-running without new test execution data skips work. ## Where outputs land - Execution data: `build/jacoco/test.exec` - HTML report (when enabled): `build/reports/jacoco/test/html/index.html` - XML report (when enabled): `build/reports/jacoco/test/jacocoTestReport.xml`
- Does running `./gradlew test` produce a coverage report?No. The `test` run only writes execution data to `build/jacoco/test.exec`. You must also run `jacocoTestReport` (or wire it as a finalizer/dependency) to render HTML/XML.
- Why might you need to set `toolVersion`?The bundled JaCoCo version may not support the class-file major version emitted by a newer JDK, causing instrumentation failures. Pinning a newer `toolVersion` fixes it.
saying these in an interview costs you the question
- Claiming you must add a `jacoco` dependency in `dependencies {}` — it is a core plugin applied by id.
- Assuming the report is generated automatically by the `test` task.