Reputation: 207
I'm trying to generate unit test code coverage data for sonar for a multi-module maven project, and not getting correct results.
The project structure is similar to the following:
I am using the jacoco maven plugin to generate jacoco.exec
files, and the sonar maven plugin to analyse the code (including the jacoco.exec
files).
These files are generated during the process-tests
phase, as follows:
<properties>
<jacoco.report.path>${project.build.directory}/jacoco.exec</jacoco.report.path>
<sonar.jacoco.reportPath>${jacoco.report.path}</sonar.jacoco.reportPath>
</properties>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.4.201502262128</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<phase>process-test-classes</phase>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${jacoco.report.path}</destFile>
</configuration>
</execution>
</executions>
</plugin>
When I run mvn clean install I can see that there is a jacoco.exec
file created for each module:
$ find . -name '*.exec'
./moduleA/target/jacoco.exec
./moduleB/moduleB1/target/jacoco.exec
./moduleB/moduleB2/target/jacoco.exec
./moduleC/target/jacoco.exec
When I run mvn sonar:sonar I see that the Jacoco sensor runs for all modules, but only seems to work with the first module. Subsequent modules show Coverage information was not collected
:
[INFO] [17:13:58.333] Sensor JaCoCoSensor
[INFO] [17:13:58.350] Analysing moduleA\target\jacoco.exec
[INFO] [17:13:58.374] No information about coverage per test.
[INFO] [17:13:58.374] Sensor JaCoCoSensor (done) | time=41ms
...
[INFO] [17:14:02.202] Sensor JaCoCoSensor
[INFO] [17:14:02.261] Analysing moduleB\moduleB1\target\jacoco.exec
[WARN] [17:14:02.334] Coverage information was not collected. Perhaps you forget to include debug information into compiled classes?
[INFO] [17:14:02.334] Sensor JaCoCoSensor (done) | time=132ms
...
I'm not sure why there's no coverage information in the second and subsequent modules, since maven-compiler-plugin
includes debug information by default, and to be safe I also ran mvn clean install -Dmaven.compiler.debug=true
but got the same results.
As a consequence of this, when I inspect the project in the sonar server it shows code coverage just for the first module: moduleA
. No code coverage information for the other modules is present.
Apparently the solution here is to generate only a single jacoco.exec
file, so that when the jacoco-maven-plugin
executes it appends the result for each module to that file, so that sonar can work its magic correctly.
Accordingly, I modified my parentPom/pom.xml
file as follows:
<properties>
<!-- single jacoco.exec file relative to root directory of the project -->
<jacoco.report.path>${session.executionRootDirectory}/code-coverage/jacoco.exec</jacoco.report.path>
<sonar.jacoco.reportPath>${jacoco.report.path}</sonar.jacoco.reportPath>
</properties>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.4.201502262128</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<phase>process-test-classes</phase>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${jacoco.report.path}</destFile>
<append>true</append> <!-- now appending to single jacoco.exec file -->
</configuration>
</execution>
</executions>
</plugin>
This means that after unit tests have run, the jacaco agent is invoked
Now when I run mvn clean install I see only one jacoco.exec
file:
$ find . -name '*.exec'
./code-coverage/target/jacoco.exec
But when I run mvn sonar:sonar the JaCoCoSensor does not seem to be invoked and the project on the sonar server has no code coverage at all.
What am I doing wrong here? How do I get sonar to analyse code coverage for all modules in my maven project?
Do I need to modify the maven-surefire-plugin
in some way?
I am using SonarQube 5.1, JDK 1.8, jacoco-maven-plugin 0.7.4.201502262128
Upvotes: 6
Views: 3732
Reputation: 10833
JaCoCo sensor will only load coverage for the classes you covered in your module.
This means that if for some reason the jacoco.exec in your module B does not contain coverage information about the .class files of this module then it won't load any coverage (even if you covered classes in another module).
Upvotes: 1