Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Test coverage with JaCoCo

Coverage shows which lines and branches of your code were executed while the tests ran. It answers the question "what did my tests not touch at all?". For Java the standard tool is JaCoCo: it attaches to the test JVM, records executed code and builds a report.

Adding JaCoCo

Add the plugin to build/plugins in pom.xml:

<!-- pom.xml -->
<plugin>
  <groupId>org.jacoco</groupId>
  <artifactId>jacoco-maven-plugin</artifactId>
  <version>0.8.15</version>
  <executions>
    <execution>
      <goals>
        <goal>prepare-agent</goal>
      </goals>
    </execution>
    <execution>
      <id>report</id>
      <phase>test</phase>
      <goals>
        <goal>report</goal>
      </goals>
    </execution>
  </executions>
</plugin>

prepare-agent puts JaCoCo's Java agent into the argLine property before the tests. Surefire picks it up through @{argLine} in its configuration — this is why the Mockito lesson used @{argLine} and not a plain value. report builds the report right after the tests.

Running

mvn test

After the usual test output Maven prints:

[INFO] Tests run: 60, Failures: 0, Errors: 0, Skipped: 2
[INFO]
[INFO] --- jacoco:0.8.15:report (report) @ blog ---
[INFO] Loading execution data file ...\target\jacoco.exec
[INFO] Analyzed bundle 'blog' with 7 classes
[INFO] BUILD SUCCESS

Open target/site/jacoco/index.html in a browser. The report has a table by package and class; clicking a class shows its source code with colored lines:

ColorMeaning
GreenThe line was executed
YellowOnly some branches of a condition were executed
RedThe line was never executed

What the report showed

For the course project the report found two gaps. In InMemoryPostRepository the deleteById method is red — no test calls it. In PriceCalculator the line if (percent < 0 || percent > 100) is yellow: there is a test for 120%, but none for a negative discount. Both are honest hints: write a test for deleting and one for -5.

The same numbers are in target/site/jacoco/jacoco.csv:

GROUP,PACKAGE,CLASS,INSTRUCTION_MISSED,INSTRUCTION_COVERED,BRANCH_MISSED,BRANCH_COVERED,LINE_MISSED,LINE_COVERED,...
blog,com.example.blog,InMemoryPostRepository,7,58,0,2,1,10,...
blog,com.example.blog,PostService,0,73,0,4,0,16,...
blog,com.example.shop,PriceCalculator,0,46,1,5,0,9,...

How much is enough

Coverage shows what was not tested, but says nothing about the quality of what was. A test without assertions executes all lines and gives 100% while checking nothing. Treat the report as a map of blind spots, not as a score. Many teams aim for 70–80% on business logic and do not test trivial code such as getters for the sake of the number.

Common mistake

If Surefire's argLine is written without @{argLine}, it overwrites the value JaCoCo prepared. The tests pass, and the report silently disappears:

<argLine>-javaagent:${org.mockito:mockito-core:jar} -Xshare:off</argLine>
[INFO] --- jacoco:0.8.15:report (report) @ blog ---
[INFO] Skipping JaCoCo execution due to missing execution data file.

Start the value with @{argLine}: <argLine>@{argLine} -javaagent:...</argLine>. Surefire substitutes the JaCoCo agent there at run time.

Thanks for reading!

Donate to the site — we work hard for you.