Over a million developers have joined DZone.

Separating Code Coverage With Maven, Sonar and Jacoco

· Java Zone

Navigate the Maze of the End-User Experience and pick up this APM Essential guide, brought to you in partnership with CA Technologies

In this example I will expand upon my previous example of keeping your unit and integration tests in separate packages, and explain how to also produce code coverage statistics.

For this I continue to use Maven, whilst adding Sonar and Jacoco to provide the code coverage.You can run the example below, but you will need to read the first article here to understand it.http://johndobie.blogspot.com/2011/06/seperating-maven-unit-integration-tests.html

1.1 Example Structure

Here we have the typical maven structure and our new folder \src\integrationtest\java



1.2 Running the Example

The full code is hosted at google code.  Use the following commands to check it out and run it.

svn co https://designbycontract.googlecode.com/svn/trunk/sonar
cd sonar
mvn –Psonar,it clean install sonar:sonar

You need to have sonar running.  Instructions on the install can be found here.http://docs.codehaus.org/display/SONAR/Install+Sonar

Go to sonar web interface and click on 'configure widgets' to add the IT coverage widget.You will also have to add the Jacoco plugin.

You can see the Jenkins build here:

http://ec2-75-101-221-43.compute-1.amazonaws.com:8080/job/maven-sonar-jaccoco/

You can see the Sonar build here

http://ec2-75-101-221-43.compute-1.amazonaws.com:9000/dashboard/index/1


1.3  Results of running the example

  • The tests in the standard maven test structure are run during the unit test phase as usual.
  • The tests in the integrationtest directory are run during the integration test phase.
  • The test classes and results are placed in a seperate integrationtest directory in target


The jacoco test coverage reports are placed in the /target/coverage-reports directory



In Sonar, the unit test coverage is shown in one widget and the integration test coverage in another.




2.0 How does it work?

The basic steps are as follows. The details for each are below.

 

  • Run the maven integration-test lifecycle with Jacoco coverage enabled for unit and integration tests.
  • Run Sonar pointing to the coverage results.
  • Put it all in a profile so it can be used conveniently.

2.1  Running the tests with Jacoco

We first define the directories for the jacoco coverage files.

<coverage.reports.dir>
  ${basedir}/target/coverage-reports
</coverage.reports.dir>
<sonar.jacoco.reportPath>
  ${coverage.reports.dir}/jacoco-unit.exec
</sonar.jacoco.reportPath>
<sonar.jacoco.itReportPath>
  ${coverage.reports.dir}/jacoco-it.exec
</sonar.jacoco.itReportPath>
<sonar.jacoco.jar>
  ${basedir}/lib/jacocoagent.jar
</sonar.jacoco.jar>

Then we start the unit tests by running the standard the surefire plugin with the Jacoco agent pointing to ${sonar.jacoco.reportPath}.  This is used to store the unit test code coverage results.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.7.2</version>
    <configuration>
    <b><argLine>          
       -javaagent:${sonar.jacoco.jar}=destfile=${sonar.jacoco.reportPath}       
    </argLine></b>
    <test>**/*.java</test>
    </configuration>
</plugin>

For the Integration tests we use the failsafe plugin and point the Jacoco agent to ${sonar.jacoco.itReportPath}.  This is used to store the integration test code coverage results.

<plugin>
  <artifactId>maven-failsafe-plugin</artifactId>
  <version>2.8</version>
  <configuration>         
    <argLine>
      -javaagent:${sonar.jacoco.jar}=destfile=${sonar.jacoco.itReportPath}
    </argLine>
   <testClassesDirectory>
      ${integrationOutputDirectory}
   </testClassesDirectory>
   <reportsDirectory>
     ${integrationOutputDirectory}/failsafe-reports
   </reportsDirectory>
   <test>**/*.java</test>
   <additionalClasspathElements>
     <additionalClasspathElement>
       ${integrationSourceDirectory}/resources</additionalClasspathElement>
     </additionalClasspathElements>
   </configuration>
   <executions>
     <execution>
       <goals>
          <goal>integration-test</goal>
       </goals>
     </execution>
  </executions>
</plugin>

When these are run they will produce the following 2 coverage files.



Running Sonar

We use the standard sonar:sonar target however we first compile and run our tests. This will cause the unit and integration tests to run as described above.

The following parameter tells Sonar to use jacoco as the default code coverage plugin

<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>

 

We then specify for Sonar to re-use the created coverage files.

<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>

We then run the whole process by running the following Maven command

mvn –Psonar,it clean install sonar:sonar

This produces the results discussed above in section 1.3. Results Of Running the Examples


2.3  Using a Profile

The sonar profile tidies all of these pieces up into one reusable unit. The full profile is here.https://designbycontract.googlecode.com/svn/trunk/sonar/pom.xml

2.4  Next Steps

You can look at a multi-module example of the same technique here:http://johndobie.blogspot.com/2011/06/maven-multi-module-with-sonar-and.html

From http://johndobie.blogspot.com/2011/06/seperating-test-code-coverage-with.html

Thrive in the application economy with an APM model that is strategic. Be E.P.I.C. with CA APM.  Brought to you in partnership with CA Technologies.

Topics:

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}