Enterprise Java

Creating Code Coverage Reports for Unit And Integration Tests with The JaCoCo Maven Plugin

When I started using Java 7, I noticed right away that the Cobertura Maven plugin doesn’t support it. This was a huge problem to me because I used code coverage reports every day. I did some research and found the JaCoCo code coverage library. It looked interesting and I decided to give it a shot.

The problem was that configuring it was really hard and took a lot of time. I read numerous tutorials just to find out that the instructions given in them did not work for me. Then I ran into this blog post and everything fall into place.

Although that blog post was extremely valuable to me, it is a bit vague. I felt that a more detailed explanation about the usage of the JaCoCo Maven plugin would be valuable.

This blog post describes how we can create code coverage reports for unit and integration tests by using the JaCoCo Maven plugin.

The requirements of our build are following:

  • Our build must create code coverage reports for both unit and integration tests when the tests are run.
  • The code coverage reports must be created in separate directories. In other words, the code coverage report for unit tests must be created into a different directory than the code coverage report for integration tests.

Let’s get started.

Note: The example application of this blog post is based on the example application of my blog post called Integration Testing with Maven. If you have not read it yet, I recommend that you read it before reading this blog post.

Configuring The JaCoCo Maven Plugin

We use the JaCoCo Maven plugin for two purposes:

  1. It provides us an access to the JaCoCo runtime agent which records execution coverage data.
  2. It creates code coverage reports from the execution data recorded by the JaCoCo runtime agent.

We can configure the JaCoCo Maven plugin by following these steps:

  1. Add the JaCoCo Maven plugin to the plugins section of our POM file.
  2. Configure the code coverage report for unit tests.
  3. Configure the code coverage report for integration tests.

These steps are described with more details in the following.

Adding The JaCoCo Maven Plugin to The POM File

We can add the JaCoCo Maven plugin to our POM file by adding the following plugin declaration to its plugins section:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.6.3.201306030806</version>
</plugin>

Let’s move on and find out how we can configure the code coverage report for our unit tests.

Configuring The Code Coverage Report for Unit Tests

We can configure the code coverage report for unit tests by adding two executions to the plugin declaration. These executions are described in the following:

  1. The first execution creates a property which points to the JaCoCo runtime agent. Ensure that the execution data is written to the file target/coverage-reports/jacoco-ut.exec. Set the name of the property to surefireArgLine. The value of this property is passed as a VM argument when our unit tests are run.
  2. The second execution creates the code coverage report for unit tests after unit tests have been run. Ensure that the execution data is read from the file target/coverage-reports/jacoco-ut.exec and that the code coverage report is written to the directory target/site/jacoco-ut.

The relevant part of our plugin configuration looks as follows:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.6.3.201306030806</version>
    <executions>
        <!--
           Prepares the property pointing to the JaCoCo runtime agent which
           is passed as VM argument when Maven the Surefire plugin is executed.
       -->
        <execution>
            <id>pre-unit-test</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
                <!--
                   Sets the name of the property containing the settings
                   for JaCoCo runtime agent.
               -->
                <propertyName>surefireArgLine</propertyName>
            </configuration>
        </execution>
        <!--
           Ensures that the code coverage report for unit tests is created after
           unit tests have been run.
       -->
        <execution>
            <id>post-unit-test</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
            <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
                <!-- Sets the output directory for the code coverage report. -->
                <outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

Let’s find out how we can configure the code coverage report for our integration tests.

Configuring The Code Coverage Report for Integration Tests

We can configure the code coverage report for integration tests by adding two executions to the plugin declaration. These executions are described in the following:

  1. This first execution creates a property which points to the JaCoCo runtime agent. Ensure that the execution data is written to the file target/coverage-reports/jacoco-it.exec. Set the name of the property to failsafeArgLine. The value of this property is passed as a VM argument when our integration tests are run.
  2. Create an execution which creates the code coverage report for integration tests after integration tests have been run. Ensure that the execution data is read from the file target/coverage-reports/jacoco-it.exec and that the code coverage report is written to the directory target/site/jacoco-it.

The relevant part of our plugin configuration looks as follows:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.6.3.201306030806</version>
    <executions>
        <!-- The Executions required by unit tests are omitted. -->
        <!--
           Prepares the property pointing to the JaCoCo runtime agent which
           is passed as VM argument when Maven the Failsafe plugin is executed.
       -->
        <execution>
            <id>pre-integration-test</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
                <!--
                   Sets the name of the property containing the settings
                   for JaCoCo runtime agent.
               -->
                <propertyName>failsafeArgLine</propertyName>
            </configuration>
        </execution>
        <!--
           Ensures that the code coverage report for integration tests after
           integration tests have been run.
       -->
        <execution>
            <id>post-integration-test</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>report</goal>
            </goals>
            <configuration>
                <!-- Sets the path to the file which contains the execution data. -->
                <dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
                <!-- Sets the output directory for the code coverage report. -->
                <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

That’s it. We have now configured the JaCoCo Maven plugin. Our next step is to configure the Maven Surefire plugin. Let’s find out how we can do this.

Configuring The Maven Surefire Plugin

We use the Maven Surefire plugin to run the unit tests of our example application. Because we want to create a code coverage report for our unit tests, we have to ensure that the JaCoCo agent is running when our unit tests are run. We can ensure this by adding the value of the surefireArgLine property as the value of the argLine configuration parameter.

The configuration of the Maven Surefire plugin looks as follows (the required change is highlighted):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.15</version>
    <configuration>
        <!-- Sets the VM argument line used when unit tests are run. -->
        <argLine>${surefireArgLine}</argLine>
        <!-- Skips unit tests if the value of skip.unit.tests property is true -->
        <skipTests>${skip.unit.tests}</skipTests>
        <!-- Excludes integration tests when unit tests are run. -->
        <excludes>
            <exclude>**/IT*.java</exclude>
        </excludes>
    </configuration>
</plugin>

We are almost done. The only thing left for us to do is to configure the Maven Failsafe plugin. Let’s find out how we can do it.

Configuring The Maven Failsafe Plugin

The integration tests of our example application are run by the Maven Failsafe plugin. Because we want to create a code coverage report for our integration tests, we have to ensure that the JaCoCo agent is running when our integration tests are run. We can do this by adding the value of the failsafeArgLine property as the value of the argLine configuration parameter.

The configuration of the Maven Failsafe plugin looks as follows (the required change is highlighted):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.15</version>
    <executions>
        <!--
            Ensures that both integration-test and verify goals of the Failsafe Maven
            plugin are executed.
        -->
        <execution>
            <id>integration-tests</id>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
            <configuration>
                <!-- Sets the VM argument line used when integration tests are run. -->
                <argLine>${failsafeArgLine}</argLine>
                <!--
                    Skips integration tests if the value of skip.integration.tests property
                    is true
                -->
                <skipTests>${skip.integration.tests}</skipTests>
            </configuration>
        </execution>
    </executions>
</plugin>

Creating Code Coverage Reports

We have now successfully finished the required configuration. Let’s see how we can create code coverage reports for unit and integration tests.

The example application of this blog post has three build profiles which are described in the following:

  • The dev profile is used during development and it is the default profile of our build. When this profile is active, only unit tests are run.
  • The integration-test profile is used to run integration tests.
  • The all-tests profile is used to run both unit and integration tests.

We can create different code coverage reports by running the following commands at command prompt:

  • The command mvn clean test runs unit tests and creates the code coverage report for unit tests to the directory target/site/jacoco-ut.
  • The command mvn clean verify -P integration-test runs integration tests and creates the code coverage report for integration tests to the directory target/site/jacoco-it.
  • The command mvn clean verify -P all-tests runs unit and integration tests and creates code coverage reports for unit and integration tests.

That’s all for today. As always, the example application of this blog post is available at Github.
 

Petri Kainulainen

Petri is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button