Maven – JaCoCo code coverage example
In this article, we will show you how to use a JaCoCo Maven plugin to generate a code coverage report for a Java project.
Tested with
- Maven 3.5.3
- JUnit 5.3.1
- jacoco-maven-plugin 0.8.2
JaCoCo is an actively developed line coverage tool, that is used to measure how many lines of our code are tested.
1. JaCoCo Maven Plugin
1.1 Declare the following JaCoCo plugin in the pom.xml
file.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<!-- attached to Maven test phase -->
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
It will run the JaCoCo ‘report’ goal during the Maven test phase.
2. Unit Test
2.1 A simple Java code to return a message, and an empty string checking.
package com.mkyong.examples;
public class MessageBuilder {
public String getMessage(String name) {
StringBuilder result = new StringBuilder();
if (name == null || name.trim().length() == 0) {
result.append("Please provide a name!");
} else {
result.append("Hello " + name);
}
return result.toString();
}
}
2.2 Unit test above class.
package com.mkyong.examples;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestMessageBuilder {
@Test
public void testNameMkyong() {
MessageBuilder obj = new MessageBuilder();
assertEquals("Hello mkyong", obj.getMessage("mkyong"));
}
}
2.3 Run mvn test
, the JaCoCo code coverage report will be generated at target/site/jacoco/*
$ mvn clean test
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mkyong.examples.TestMessageBuilder
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.012 s - in com.mkyong.examples.TestMessageBuilder
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- jacoco-maven-plugin:0.8.2:report (report) @ maven-code-coverage ---
[INFO] Loading execution data file D:\maven-examples\maven-code-coverage\target\jacoco.exec
[INFO] Analyzed bundle 'maven-code-coverage' with 1 classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.164 s
[INFO] Finished at: 2018-11-14T16:48:39+08:00
[INFO] ------------------------------------------------------------------------
2.4 Open the target/site/jacoco/index.html
file, review the code coverage report :
- Green – Code is tested or covered.
- Red – Code is not tested or covered.
- Yellow – Code is partially tested or covered.
3. Improving the Unit Test
3.1 Adding one more test for the red line.
package com.mkyong.examples;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestMessageBuilder {
@Test
public void testNameMkyong() {
MessageBuilder obj = new MessageBuilder();
assertEquals("Hello mkyong", obj.getMessage("mkyong"));
}
@Test
public void testNameEmpty() {
MessageBuilder obj = new MessageBuilder();
assertEquals("Please provide a name!", obj.getMessage(" "));
}
}
Review the report again.
$ mvn clean test
target/site/jacoco/index.html
3.2 Add one more test for the yellow line if condition.
package com.mkyong.examples;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestMessageBuilder {
@Test
public void testNameMkyong() {
MessageBuilder obj = new MessageBuilder();
assertEquals("Hello mkyong", obj.getMessage("mkyong"));
}
@Test
public void testNameEmpty() {
MessageBuilder obj = new MessageBuilder();
assertEquals("Please provide a name!", obj.getMessage(" "));
}
@Test
public void testNameNull() {
MessageBuilder obj = new MessageBuilder();
assertEquals("Please provide a name!", obj.getMessage(null));
}
}
Review the report again.
$ mvn clean test
target/site/jacoco/index.html
Finally, all lines are tested, 100% coverage.
4. FAQs
4.1 Make sure lines coverage must meet the minimum 90%.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<!-- Add this checking -->
<execution>
<id>jacoco-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
<rule>
<element>PACKAGE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>0.9</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>
</executions>
</plugin>
The jacoco:check
goal is attached to Maven verify phase.
$ mvn clean verify
[INFO] Analyzed bundle 'maven-code-coverage' with 1 classes
[WARNING] Rule violated for package com.mkyong.examples: lines covered ratio is 0.8, but expected minimum is 0.9
More JaCoCo check examples :
4.2 How to update the default JaCoCo output folder?
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<!-- default target/jscoco/site/* -->
<configuration>
<outputDirectory>target/jacoco-report</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Download Source Code
$ cd maven-code-coverage
$ mvn clean test
# view report at ‘target/site/jacoco/index.html’
I get the below error. I am using Maven 3.6.1, Java 8, Jacoco plugin 0.8.3 (but same error for 0.8.2)
INFO] — jacoco-maven-plugin:0.8.3:report (report) @ RRC —
[INFO] Loading execution data file /Users/acme/dev/src/gitlab/acme/abc/target/jacoco.exec
[INFO] ————————————————————————
[INFO] BUILD FAILURE
[INFO] ————————————————————————
[INFO] Total time: 7.519 s
[INFO] Finished at: 2019-05-03T11:48:26+01:00
[INFO] ————————————————————————
[ERROR] Failed to execute goal org.jacoco:jacoco-maven-plugin:0.8.3:report (report) on project ABC: An error has occurred in JaCoCo report generation.: Error while creating report: Error while analyzing /Users/acme/dev/src/gitlab/acme/abc/target/classes/docs/ABC Release Statement.odt. unexpected EOF -> [Help 1]
[ERROR]
it’s a known problem, please take a look:
https://github.com/jacoco/jacoco/issues/546#issuecomment-305495921
https://github.com/jacoco/jacoco/issues/394
Worked perfectly. This is the best documentation I’ve seen for jacoco around. You would think that the dolts who wrote the code would document how to use their coverage tool.
Did u get the code coverage? I got the reports but code coverage is 0. In eclipse it is showing above 90%.
Error : The POM for org.jacoco:jacoco-maven-plugin:jar:0.8.2 is missing,
How can we use JaCoCo Maven Plugin with mockito. I am using JaCoCo maven plugin in my Spring Boot Application with Mockito but I am always getting 0% coverage.
Can you please help me on this.
Hi .It is only showing for main java file .Not compiling the test java file .Kindly help
Failure to transfer org.jacoco:jacoco-maven-plugin:pom:0.8.2 from https://artifacts.mastercard.int/artifactory/maven-all was cached in
the local repository, resolution will not be reattempted until the update interval of public-snapshots has elapsed or updates are forced.
Original error: Could not transfer artifact org.jacoco:jacoco-maven-plugin:pom:0.8.2 from/to snapshots (https://artifacts.mastercard.int/
artifactory/maven-all): sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I get above error in pom while running this application
What would be the goal command to run jacoco for one specific test case? the Maven test command in 2.3 will run all testcases which in my case is hundreds.
Followed the tutorial. Report generated but code coverage is showing as zerop. Any idea?
[INFO] Scanning for projects…
[INFO]
[INFO] ———————————————————-
[INFO] Building demo1 0.0.1-SNAPSHOT
[INFO] ——————————–[ jar ]———————————
[INFO]
[INFO] — jacoco-maven-plugin:0.8.2:prepare-agent (default) @ demo1 —
[INFO] argLine set to -javaagent:C:\\Users\\Admin\\.m2\\repository\\org\\jacoco\\org.jacoco.agent\\0.8.2\\org.jacoco.agent-0.8.2-runtime.jar=destfile=D:\\algoshack_development\\AlgoAfScripts_02042020_1226\\demo1\\target\\jacoco.exec
[INFO]
[INFO] — maven-resources-plugin:2.6:resources (default-resources) @ demo1 —
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] — maven-compiler-plugin:3.1:compile (default-compile) @ demo1 —
[INFO] Nothing to compile – all classes are up to date
[INFO]
[INFO] — maven-resources-plugin:2.6:testResources (default-testResources) @ demo1 —
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 0 resource
[INFO]
[INFO] — maven-compiler-plugin:3.1:testCompile (default-testCompile) @ demo1 —
[INFO] Changes detected – recompiling the module!
[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
[INFO] Compiling 3 source files to D:\algoshack_development\AlgoAfScripts_02042020_1226\demo1\target\test-classes
[INFO]
[INFO] — maven-surefire-plugin:2.12.4:test (default-test) @ demo1 —
[INFO] Surefire report directory: D:\algoshack_development\AlgoAfScripts_02042020_1226\demo1\target\surefire-reports
——————————————————-
T E S T S
——————————————————-
Running demo2.Test2
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.096 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] — jacoco-maven-plugin:0.8.2:report (report) @ demo1 —
[INFO] Loading execution data file D:\algoshack_development\AlgoAfScripts_02042020_1226\demo1\target\jacoco.exec
[INFO] Analyzed bundle ‘demo1’ with 0 classes
[INFO]
[INFO] — maven-jar-plugin:2.4:jar (default-jar) @ demo1 —
[INFO] Building jar: D:\algoshack_development\AlgoAfScripts_02042020_1226\demo1\target\demo1-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] — maven-install-plugin:2.4:install (default-install) @ demo1 —
[INFO] Installing D:\algoshack_development\AlgoAfScripts_02042020_1226\demo1\target\demo1-0.0.1-SNAPSHOT.jar to C:\Users\Admin\.m2\repository\Demo\demo1\0.0.1-SNAPSHOT\demo1-0.0.1-SNAPSHOT.jar
[INFO] Installing D:\algoshack_development\AlgoAfScripts_02042020_1226\demo1\pom.xml to C:\Users\Admin\.m2\repository\Demo\demo1\0.0.1-SNAPSHOT\demo1-0.0.1-SNAPSHOT.pom
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 2.877 s
[INFO] Finished at: 2020-04-28T20:03:53+05:30
[INFO] ————————————————————————
Hello!
I’ve followed your tutorial, but for some reason, my report doesn’t inlude line by line coverage. I can see for each function the percentage of coverage, but I cannot click on it to see my java code as it was covered by the tests. Any help ?
Thank you!
Excellent tutorial! Works without any problems with the latest JaCoCo version, 0.8.5. Thank you!
not working i get:
[WARNING] The POM for org.jacoco:jacoco-maven-plugin:jar:0.8.2 is missing, no dependency information available
[WARNING] Error injecting: org.jacoco.maven.AgentMojo
java.lang.NoClassDefFoundError: org/jacoco/core/runtime/AgentOptions
[ERROR] Failed to execute goal org.jacoco:jacoco-maven-plugin:0.8.2:prepare-agent (default)
Execution default of goal org.jacoco:jacoco-maven-plugin:0.8.2:prepare-agent failed: A required class was missing while executing org.jacoco:jacoco-maven-plugin:0.8.2:prepare-agent: org/jacoco/core/runtime/AgentOptions
Do you had any solution for this error?
I want Jacoco to generate reports even if the build fails.