Show Code Coverage in SonarQube for Maven Projects

Recently we started using SonarQube for code quality, security checks and code coverage reports for our projects. SonarQube is an open source static code analyzer, covering 27 programming languages. It helped us to standardize our coding standards and write clean code, making sure no code with code smells goes to production. Everything worked well with SonarQube for all our projects, except it was showing 0% code coverage for all our projects despite having working unit tests.

After good amount of research on google we found the solution, but we were not alone who are facing this issue. There are many like us who are facing the zero code coverage issue with SonarQube, and only a few of them were able to fix the issue. So I decided to share this solution which can help others as well.

Why is Code Coverage important for us?

Code coverage is an important metric for the application, which shows how much portion of your code was executed, or how many lines of code are yet to be covered with your tests. Higher code coverage implies that a large portion of your code is executed by your tests and successful execution of tests means the code covered in the code coverage report is working fine. So higher code coverage can be interpreted as more reliable code. In some tech giants, minimum 80% coverage rule is being followed, which means the build won’t go to production if code coverage for that build is less than 80%. Code coverage provides a detailed view on what part of your application is tested and what all branches got missed in your tests which helps to plan new tests to write.

All our projects are maven based and use JUnit and Mockito to write unit tests. Jacoco was our choice for generating the code coverage report for our projects, but there are many more tools available in the community to generate the code coverage reports. For example, Cobertura is one of the widely used code coverage tools. So before integrating coverage reports with SonarQube, it is important to understand how to configure the maven plugin for jacoco.

Working with jacoco-maven-plugin

If you are using Jacoco for a code coverage report for a maven project you need to set up jacoco-maven-plugin in your pom.xml file. To configure jacoco-maven-plugin, you need to add these lines in the <plugins> section of your pom.xml:

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

Jacoco-maven-plugin provides many maven goals to configure for your project. Let’s have a look at frequently used maven goals for the plugin:

  • prepare-agent: prepare-agent goal is important to setup the runtime agent for code coverage. This goal sets some important parameters and argLine which are required to run the agent and prepare execution info for the code coverage report. With this goal you can configure how to generate the execution info file for the coverage reports. Here is the minimal configuration required for this goal:
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/jacoco-ut.exec</destFile>
</configuration>
</execution>

As shown above you need to give a unique id to all your execution goals and for prepare-agent goal, you need to configure the destination of the execution file with <destFile> configuration.

  • prepare-agent-integration: If you have integration tests setup for your project then you need to configure how execution file gets generated for these tests, similar to shown above for unit tests. Make sure you provide a different path for execution file or set <append> configuration field to true to append execution info for integration test to existing execution info file.
  • report: This goal is important to generate the code coverage reports in multiple formats (HTML, XML and CSV) from execution info. In this goal you can configure classes to exclude from the report or classes to include and output directory and encoding of the reports. Make sure <dataFile> configuration is pointing to execution info file generated in prepare-agent goal. Here is the minimal configuration required for JUnit test code coverage:
<execution>
<id>default-report</id>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/jacoco-ut.exec</dataFile>
<outputEncoding>UTF-8</outputEncoding>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
  • report-integration: Similar to the previous goal, you can provide configurations for generating code coverage reports in different formats for your integration tests. If you have configured a different execution file path for integration test then make sure to use it as a <dataFile> in the <configuration>.
  • check: This is an important goal to automate your builds by applying constraints based on the code coverage. With the check goal, you can configure rules for your project to meet on code coverage, for example more than 80% code coverage, otherwise your build will fail. Here is the configuration for the same:
<execution>
<id>default-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/jacoco-ut.exec</dataFile>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>INSTRUCTION</counter>
<value>COVEREDRATIO</value>
<minimum>0.80</minimum>
</limit>
</limits>
</rule>
</rules>
</configuration>
</execution>

You can apply many more rules for your build based on the code coverage report. You can read more about these rules on plugin’s documentation: https://www.eclemma.org/jacoco/trunk/doc/check-mojo.html#rules

Once you have configured the jacoco-maven-plugin, you need to run mvn clean install phase to generate the code coverage report. With above configuration, code coverage report must be generated in the build directory(target) in different formats (jacoco.xml, jacoco.csv and index.html).

Integrate Code Coverage with SonarQube

Once you have the coverage report generated, we can easily integrate it with SonarQube. To add code coverage in SonarQube, you just need to define a few properties for sonar-maven-plugin. To add sonar-maven-plugin for your project add these lines in <plugins> section of your pom.xml file:

<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.7.0.1746</version>
</plugin>

After including sonar-maven-plugin into your project you need to define few properties in the pom.xml file. Here are the properties you need to define to integrate code coverage with SonarQube:

<properties>
<java.version>1.8</java.version>
<sonar.language>java</sonar.language>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.coverage.jacoco.xmlReportPaths>${project.build.directory}/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
<sonar.jacoco.reportsPaths>${project.build.directory}/jacoco-ut.exec</sonar.jacoco.reportsPaths>
<sonar.tests>src/test/java</sonar.tests>
<sonar.projectKey>sonar-test</sonar.projectKey>
<sonar.host.url>http://localhost:9000</sonar.host.url>
</properties>

If you are using Cobertura for generating code coverage report then set it as a value of sonar.java.coveragePlugin property. Make sure the value of sonar.coverage.jacoco.xmlReportsPath property points to the xml code coverage report file generated by jacoco-maven-plugin. If you are using Cobertura then point sonar.flex.cobertura.reportPaths property to the generated xml report.

Now to push code coverage report to SonarQube, you need to first generate code coverage report as part of the build. To generate the report run below maven goal:

mvn clean install

Once coverage report is generated, you need to run sonar plugin for analyzing code by SonarQube by executing below maven goal:

mvn sonar:sonar -Dsonar.login=<your-token>

And hurray!! Here is your code coverage report on your SonarQube:

Software Engineer at Newfold Digital