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

  1. Maven 3.5.3
  2. JUnit 5.3.1
  3. jacoco-maven-plugin 0.8.2
Note
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.

pom.xml

	<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.

MessageBuilder.java

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.

TestMessageBuilder.java

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/*

Terminal

$ 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 :

  1. Green – Code is tested or covered.
  2. Red – Code is not tested or covered.
  3. Yellow – Code is partially tested or covered.

3. Improving the Unit Test

3.1 Adding one more test for the red line.

TestMessageBuilder.java

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.

Terminal

$ mvn clean test

target/site/jacoco/index.html

3.2 Add one more test for the yellow line if condition.

TestMessageBuilder.java

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.

Terminal

$ 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%.

pom.xml

	<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.

Terminal

$ 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
Note
More JaCoCo check examples :

4.2 How to update the default JaCoCo output folder?

pom.xml

	<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

$ git clone https://github.com/mkyong/maven-examples.git
$ cd maven-code-coverage

$ mvn clean test
# view report at ‘target/site/jacoco/index.html’

References

  1. Wikipedia : Java code coverage tools
  2. JaCoCo Java Code Coverage Library
  3. JaCoCo in Eclipse IDE

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

avatar
4 Comment threads
0 Thread replies
1 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
Venkatesh KadalirobertPat Recent comment authors
newest oldest most voted
Pat
Guest
Pat

Error : The POM for org.jacoco:jacoco-maven-plugin:jar:0.8.2 is missing,

Venkatesh Kadali
Guest
Venkatesh Kadali

I want Jacoco to generate reports even if the build fails.

robert
Guest
robert

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]

Pat
Guest
Pat

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