Monday, 16 January 2012

Unit Test Code Coverage With Maven And Jacoco

Insert title here It’s easy to collect unit test code coverage because all of the common tools are geared up for it.
This article will explain how you can add unit test coverage to your Maven application in 10 minutes.
We will use the excellent Jacoco code coverage library to show how easy it is.

Examples

All of the examples come from this article.
http://johndobie.blogspot.com/2011/11/test-doubles-with-mockito.html

You can check them out from here
svn co
https://designbycontract.googlecode.com/svn/trunk/examples/testing/test-doubles


With Maven 3 installed, you can run them with this command.
mvn clean package

What is Jacoco

Jacoco is a free code coverage library for Java. http://www.eclemma.org/jacoco/
I use it because it is very simple to add to all types of build including ANT and Maven, and it is also very simple to add to Java containers or a standalone JVM.

How Does it Work?


Jacoco uses the standard JVM Tool Interface. http://java.sun.com/developer/technicalArticles/J2SE/jvm_ti/
In simple terms you attach a Jacoco agent to a JVM when it starts. It was introduced in JDK 5 for monitoring and profiling JVMs and being able to dynamically modify Java classes as they're being loaded.
Whenever a class is loaded Jacoco can instrument the class so it can see when the class is called and what lines are called. That’s how it builds up the coverage statistics. This is all done on the fly.
By default the results file is created when the JVM terminates.
You can also run the agent in server mode which allows you to trigger a dump of the results.

How do you attach the agent to the JVM?

This is a very simple process. You must specify where the jacoco jar is located and then you pass some parameters to define how the agent is to run.
-javaagent:[yourpath/]jacocoagent.jar=[option1]=[value1],[option2]=[value2]

A typical run might look like this
-javaagent:jacoco.jar=destfile=${sonar.jacoco.itReportPath},includes=com.dbc.*
A full reference is found here. http://www.eclemma.org/jacoco/trunk/doc/agent.html

Jacoco Support For Maven

The docs for the maven plugin are defined here. http://www.eclemma.org/jacoco/trunk/doc/maven.html
First we need to add the plugin itself.

  org.jacoco
  jacoco-maven-plugin
  0.5.5.201112152213

We can then define where the jacoco reports are output.

  ${basedir}/target/coverage-reports/jacoco-unit.exec
  ${basedir}/target/coverage-reports/jacoco-unit.exec

Finally we need to define the following 2 executions to make the agent run before the tests are run and also to make sure that the jacoco report task is run when package is executed.

  
    jacoco-initialize
    
      prepare-agent
    
  
  
    jacoco-site
    package
    
      report
    
  


All this together is shown here

 
  org.jacoco
  jacoco-maven-plugin
  0.5.5.201112152213
  
   ${basedir}/target/coverage-reports/jacoco-unit.exec
   ${basedir}/target/coverage-reports/jacoco-unit.exec
  
  
   
    jacoco-initialize
    
     prepare-agent
    
   
   
    jacoco-site
    package
    
     report
    
   
  
 
 
  org.apache.maven.plugins
  maven-compiler-plugin
  
   1.5
   1.5
  
 



To run the examples execute the following command.
mvn clean package

Results.

The results are published in /target/site/jacoco.

3 comments:

  1. hi,

    Could you provide an example for doing the same in multi-module maven project. I want to create a single jacoco.exec file which i want to be shown in the Sonar dashboard under Junit code coverage. I have tried your earlier post etc. but i am still unable to get it displayed on the SONAR.

    ReplyDelete
  2. Thank you for the article John. I am taken with the fact you took the time to explain not just how to plug it in, but also how it works under the hood. That's uncommon, I feel.

    I noticed that in your execution parts of pom jacoco-initialize has no phase associated. While this will work, Eclipse will complain.

    ReplyDelete