Code coverage is a measure of how many lines of our code are covered by the Unit Test. This is very helpful, so we can evaluate the quality of our code, how many of our code has been and have not been covered by the Unit Test. In this tutorial, I introduce to you all an Apache Maven plugin called JaCoCo Maven Plugin that helps us to measure the code coverage.
I will create a new Maven project with a simple example with Unit Test as follows:
JUnit dependency is as follows:
1 2 3 4 5 6 |
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> |
Calculation class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.huongdanjava.mavenjacocoplugin; public class Calculation { public int add(int a, int b) { return a + b; } public int sub(int a, int b) { if (a >= b) { return a - b; } return b - a; } } |
CalculationTest class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package com.huongdanjava.mavenjacocoplugin; import static org.junit.Assert.assertEquals; import org.junit.Before; import org.junit.Test; public class CalculationTest { private Calculation calculation; @Before public void init() { calculation = new Calculation(); } @Test public void testAdd() { assertEquals(4, calculation.add(1, 3)); } @Test public void testSub() { assertEquals(2, calculation.sub(7, 5)); assertEquals(9, calculation.sub(3, 12)); } } |
JaCoCo Maven Plugin:
1 2 3 4 5 |
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.2</version> </plugin> |
OK, let’s get started.
JaCoCo Maven Plugin defines a lot of goals, but there is a goal that we need to declare so that the plugin can calculate the code coverage for us, that’s goal: prepare-agent. Suppose, I now declare this goal in the example project above:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.8.1</version> <executions> <execution> <id>agent-for-ut</id> <goals> <goal>prepare-agent</goal> </goals> </execution> </executions> </plugin> |
then right-click on the project, select Run As, and select Maven test, then you’ll see the results in the Eclipse Console tab as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
[INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building maven-jacoco-plugin 0.0.1-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- jacoco-maven-plugin:0.8.2:prepare-agent (agent-for-ut) @ maven-jacoco-plugin --- [INFO] argLine set to "-javaagent:/Users/Khanh/.m2/repository/org/jacoco/org.jacoco.agent/0.8.2/org.jacoco.agent-0.8.2-runtime.jar=destfile=/Users/khanh/Working/Workspace Eclipse/maven-jacoco-plugin/target/jacoco.exec" [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-jacoco-plugin --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ maven-jacoco-plugin --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-jacoco-plugin --- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ maven-jacoco-plugin --- [INFO] Nothing to compile - all classes are up to date [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-jacoco-plugin --- [INFO] Surefire report directory: /Users/khanh/Working/Workspace Eclipse/maven-jacoco-plugin/target/surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- objc[1640]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/bin/java (0x1052214c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_131.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x10531b4e0). One of the two will be used. Which one is undefined. Running com.huongdanjava.mavenjacocoplugin.CalculationTest Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.095 sec Results : Tests run: 2, Failures: 0, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.771 s [INFO] Finished at: 2018-10-12T20:59:30+07:00 [INFO] Final Memory: 15M/220M [INFO] ------------------------------------------------------------------------ |
As you can see in the line:
1 2 |
[INFO] --- jacoco-maven-plugin:0.8.2:prepare-agent (agent-for-ut) @ maven-jacoco-plugin --- [INFO] argLine set to "-javaagent:/Users/Khanh/.m2/repository/org/jacoco/org.jacoco.agent/0.8.2/org.jacoco.agent-0.8.2-runtime.jar=destfile=/Users/khanh/Working/Workspace Eclipse/maven-jacoco-plugin/target/jacoco.exec" |
a file named jacoco.exec was created in the target directory of the project. This is the file containing the code coverage report which JaCoCo Maven Plugin created. This file is in binary format so we can not see it directly, but we still have another way to view this report result using the goal report of JaCoCo Maven Plugin.
Let’s run the Maven project with the goal jacoco:report to see how the results:
At this point, if you check the target directory for the project, you will see a directory named site containing the code coverage information that JaCoCo Maven Plugin created after we run the project with goal report:
Open the index.html file in the target/site/jacoco directory and you will see the following output:
This is all information about code coverage in our project. Can you easily see how much code coverage for each package in our project?
You can click on each package to see details:
As you can see, we can see code coverage details for each method. You can also click on each method to see what code we have covered.
By default, the code that is covered will be high light by green, and vice versa will be red. So if I now modify the code of the CalculationTest, remove:
1 |
assertEquals(9, calculation.sub(3, 12)); |
in the testSub() method, you will see code coverage report for class Calculation now as follows: