Measuring Overall Code Coverage in Multi-Module Maven Project
Measuring Overall Code Coverage in Multi-Module Maven Project
Join the DZone community and get the full member experience.
Join For FreeLearn how integrating security into DevOps to deliver "DevSecOps" requires changing mindsets, processes and technology.
But apart from separating varying tests from each other how can we use available mechanisms to invoke both unit and integration tests and measure theirs code coverage? I want to achieve such situation (maybe except the number of tests because I usually want to have a little bit more :)) on the Sonar dashboard:
We'll work on a simple maven project with the popular layout:
Both modules contains two "production" classes: one to be tested using unit tests and other for integration testing. Structure of the project looks like below (I hope class names are pretty obvious):
Now it's time to adjust our project to handle suitable coverage measurement tool. I prefer JaCoCo because it is well integrated with Sonar and can be adapted to work with different test types. As a test framework we'll use TestNG. So let's add to our master pom.xml following dependencies:
<dependencies> <dependency> <groupid>org.testng</groupid> <artifactid>testng</artifactid> <version>6.7</version> <scope>test</scope> </dependency> <dependency> <groupid>org.jacoco</groupid> <artifactid>org.jacoco.core</artifactid> <version>0.6.2.201302030002</version> <scope>test</scope> </dependency> </dependencies>In TestNG we can combine tests in groups by using @Test(group="groupName"), and we're going to use this functionality and use "unit" group for all unit tests and "int" group for integration ones.
We also must set sonar properties:
<properties> <!-- select JaCoCo as a coverage tool --> <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin> <!-- force sonar to reuse reports generated during build cycle --> <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis> <!-- set path for unit tests reports --> <sonar.jacoco.reportPath>${project.basedir}/target/jacoco-unit.exec</sonar.jacoco.reportPath> <!-- all modules have to use the same integration tests report file --> <sonar.jacoco.itReportPath>${project.basedir}/../target/jacoco-it.exec</sonar.jacoco.itReportPath> </properties>The next thing we've to do is to configure Maven plugins. To the standard surefire configuration we'll add exclusion of the "int" tests group:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.14</version> <configuration> <excludedGroups>int</excludedGroups> </configuration> </plugin>Now a little bit more complex situation with configuring failsafe plugin. Failsafe is more suitable for integration tests because when a test fails, it does not immediately abort (instead it lets the clean-up by processing post-integration-test phase).
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <version>2.14</version> <configuration> <!-- property set by jacoco-maven-plugin --> <argLine>${itCoverageAgent}</argLine> <groups>int</groups> <!-- by default only IT*, *IT and *ITCase classes are included --> <includes> <include>**/*.java</include> </includes> </configuration> <executions> <execution> <id>integration-test</id> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> </execution> </executions> </plugin>The last step is adding jacoco plugin:
<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.6.2.201302030002</version> <executions> <!-- prepare agent for measuring unit tests --> <execution> <id>prepare-unit-tests</id> <goals> <goal>prepare-agent</goal> </goals> <configuration> <destFile>${sonar.jacoco.reportPath}</destFile> </configuration> </execution> <!-- prepare agent for measuring integration tests --> <execution> <id>prepare-integration-tests</id> <goals> <goal>prepare-agent</goal> </goals> <phase>pre-integration-test</phase> <configuration> <destFile>${sonar.jacoco.itReportPath}</destFile> <propertyName>itCoverageAgent</propertyName> </configuration> </execution> </executions> </plugin>Now invoke normal maven build (by typing mvn clean install). We can see in the compilation output that JaCoCo plugin is invoked both for unit
[INFO] --- jacoco-maven-plugin:0.6.2.201302030002:prepare-agent (prepare-unit-tests) @ first ---
and integration tests
[INFO] --- jacoco-maven-plugin:0.6.2.201302030002:prepare-agent (prepare-integration-tests) @ first ---
While build finished successful we can proceed to running Sonar: mvn sonar:sonar
I hope everything went ok, and now you can admire well measured code coverage on your Sonar dashboard!
Learn how enterprises are using tools to automate security in their DevOps toolchain with these DevSecOps Reference Architectures.
Published at DZone with permission of Jakub Kubrynski , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}