skip to content

Code Coverage

Wiring the JaCoCo agent in through prepare-agent, generating reports, and failing the build on coverage rules. Asked because many candidates can name a coverage tool but not explain how the agent reaches the test JVM.

on this pageshow

explore

questions

5

How do you set up JaCoCo to measure code coverage in a Maven build, and what does the prepare-agent goal actually do?

level: juniorimportance: must knowfreq 70%

answer

  1. prepare-agent sets argLine
  2. javaagent attaches to test JVM
  3. jacoco.exec output
  4. Surefire/Failsafe read ${argLine}
  5. @{argLine} avoids clobber

basics

~10 s

Add the jacoco-maven-plugin and bind its prepare-agent goal. prepare-agent sets a property (argLine) that adds the JaCoCo Java agent to the JVM running your tests, so it records which lines execute.

solid answer

~40 s

You add jacoco-maven-plugin to the build and bind the prepare-agent goal (usually to the initialize/early phase via the default execution). prepare-agent does not run tests itself; it configures the JaCoCo Java agent and exposes its JVM options in a Maven property named argLine by default. Surefire/Failsafe pick up ${argLine} and prepend it to the test JVM command line, so the agent instruments classes on the fly and writes execution data to target/jacoco.exec. The key gotcha: if you also set argLine manually (e.g. for -Xmx), you must include @{argLine} or set it via a property so you don't clobber JaCoCo's value. Then bind the report goal (typically to the test/verify phase) to turn jacoco.exec into HTML/XML.

code

xml · 16 lines
xml
<plugin>
  <groupId>org.jacoco</groupId>
  <artifactId>jacoco-maven-plugin</artifactId>
  <version>0.8.12</version>
  <executions>
    <execution>
      <id>jacoco-prepare</id>
      <goals><goal>prepare-agent</goal></goals>
    </execution>
    <execution>
      <id>jacoco-report</id>
      <phase>test</phase>
      <goals><goal>report</goal></goals>
    </execution>
  </executions>
</plugin>

go deeper

for a junior

Knows you add jacoco-maven-plugin and bind prepare-agent + report to get a coverage report.

for a middle

Understands prepare-agent populates the argLine property that Surefire/Failsafe consume to attach the agent.

for a senior

Diagnoses empty-coverage problems from argLine clobbering and uses @{argLine} or a custom propertyName.

for a principal

Standardizes coverage wiring across many repos via a parent/BOM, sets propertyName conventions and avoids per-module argLine hacks.

## What code coverage is Code coverage measures which lines/branches of your source code were actually executed while your tests ran. JaCoCo (Java Code Coverage) is the de-facto tool; the `jacoco-maven-plugin` integrates it into Maven. ## How JaCoCo collects data JaCoCo works as a **Java agent** — a `-javaagent:...` JVM argument that instruments bytecode as classes load and records execution counts. To get coverage you must inject that agent into the JVM that runs your tests. ## The prepare-agent goal The `prepare-agent` goal does NOT run tests. Its job is to compute the correct `-javaagent` string and store it in a Maven property. By default that property is named **`argLine`**. Why `argLine`? Because Maven Surefire (unit tests) and Failsafe (integration tests) read a configuration property called `argLine` and prepend it to the forked test JVM's command line. So by writing into `argLine`, JaCoCo transparently attaches itself to the test JVM. The agent writes raw execution data to **`target/jacoco.exec`** by default. ## Wiring it up ```xml <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.12</version> <executions> <execution> <id>prepare-agent</id> <goals><goal>prepare-agent</goal></goals> </execution> <execution> <id>report</id> <phase>test</phase> <goals><goal>report</goal></goals> </execution> </executions> </plugin> ``` The `prepare-agent` execution binds by default to the **initialize** phase, so it runs before tests. ## The argLine clobbering trap If you set `argLine` yourself in Surefire/Failsafe config (e.g. `-Xmx512m`), you overwrite JaCoCo's value and coverage silently becomes empty. Fix by referencing the late-evaluated property: ```xml <configuration> <argLine>@{argLine} -Xmx512m</argLine> </configuration> ``` The `@{...}` syntax forces Surefire to resolve the property late, after prepare-agent has set it. Alternatively, point JaCoCo at a different property via `<propertyName>surefireArgLine</propertyName>` and reference that. ## Output - `target/jacoco.exec` — binary execution data - `target/site/jacoco/` — HTML report (after the `report` goal)

  • Your coverage report is empty (0%) even though tests pass. What's the most likely cause?
    Something overwrote the JaCoCo argLine — e.g. a hardcoded <argLine> in Surefire config without @{argLine}, so the agent never attached. Also check forkCount/tests actually ran.
  • What property does prepare-agent write into and why that name?
    By default the 'argLine' property, because Surefire and Failsafe automatically prepend ${argLine} to the forked test JVM command line.

prepare-agent is like clipping a fitness tracker onto the JVM before it goes for its run — it doesn't run, it just makes sure the tracker is recording.

saying these in an interview costs you the question

  • Saying prepare-agent runs the tests
  • Thinking JaCoCo statically modifies source/class files on disk
  • Not knowing about the argLine clobbering problem

context

open as a page

How do you enforce a minimum coverage threshold in Maven so the build fails when coverage is too low?

level: middleimportance: must knowfreq 60%

basics

~10 s

Bind JaCoCo's check goal and define <rules> with a <limit> — e.g. counter LINE, value COVEREDRATIO, minimum 0.80. If coverage is below the limit, the build fails (typically in the verify phase).

open as a page

After execution data is collected, how do you produce a human- and CI-readable coverage report with JaCoCo, and what formats matter?

level: juniorimportance: should knowfreq 50%

basics

~10 s

Bind the report goal. It reads target/jacoco.exec and your compiled classes to emit HTML (for humans) and XML (for CI tools like SonarQube) in target/site/jacoco/.

open as a page

How do you measure code coverage for integration tests run by the Failsafe plugin, separately from unit tests?

level: seniorimportance: should knowfreq 40%

basics

~10 s

Add a second prepare-agent execution that writes to a separate property (e.g. failsafeArgLine) and a separate destFile (jacoco-it.exec), reference that property in Failsafe's argLine, then run a report on that exec during verify.

open as a page

In a multi-module Maven project, how do you produce a single combined coverage report across all modules?

level: seniorimportance: should knowfreq 35%

basics

~10 s

Create a dedicated 'report' module that depends on all the modules you want measured, and run JaCoCo's report-aggregate goal there. It merges each module's jacoco.exec into one consolidated report.

open as a page