Jacoco code coverage reports not generating for integration tests, not showing in sonar - maven

I had configured Jacoco + Sonar in Maven. I am able to generate the coverage reports for unit tests & display the coverage in Sonar as well. But, unable to generate the reports for integration tests. "jacoco-it.exec" is generated but, when I go and open the index.html, it looks empty. But, there are many integration tests got executed & passed as well. In jacoco-sessions.html, it is clearly mentioned about all the classes which are used internally. Please help me if you have any idea what is wrong in the below code wrt integration tests. I have configured Sonar also properly & given the path to pick up the results for integrations tests. Please see once and help me if you have any idea. pom.xml:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
<dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
</configuration>
<executions>
<execution>
<id>pre-integration-test</id
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent</goal>
</goals> </execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<systemPropertyVariables>
<jacoco-agent.destfile>${project.build.directory}/coverage-reports/jacoco-it.exec</jacoco-agent.destfile>
</systemPropertyVariables>
<encoding>UTF-8</encoding>
<skipTests>false</skipTests>
<runOrder>alphabetical</runOrder>
<includes>
....<There are integration tests>
</includes>
<excludes>
....
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>

Related

SonarQube coverage is always 0

I have a project that uses SonarQube to analyse my code. As the title suggests, the coverage metric is always appears to be 0 in the SQ report (on my server) despite me having multiple Junit tests. I currently run the following command
clean package deploy sonar:sonar -Dsonar.projectKey=SomeName -Dmaven.test.skip=true
when building my project in Jenkins (Jenkins Maven project).
I had similar issue some time back with different project. I manage to resolved it via this article. However, it didn't help this time. After searching for a bit, I found article 1 and article 2 (as well as some more with similar ideas). Both had some good suggestions but unfortunately nothing worked.
I noticed that I also get the following warning every time (don't know what causes it)
Cobertura report not found at /var/lib/jenkins/jobs/SomeProjectName/workspace/SomeFolderName/target/site/cobertura/coverage.xml
At first, I tried to add cobertura plugin (as suggested here) but that just removed the warning (coverage remained 0 in the report). My current understanding is that it overwrites Jacoco but I failed to find the reason why or solution to it.
My plugins:
<build>
<plugins>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<verbose>true</verbose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<finalName>uber-${project.artifactId}-${project.version}</finalName>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-ut.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-ut.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
</configuration>
</execution>
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
<propertyName>failsafeArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.9.2</version>
<executions>
<execution>
<configuration>
<outputDirectory>${project.basedir}/target/generated-sources</outputDirectory>
<sourceDirectory>${project.basedir}/src/main/resources/</sourceDirectory>
</configuration>
<goals>
<goal>schema</goal>
<goal>protocol</goal>
<goal>idl-protocol</goal>
</goals>
<id>schemas</id>
<phase>generate-sources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
My properties:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>11</java.version>
</properties>
There are a few things that have to be set correctly to result in your test coverage being shown in SonarQube. Some of these settings have defaults that may work, but I try to avoid magic defaults, in favor of ensuring that my settings agree with each other.
Surefire and Jacoco have to have settings that agree with each other, and SonarQube has to know where to find the coverage data file.
I'm going to suggest some property values for you to use.
sonar.coverage.jacoco.xmlReportPaths: ${basedir}/target/jacoco_report/jacoco.xml
jacoco.path: ${basedir}/target/jacoco_report
Then, here is an excerpt for your jacoco plugin:
<!-- 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>
<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 output directory for the code coverage report. -->
<outputDirectory>${jacoco.path}</outputDirectory>
</configuration>
</execution>
Finally, this goes in the configuration block of the Surefire plugin:
<!-- Sets the VM argument line used when unit tests are run. -->
<argLine>${surefireArgLine}</argLine>
However, in your case you have a very high-level issue that would result in zero coverage even if you had all of these settings done correctly. Thanks to #Ian W for pointing this out.
When I saw you write "despite me having multiple Junit tests", I took your word for it that you're actually executing the unit tests. You have "-Dmaven.test.skip=true" on your command line, which causes it to not execute any unit tests. Remove that.
I am using java 11 with maven version 3.8.3 configured with jacoco 0.8.3 plugin.
the Code coverage is operational. SonadeQuebe dont't dispaly 0%
command:
mvn sonar:sonar -Dsonar.projectKey=diag -Dsonar.host.url=http://sonar.XXXXX/sonar -Dsonar.login=xxxx -Dsonar.password=xxxxx
In pom.xml
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jacoco-maven-plugin.version>0.8.3</jacoco-maven-plugin.version>
<sonar-maven-plugin.version>3.4.0.905</sonar-maven-plugin.version>
<sonar.java.codeCoveragePlugin>jacoco</sonar.java.codeCoveragePlugin>
<sonar.tests>${project.basedir}/src/test/</sonar.tests>
...
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>

jacoco including apache in report

i am first time trying jacoco for coverage :
but jacoco reports also include apache dependecies it it.
here is my pom.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.8</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/jacoco.exec</dataFile>
<excludes>
<exclude>*org/apache/*</exclude>
</excludes>
<outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
i tried
<exclude>**/lib/*</exclude>
also. nothing is removing this apache coverage from report.
below is project structure.
for my code below exclude worked
<exclude>**/axis-1.4.jar/**</exclude>

Not able to get it test coverage in sonarqube

[enter image description here][1][enter image description here][2]I know many people got such similar problem. i show many answars, tried the sample code given on sonar site. that sample is working fine. Also i show following link
How to configure multi-module Maven + Sonar + JaCoCo to give merged coverage report?
But nothing seems working in my case. Its not showing IT Test Coverage in sonarqube though mvn clean intsall is making jacoco folder in site where index.html is having coverage report.
i tried almost every thing on net but not able to resolve issue.
its a multi module project
I am using
java8.
sonarqube 4.5.6 with java plugin 2.5.1.
maven 3.0.5
please help me resolve this.
Below is parent module pom file
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<append>true</append>
</configuration>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.basedir}/target/jacoco.exec</destFile>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<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}/../target/jacoco.exec</dataFile>
</configuration>
</execution>
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.basedir}/../target/jacoco-it.exec</destFile>
<propertyName>failsafe.argLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.basedir}/../target/jacoco-it.exec</dataFile>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<!-- Sets the VM argument line used when unit tests are run. -->
<argLine>${surefireArgLine}</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<configuration>
<argLine>${failsafe.argLine}</argLine>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- automatic label creation -->
</plugins>
</build>
<!-- Plugin to generate unit test coverage in SonarQube 4.5.x report. -->
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<use>false</use>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>${maven-surefire-report-plugin.version}</version>
<configuration>
<alwaysGenerateFailsafeReport>true</alwaysGenerateFailsafeReport>
<alwaysGenerateSurefireReport>true</alwaysGenerateSurefireReport>
<aggregate>true</aggregate>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<configuration>
<excludes>
<exclude>**/*.mar</exclude>
<exclude>${jacoco.excludePattern}</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</reporting>
Properties in same pom file
<sonar.java.codeCoveragePlugin>jacoco</sonar.java.codeCoveragePlugin>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath> <!-- This is the default, put here to be explicit -->
<sonar.jacoco.itReportPath>${project.basedir}/../target/jacoco-it.exec</sonar.jacoco.itReportPath>
<sonar.language>java</sonar.language>
<sonar.java.binaries>${project.basedir}/../target/classes</sonar.java.binaries>
<jacoco-maven-plugin.version>0.7.4.201502262128</jacoco-maven-plugin.version>
<maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
<maven-surefire-report-plugin.version>2.19.1</maven-surefire-report-plugin.version>
<maven-surefire-plugin.version>2.16</maven-surefire-plugin.version>
<maven-failsafe-plugin.version>2.16</maven-failsafe-plugin.version>
mvn clean install is creating jacoco folder with index.html for test coverage but mvn sonar:sonar is not showing it in sonarqube
what mistake i am making.
in mvn sonar:sonar, it builds successfully and one of the line is JaCoCoSensor: JaCoCo report not found.
what could be the reason
i seriously feel this a bug with jacoco or sonarqube. May be it would not be compatible with java 8 or something. I tried almost every thing. Many things are deprecated with sonar java plugin 2.5.1. Please help me, i need the solution desperately
Just tried it, and the sample project works perfectly. Please make sure you do the following:
git clone https://github.com/SonarSource/sonar-examples.git
cd projects/languages/java/code-coverage/combined ut-it/combined-ut-it-multimodule-maven-jacoco
mvn clean package
mvn sonar:sonar
Also - not sure if this is related, but you're using a very old version of the SQ Java plugin (2.5.1). I can only advise you to update it to latest version.
Well, i am not sure why the above code is not working but i tried same thing bit differently and miracle happened. Let me give the solution what it worked for me.
I removed the below code from parent pom and put it in all child pom. Also since i was using it in child module i used target/jacoco.exec instead of ${project.basedir}/../target/jacoco.exec and same for jacoco-it.exec.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>target/jacoco.exec</destFile>
<propertyName>surefireArgLine</propertyName>
<append>true</append>
</configuration>
</execution>
<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>target/jacoco.exec</dataFile>
</configuration>
</execution>
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>target/jacoco-it.exec</destFile>
<propertyName>failsafe.argLine</propertyName>
<append>true</append>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>target/jacoco-it.exec</dataFile>
</configuration>
</execution>
</executions>
</plugin>
Additional information. following plugin which i mentioned in my question is not required if Test coverage is required only in sonar report. If there is requirement for code report separately then its required
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<configuration>
<excludes>
<exclude>**/*.mar</exclude>
<exclude>${jacoco.excludePattern}</exclude>
</excludes>
</configuration>
</plugin>

Merging Integration and Unit test reports with JaCoCo

I am generating failsafe and surefire reports with maven with the JaCoCo plugin, but I can only manage to get them in separate reports. I would like to have a overall coverage view (merge between both Unit Tests and Integration Tests) as well.
After what I think was a thorough google search I could only found a way to do this with Sonar. Is there any simpler way to do this?
Related question: Maven separate Unit Test and Integration Tests
I recently implemented this: after some headaches and a lot of testing, I have a configuration that works beautifully.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>pre-integration-test</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
<propertyName>testArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
</configuration>
</execution>
<execution>
<id>post-unit-test</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
</configuration>
</execution>
<execution>
<id>merge-results</id>
<phase>verify</phase>
<goals>
<goal>merge</goal>
</goals>
<configuration>
<fileSets>
<fileSet>
<directory>${project.build.directory}/coverage-reports</directory>
<includes>
<include>*.exec</include>
</includes>
</fileSet>
</fileSets>
<destFile>${project.build.directory}/coverage-reports/aggregate.exec</destFile>
</configuration>
</execution>
<execution>
<id>post-merge-report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/coverage-reports/aggregate.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-aggregate</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<argLine>${surefireArgLine}</argLine>
<skipTests>${skip.unit.tests}</skipTests>
<includes>
<include>**/*UT.java</include>
<include>**/*MT.java</include>
<include>**/*Test.java</include>
</includes>
<skipTests>${skipUTMTs}</skipTests>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<skipTests>${skipTests}</skipTests>
<skipITs>${skipITs}</skipITs>
<argLine>${testArgLine}</argLine>
<excludes>
<exclude>**/*UT*.java</exclude>
</excludes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
As you can see, there are 6 distinct Jacoco executions to run the tests, merge the files and create an aggregate report. On top of the Jacoco config, you also need to configure Surefire and Failsafe to take an argument from Jacoco (Surefire runs the unit tests and Failsafe runs the integration tests).
All of the configuration that I used should be there, what you do with it is your design architecture to make it fit within your desired requirements. Personally, I recommend a look into what I exclude and include within surefire and failsafe if you are having issues with files not being read.
Not the answer you're looking for, but still...
In most cases, you should not merge coverage from unit and integration tests.
The value of unit tests is that they improve the design of your application and ensure that corner cases of your code is working correctly. You should try to have a high branch coverage of your unit tests.
The value of your integration tests is that they ensure that the main use cases of your application are working correctly and that the whole stack is integrated correctly. You should try to have a high functional coverage for your integration tests. (But it is fairly hard to measure functional coverage with a tool).
If you need integration tests to improve your branch coverage, that's a strong indication that you should review the design of your code. And if you already have a high branch coverage without integration tests, adding them should not modify significantly your metrics.
You should take a look into the documentation of JaCoCo Maven plugin which contains a merge goal.
Maybe more nice way is to achieve is use same jacoco file, but let it another tests, which works for us - unit and it tests.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.1</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<skip>${maven.surefire.skipTests}</skip>
<propertyName>maven.surefire.argLine</propertyName>
<!-- using the same dest file for both UT and IT -->
<destFile>${sonar.jacoco.reportPath}</destFile>
</configuration>
</execution>
<execution>
<id>default-prepare-agent-integration</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<skip>${maven.failsafe.skipTests}</skip>
<propertyName>maven.failsafe.argLine</propertyName>
<!-- append to the UT dest file -->
<destFile>${sonar.jacoco.reportPath}</destFile>
<append>true</append>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>${maven.surefire.skipTests}</skipTests>
<failIfNoTests>${maven.surefire.failIfNoTests}</failIfNoTests>
<!-- allow argLine to be modified by other plugins, e.g. jacoco -->
<argLine>#{maven.surefire.argLine}</argLine>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<skipTests>${maven.failsafe.skipTests}</skipTests>
<failIfNoTests>${maven.failsafe.failIfNoTests}</failIfNoTests>
<!-- allow argLine to be modified by other plugins, e.g. jacoco -->
<argLine>#{maven.failsafe.argLine}</argLine>
</configuration>
</plugin>
Building on top of the answer of Chad, here is my configuration. It is configured as a separate profile named jacoco so I can turn it on and off easily. It uses only the default configuration. It can create a separate code coverage report for unit tests, separate code coverage report for integration tests and also a combined code coverage report.
<profile>
<id>jacoco</id>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>pre-integration-test</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
</execution>
<execution>
<id>post-integration-test</id>
<goals>
<goal>report-integration</goal>
</goals>
</execution>
<execution>
<id>merge-results</id>
<phase>verify</phase>
<goals>
<goal>merge</goal>
</goals>
<configuration>
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<includes>
<include>*.exec</include>
</includes>
<excludes>
<exclude>aggregate.exec</exclude>
</excludes>
</fileSet>
</fileSets>
<destFile>${project.build.directory}/aggregate.exec</destFile>
</configuration>
</execution>
<execution>
<id>post-merge-report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/aggregate.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-aggregate</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
I get the point where Unit tests should really be at the source of code coverage... but sometimes, one would like to have the ability to know right? Here is what I did (this is from using gradle).
plugins {
[...]
id 'jacoco'
}
[...]
test {
jacoco { /* specify the "exec" data file name (see the "Unit" in there) */
destinationFile = file("$buildDir/jacoco/jacocoTestUnit.exec")
classDumpDir = file("$buildDir/jacoco/classpathdumpsUnit")
}
useJUnitPlatform { /* I use the JUnit Jupiter #Tag Annotation to create my suites... you are free to do something else */
excludeTags 'IT'
}
description = "Run unit tests"
group = "verification"
}
task intTest(type: Test) {
jacoco {
destinationFile = file("$buildDir/jacoco/jacocoTestInt.exec")
classDumpDir = file("$buildDir/jacoco/classpathdumpsInt")
}
useJUnitPlatform {
includeTags 'IT'
}
description = "Run integration tests"
group = "verification"
}
jacocoTestReport {
/*
* find all test exec files and feed them to jacoco
*/
def list = []
def dir = new File("${buildDir}/jacoco/")
if(dir.exists()) {
dir.eachFileRecurse(FileType.FILES) { file ->
/* gather all the "exec" files available */
if (file.getName().startsWith("jacocoTest") && file.getName().endsWith(".exec")) {
list << file.getAbsolutePath()
}
}
/* provide all the "exec" files to jacoco */
executionData.from = files(list)
}
/*
* you must run all tests before running jacoco.
* We want the liberty to run partial tests instead of all,
* so this task doesn't depend on any test task.
*/
reports {
xml.enabled true
}
}
With this, you can have the the possibility to get the coverage from Unit tests with:
./gradlew clean test jacocoTestReport
Or you can have the coverage from Integration tests with:
./gradlew clean intTest jacocoTestReport
Or you can have the overall coverage of both unit and Integration tests with:
./gradlew clean test inTest jacocoTestReport
Disclaimer: I'm no Jacoco or Gradle expert... feel free to comment anything I may have forgotten. This worked beautifully so far for my needs.
In order to merge the reports here, I have a complete working solution.
Please note that in order to work properly the merge strategy, the phases should be executed sequentially (if the mvn test and mvn verify -DskipUnitTests will be executed in parallel there is possible to not work fine).
<!-- Jacoco is used to generate the reports for SonarQube -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
<configuration>
<skip>${skipTests}</skip>
</configuration>
<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>
<!-- Make sure that after the Unit Tests execution, the jacoco-ut.exec file is generated,
will be merged to the aggregation file -->
<execution>
<id>post-unit-merge</id>
<phase>test</phase>
<goals>
<goal>merge</goal>
</goals>
<configuration>
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<includes>
<include>**/coverage-reports/*.exec</include>
</includes>
</fileSet>
</fileSets>
<destFile>${project.build.directory}/coverage-reports/jacoco_aggregation.exec</destFile>
</configuration>
</execution>
<!-- Ensures that the code coverage report is created/updated 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_aggregation.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
</configuration>
</execution>
<!-- 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>
<!-- Make sure that after the Integration Test execution, the jacoco-it.exec file is generated,
will be merged to the aggregation file -->
<execution>
<id>post-integration-merge</id>
<phase>post-integration-test</phase>
<goals>
<goal>merge</goal>
</goals>
<configuration>
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<includes>
<include>**/coverage-reports/*.exec</include>
</includes>
</fileSet>
</fileSets>
<destFile>${project.build.directory}/coverage-reports/jacoco_aggregation.exec</destFile>
</configuration>
</execution>
<!-- Ensures that the code coverage report is created/updated 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_aggregation.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Sets the VM argument line used when unit tests are run. -->
<argLine>${surefireArgLine}</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<!-- Sets the VM argument line used when integration tests are run. -->
<argLine>${failsafeArgLine}</argLine>
</configuration>
</plugin>
Now, since the reports are generated, can be executed the sonar command in order to publis the report:
mvn sonar:sonar -Dsonar.coverage.jacoco.xmlReportPaths="target/site/jacoco/jacoco.xml"
This works out-of-the-box.
Explanations
The prepare-agent goal integrates by default with both SureFire and FailSafe plugins (to be exact the argLine parameter set by prepare-agent is consumed by both plugins). Additionally, prepare-agent by default configures Jacoco so that it appends coverage results if the file already exists, so in the end you get single target/jacoco.exec file which contains results from both unit test and integration tests, combined.
Just in case this is the relevant config, as you see nothing changed from default:) :
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<executions>
<execution>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.2</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.6</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
<goal>report</goal>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

How does Sonar Maven Plugin orchestrate tests?

Is it possible to configure how the surefire plugin is called when used with mvn sonar:sonar post compile.
In my maven project I have multiple test executions, for example
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.3</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<configuration>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
</excludes>
<parallel>methods</parallel>
<useUnlimitedThreads>true</useUnlimitedThreads>
<argLine>${jacoco.agent.argLine}</argLine>
</configuration>
</execution>
<execution>
<id>default-integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<includes>
<include>**/*IntegrationTest.java</include>
</includes>
<parallel>classes</parallel>
<argLine>${jacoco.agent.argLineIntegration}</argLine>
</configuration>
</execution>
</executions>
</plugin>
Note the integration tests in particular require some preprocessing ( aspectj compile for example ).
Is there any way to tell sonar to do this ? Or Indeed is it possible to generate the reports beforehand and just tell sonar to use them ?
You can have a look at the reuse report mode: http://docs.codehaus.org/display/SONAR/Code+Coverage+by+Unit+Tests+for+Java+Project

Resources