Add code coverage metrics to your maven project
While working on the bitcoinj project I have added support for code coverage collection and tracking. This post summarizes steps you have to take to add that for your own maven projects.
- Figure out what type of code coverage you want
For the bitcoinj library it is important to have a “unit test coverage” - it works by verifying which parts of the source code are reached during unit testing phase during build process. This type of code coverage is the one we usually mean when we say “code coverage”, but it’s important to know that you can also instrument a live application and see which parts of application are used and how frequently - you should consult for example wikipedia here: http://en.wikipedia.org/wiki/Code_coverage or here: http://en.wikipedia.org/wiki/Java_Code_Coverage_Tools and choose the tool you want to use. Because for libraries we have to focus on “unit test coverage” I have choosen JaCoCo
-
Add JaCoCo maven plugin Adding JaCoCo maven plugin is quite straightforward, those are the parts you have to add to your pom.xml:
<!-- Code coverage plugin, generates coverage report to target/site/jacoco/ To skip coverage generation add -Djacoco.skip=true --> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.7.2.201409121644</version> <configuration> <excludes> <exclude>**/Protos*.class</exclude> <!-- Exclude generated protobuf classes --> <exclude>org/bitcoinj/jni/*</exclude> <!-- Exclude JNI classes --> <exclude>org/bitcoin/*</exclude> <!-- Exclude native classes --> </excludes> </configuration> <executions> <execution> <id>pre-unit-test</id> <goals> <goal>prepare-agent</goal> </goals> <configuration> <destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile> <propertyName>surefireArgLine</propertyName> </configuration> </execution> <execution> <id>post-unit-test</id> <phase>test</phase> <goals> <goal>report</goal> </goals> <configuration> <dataFile>${project.build.directory}/coverage-reports/jacoco.exec</dataFile> <outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory> </configuration> </execution> <execution> <id>default-report</id> <phase>prepare-package</phase> <goals> <goal>report</goal> </goals> </execution> </executions> </plugin>
Important things to note here:
in excludes we can exclude files from being included in the report - it’s worth to exclude automatically generated files the jacoco.exec file will be useful in the next steps as well
Additionally you have to update configuration for maven-surefire-plugin:
<!-- Unit tests plugin, to skip runing test add -Dmaven.test.skip -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<argLine>${surefireArgLine}</argLine> <!-- This is required for code coverage to work. -->
</configuration>
</plugin>
These 2 plugins work together - JaCoCo will be used as a Java agent during the unit testing phase. From now on you can just run
mvn clean test
Which will rerun all tests and recreate coverage report. to skip running tests and generating coverage report run maven commands like this:
mvn clean package -Dmaven.test.skip=true -Djacoco.skip=true
- Setup http://coveralls.io support
As a additional step (especially for projects using travis-ci) you can configure http://coveralls.io/ to keep track of your code coverage over time.
It’s enough to add this maven plugin:
<!-- Coveralls is a online code coverage tool -->
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>3.0.1</version>
</plugin>
And then in the .travis.yml
add this:
after_success:
- mvn jacoco:report coveralls:report
-
Add Intellij IDEA integration Following guide works for Intellij Community edition (I have tested this on version 14 but it should work on earlier versions as well) To add Intellij integration you have to do following things:
Hit Ctrl+Alt+6 Select previously generated file jacoco.exec The code coverage report should refresh every time you run mvn test