JaCoCo not generating jacoco.exec until after skipping JaCoCo execution - maven

I'm having trouble generating AHP reports via JaCoCo in one of my modules. When the build starts, I see JaCoCo correctly setting argLine with:
[INFO] jacoco.agent.argLine set to -javaagent:<...>/.m2/repository/org/jacoco/org.jacoco.agent/0.7.2.201409121644/org.jacoco.agent-0.7.2.201409121644-runtime.jar=destfile=<...>/target/jacoco.exec
However, the .exec hasn't been created yet by the time maven tries to run JaCoCo:
[INFO] Skipping JaCoCo execution due to missing execution data file:<...>/target/jacoco.exec
The jacoco.exec does eventually get created, after maven has skipped JaCoCo execution. Therefore, I can still generate AHP reports, if I re-run the build without cleaning.
I've seen in various other questions that I need to be careful using Maven Surefire with JaCoCo. However, I don't explicitly use argLine in my Surefire plugins, or in any plugin for that matter. I'm starting to wonder if one of the other plugins is hijacking the argLine parameter automatically like JaCoCo does.
Here is a list of all plugins used:
jacoco-maven-plugin
vertx-maven-plugin
maven-resources-plugin
maven-dependency-plugin
maven-surefire-plugin
maven-failsafe-plugin
maven-surefire-report-plugin
maven-assembly-plugin
I do see one suspicious message in the build output:
[INFO] --- maven-compiler-plugin:3.0:compile (default-compile) # <module> ---
[INFO] Changes detected - recompiling the module!
I'm not sure if that's relevant, but it appears twice before the Skipping message, and doesn't appear in a module where JaCoCo works properly.
Any ideas?
*edit - Here's the jacoco config
<plugins>
<...>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.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>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.jacoco</groupId>
<artifactId>
jacoco-maven-plugin
</artifactId>
<versionRange>
[0.7.2.201409121644,)
</versionRange>
<goals>
<goal>prepare-agent</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
I'm not sure exactly what that plugin management part is doing, but commenting it out doesn't fix anything. I've also tried putting the JaCoCo plugin config above the surefire/failsafe config in case order mattered for plugins sharing the same goals, but that didn't help either.
*edit 2 - Looks like the problem was surefire's includes. Commenting them out somehow fixes JaCoCo's .exec generation, and JaCoCo works properly.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.plugin.version}</version>
<configuration>
<!-- <includes>
<include>**/unit/**/*Test*.java</include>
</includes> -->
</configuration>
</plugin>
Anyone know why?

Just an addition to the answers already given.
It could happen that in your maven-surefire-plugin configuration you already use the argLine configuration to override something like the memory used. If you do so the argline set by jacoco-maven-plugin will not be used failing to generate the jacoco report.
In this case assign a property name to the jacoco-maven-plugin config and then reference it in your maven-surefire-plugin argLine parameter.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<executions>
<!-- prepare agent for measuring unit tests -->
<execution>
<id>prepare-unit-tests</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<append>true</append>
<destFile>${sonar.jacoco.reportPath}</destFile>
<!-- Sets the VM argument line used when unit tests are run. -->
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
</executions>
</plugin>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<printSummary>false</printSummary>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<forkCount>3</forkCount>
<reuseForks>true</reuseForks>
<argLine>${surefireArgLine} -Xmx1024m -noverify</argLine>
</configuration>
</plugin>

To solve this issue I would use the following three steps:
Determine which plugin execution is producing the jacoco.exec file. To do that, you could run Maven with debug logging enabled (mvn -X) and look for the jacoco.agent.argLine property name or its value in the output. You could also have a look at the effective POM (mvn help:effective-pom) in case the relevant configuration comes from the parent POM. Note that my guess is that it's an execution of the maven-failsafe-plugin.
Determine the phase that plugin is executed in. E.g. for maven-failsafe-plugin this would likely be integration-test.
Change the configuration of the JaCoCo plugin so that the report goal is executed later in the build lifecycle. E.g. if the jacoco.exec file is produced in the integration-test phase, you could execute the report goal in the post-integration-test phase.

In my case the solution was what #massimo mentioned, i was overriding memory values inside <surefireArgLine> tag, after i removed the tag it started generating the report and showed code coverage.

for me one of the reason for exec file not getting generated is when i placed the prepare-agent , prepare-package goals inside plugin section of pluginManagement
when i tried the same outside pluginManagement , i was sucessfully able to run the same and jacoco-exec file was generated using mvn clean install command
my pomfile is as below :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mmt</groupId>
<artifactId>jacoco</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jacoco</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<argLine>-Xms256m -Xmx1524m -XX:MaxPermSize=256m -Duser.language=en</argLine>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.7.201606060606</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>
</plugins>
</build>
</project>

I did not find any solution, but I did the following:
mvn clean jacoco:prepare-agent install
create file jacoco.exec, but execute mvn sonar:sonar not create File.
Solution:
Step 1:
mvn clean jacoco:prepare-agent install
Step 2:
copy file jacoco.exec from /src/main/resources
Step 3:
Add next plugin on pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>
${basedir}/target/</outputDirectory>
<resources>
<resource>
<directory>
${basedir}/src/main/resources/ </directory>
<includes>
<include>jacoco.exec</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
<configuration>
<encoding>cp1252</encoding>
</configuration>
</plugin>
Step 4:
mvn clean install
Step 5:
mvn sonar:sonar
READY
Add my section Plugins
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>cp1252</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>
${basedir}/target/</outputDirectory>
<resources>
<resource>
<directory>
${basedir}/src/main/resources/ </directory>
<includes>
<include>jacoco.exec</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-folder</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
<resources>
<resource>
<filtering>false</filtering>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
<configuration>
<encoding>cp1252</encoding>
</configuration>
</plugin>
<!-- Plugin Sonar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.1</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.6.201602180812</version>
<configuration>
<destFile>${project.build.directory}/jacoco.exec</destFile>
</configuration>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${basedir}/target/jacoco.exec</destFile>
<dataFile>${basedir}/target/jacoco.exec</dataFile>
</configuration>
</execution>
<execution>
<id>jacoco-site</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>

I also faced the same problem where jacoco plugin was added to parent pom, and jacoco.exec file was generating for one of the sub modules. I had to remove the argLine arguments of maven surefire plugin, then it got generated.

Related

Jacoco Report Aggregate Coverage Report issue on Sonar

I have a multi-module maven project. I am facing issues while generating the sonar report for the jacoco report-aggregate coverage.
I have 2 modules (A and B) for which I want to generate the report.
I have created another module (jacoco-report-aggr) under the parent module for generating the report-aggregate of jacoco.
When I run "mvn clean install", the jacoco index.html fille generated in the jacoco-report-aggr module shows the coverage for both modules A and modules B. But when I run "mvn sonar:sonar" the sonar report generated shows
the coverage for only module B but not module A.
Attaching the corresponding parts of the xml files.
I have the parent pom.xml as below.
<sonar.java.coveragePlugin>jacoco-maven-plugin</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.language>java</sonar.language>
<jacoco.version>0.8.5</jacoco.version>
<surefire.plugin.version>2.19.1</surefire.plugin.version>
<aggregate.report.dir>jacoco-report-aggr/target/site/jacoco-aggregate/jacoco.xml</aggregate.report.dir>
<sonar.coverage.jacoco.xmlReportPaths>/jacoco-report-aggr/target/site/jacoco/jacoco.xml,/jacoco-report-aggr/target/site/jacoco-aggregate/jacoco.xml,
${basedir}/../${aggregate.report.dir},
${basedir}/../../${aggregate.report.dir},
${basedir}/../../${aggregate.report.dir}</sonar.coverage.jacoco.xmlReportPaths>
<!--Jacoco Code Coverage Plugin. Only start the agent-->
<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>
<goal>report</goal>
</goals>
<configuration>
<propertyName>jacoco.agent.argLine</propertyName>
<destFile>target/jacoco.exec</destFile>
</configuration>
</execution>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<!--Maven Surefire Plugin-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.plugin.version}</version>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.7.0.1746</version>
</plugin>
The child modules pom looks like this.
<properties>
<sonar.coverage.jacoco.xmlReportPaths>${basedir}/../${aggregate.report.dir}</sonar.coverage.jacoco.xmlReportPaths>
</properties>
The pom.xml file of the jacoco-report-aggr module looked like this
<dependencies>
<dependency>"Module A"</dependency>
<dependency>"Module B"</dependency>
</dependencies>
<properties>
<sonar.coverage.jacoco.xmlReportPaths>${basedir}/../${aggregate.report.dir}
</sonar.coverage.jacoco.xmlReportPaths>
</properties>
<build>
<plugins>
<!--Maven Surefire Plugin-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.plugin.version}</version>
</plugin>
<!--Jacoco Aggregate Report plugin over dependencies-->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Ensure Maven build fails when tests fail to run

I've noticed that sometimes when running maven builds on Jenkins the number of Jbehave tests that are run vary from one run to another. When analyzing the logs I see the following snippet:
Failed to run story stories/cancel.story
java.lang.InterruptedException: stories/cancel.story
at org.jbehave.core.embedder.StoryRunner$RunContext.interruptIfCancelled(StoryRunner.java:616)
at org.jbehave.core.embedder.StoryRunner.runStepsWhileKeepingState(StoryRunner.java:514)
at org.jbehave.core.embedder.StoryRunner.runScenarioSteps(StoryRunner.java:479)
at org.jbehave.core.embedder.StoryRunner.runStepsWithLifecycle(StoryRunner.java:445)
at org.jbehave.core.embedder.StoryRunner.runCancellable(StoryRunner.java:305)
at org.jbehave.core.embedder.StoryRunner.run(StoryRunner.java:220)
at org.jbehave.core.embedder.StoryRunner.run(StoryRunner.java:181)
at org.jbehave.core.embedder.StoryManager$EnqueuedStory.call(StoryManager.java:235)
at org.jbehave.core.embedder.StoryManager$EnqueuedStory.call(StoryManager.java:207)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
The problem is that when tests are skipped or fail to run in this way the build is still considered a success.
Is there a maven surefire plugin configuration that will ensure that whenever tests fail to run the build results in a failure? Here are the maven surefire build configurations
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.11</version>
<configuration>
<includes>
<include>**/*TestSuite.java</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
</plugin>
<plugin>
<groupId>net.thucydides.maven.plugins</groupId>
<artifactId>maven-thucydides-plugin</artifactId>
<version>${thucydides.version}</version>
<executions>
<execution>
<id>thucydides-reports</id>
<phase>post-integration-test</phase>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.2</version>
<configuration>
<reportPlugins>
<plugin>
<groupId>net.thucydides.maven.plugins</groupId>
<artifactId>maven-thucydides-plugin</artifactId>
<version>${thucydides.version}</version>
</plugin>
</reportPlugins>
</configuration>
</plugin>
</plugins>
</build>
Your maven-surefire-plugin is set to skip tests completely (with <skip>true</skip>), so tests are running with maven-failsafe-plugin. That plug-in is supposed to not stop on failure during integration-test, and then only fail on verify phase.
So if you really want this question answered:
Is there a maven surefire plugin configuration that will ensure that whenever tests fail to run the build results in a failure?
That is: you want maven-surefire-plugin to run the tests, and not the maven-failsafe-plugin, then the answer is: remove
<configuration>
<skip>true</skip>
</configuration>
from your POM. In this case you also don't need maven-failsafe-plugin configuration, because it would just make your tests run twice.
But if your goal is to get maven-failsafe-plugin to work, then I think you may have one of the following issues:
Not running the right goal. As plug-in help states, you should invoke it as
mvn verify
An old plug-in, which is not compatible with test framework you are using (current version is 2.19.1)
Or this help recommendation:
For very complex builds, it may be better to separate the executions for the integration-test and verify goals:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<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>

Generated sources being compiled twice

Using Eclipse Luna with m2eclipse, I have a parent Maven project (facturas_root) and two Maven modules inheriting from it (sharepoint_ws and api_sharepoint).
sharepoint_ws was to be used only to generate JAXWS classes to connect to the Sharepoint WebServices, so I downloaded the related WSDL and included those as resources of the project. At generate-sources phase, it works correctly and generates the sources in target\generated-sources\ws-consume\mypackage\.
Now, the issue is that I made api_sharepoint import the sharepoint_ws dependency, but it does not detect any class. I assumed that it was because the generated classes were not at src/main/java, so I added a plugin to copy them there. Now, the problem is that at the compile phase of sharepoint_ws, it finds twice the source file of each class and throws an error.
My pom.xml -> build
<plugins>
<!-- clean /src/main/java and /target/generated-sources -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.6.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<filesets>
<fileset>
<directory>${basedir}/src/main/java/es</directory>
</fileset>
<fileset>
<directory>${basedir}/target/generated-sources</directory>
</fileset>
</configuration>
</execution>
</executions>
</plugin>
<!-- generate jaxws -->
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>maven-jaxws-tools-plugin</artifactId>
<version>1.1.2.Final</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>wsconsume</goal>
</goals>
<configuration>
<wsdls>
<wsdl>${basedir}/resources/lists.wsdl</wsdl>
</wsdls>
<targetPackage>es.ssib.otic.facturas.sharepoint_ws</targetPackage>
<outputDirectory>${basedir}/target/generated-sources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- copy sources -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-filtering</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<resources>
<resource>
<directory>${basedir}/target/generated-sources/wsconsume</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
In order to try to exclude target/generated-sources I have addded this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<configuration>
<excludes>
<exclude>**/target/generated-sources/*.java</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
As stated above, I do comment the "copy" plugin, the module depending on sharepoint_ws does not have any ot its classes available; I do use it I get errors in the tune of
[ERROR] /C:/Users/s004256/workspace/facturas_root/sharepoint_ws/src/main/java/es/ssib/otic/facturas/sharepoint_ws/DeleteList.java:[34,8] duplicate class: es.ssib.otic.facturas.sharepoint_ws.DeleteList
for each generated list.
In the first place, I recommend you'd better declare target/generated-sources as a source folder, instead of copying files here and there:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>initialize</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
This should be enough to make Maven compile the target/generated-sources/*.java and package them all in the library, and also for Eclipse to recognize target/generated-sources as a source directory (after you execute Maven/Update Project).
By the way: You should take care of binding the plugins to a phase in the correct order: If you bound all tasks to "generate-sources", you have no gurantee about in which order will they be executed. And the same goes for the "compile" phase: You have to set properly the source folders, with its inclusions and exclusions, before the compile phase.
Take a look a the Default Maven Lifecycle and try to chose different, sequential phases for your tasks.

Ignore maven plugin during a build

How can I ignore my plugin (maven-antrun-plugin) during a build or deploy?
I am generating source files from a IDL tool (written in C). I used the maven-antrun-plugin to do the source generation and applied it to the generate-sources phase. Along with the build-helper-maven-plugin, the java source generated by the IDL tool is deposited in a generated sources folder and, ultimately, included in the jar packaging as source. Perfect!
Here's what I use in my maven build:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<mkdir dir="target/generated-sources/" />
<!-- other task stuff here -->
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>target/generated-sources/gen-java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
However, now the problem is that our team is directed to not use the IDL tool in our Continuous Integration (CI) environment; the plugin will fail in CI because the IDL tool is not installed. As a result, I must check in the generated source (with the other code under src/main/java) to our GIT repo.
I would like to be able to still run the maven-antrun-plugin, but, decouple it from the generated-sources phase or any lifecycle so that the CI environment can run my build. I will run the plugin manually/locally when I make a change so that the source will be generated and then checked in to the GIT repo.
Is this even possible? How can I ignore maven-antrun-plugin during an build or deploy?
As suggested by a commenter (Jarrod Roberson), maven profiles can be used to ignore the generation of sources in the maven-antrun-plugin plugin.
Specifically, adding the profiles block shown below addresses the issue. The default-profile profile is activated by default; it does not contain the maven-antrun-plugin block.
However, the generate-source-profile does contain the maven-antrun-plugin that will initiate the sources generation.
<profiles>
<profile>
<id>default-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>generate-sources-profile</id>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<mkdir dir="target/generated-sources/" />
<!-- other task stuff here -->
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Thus, the Continuous Integration (CI) tool will do a normal build and deploy (mvn deploy). When I want to generate sources then I will run the generate sources profile by doing, for example, mvn clean install -P generate-sources-profile.
You can use profiles or simply skip maven-antrun-plugin execution
skip - Specifies whether the Antrun execution should be skipped.
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<skip>${skipAntRunForMe}</skip>
<tasks>
<mkdir dir="target/generated-sources/"/>
<!-- other task stuff here -->
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
And inovke goal with param -DskipAntRunForMe

How to configure multi-module Maven + Sonar + JaCoCo to give merged coverage report?

I've searched up and down the internet for this one. There's lots of half-answers out there, to do with Maven properties such as ${sonar.jacoco.reportPath}, or org.jacoco:jacoco-maven-plugin:prepare-agent or setting maven-surefire-plugin argLine with -javaagent.
Some how, none of these answers, either on their own, or in combination, are producing what I'm after:
A coverage report which shows a class as covered if it is used in tests higher up the stack, such as entities being used by DAOs, even though it was not fully covered by tests in its own module.
Is there a definitive config somewhere, to achieve this, please?
I was in the same situation as you, the half answers scattered throughout the Internet were quite annoying, since it seemed that many people had the same issue, but no one could be bothered to fully explain how they solved it.
The Sonar docs refer to a GitHub project with examples that are helpful. What I did to solve this was to apply the integration tests logic to regular unit tests (although proper unit tests should be submodule specific, this isn't always the case).
In the parent pom.xml, add these properties:
<properties>
<!-- Sonar -->
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
<sonar.language>java</sonar.language>
</properties>
This will make Sonar pick up unit testing reports for all submodules in the same place (a target folder in the parent project). It also tells Sonar to reuse reports ran manually instead of rolling its own. We just need to make jacoco-maven-plugin run for all submodules by placing this in the parent pom, inside build/plugins:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.6.0.201210061924</version>
<configuration>
<destFile>${sonar.jacoco.reportPath}</destFile>
<append>true</append>
</configuration>
<executions>
<execution>
<id>agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
destFile places the report file in the place where Sonar will look for it and append makes it append to the file rather than overwriting it. This will combine all JaCoCo reports for all submodules in the same file.
Sonar will look at that file for each submodule, since that's what we pointed him at above, giving us combined unit testing results for multi module files in Sonar.
NEW WAY SINCE VERSION 0.7.7
Since Version 0.7.7 there is a new way to create an aggregated report:
You create a separate 'report' project which collects all the necessary reports (Any goal in the aggregator project is executed before its modules therefore it can't be used).
aggregator pom
|- parent pom
|- module a
|- module b
|- report module
The root pom looks like this (don't forget to add the new report module under modules):
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.8</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
The poms from each sub module doesn't need to be changed at all. The pom from the report module looks like this:
<!-- Add all sub modules as dependencies here -->
<dependencies>
<dependency>
<module a>
</dependency>
<dependency>
<module b>
</dependency>
...
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.8</version>
<executions>
<execution>
<id>report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
A full exmple can be found here.
FAQ
Questions from the top of my head since that time I gone crazy with jacoco.
My application server (jBoss, Glassfish..) located in Iraq, Syria, whatever.. Is it possible to get multi-module coverage when running integration tests on it? Jenkins and Sonar are also on different servers.
Yes. You have to use jacoco agent that runs in mode output=tcpserver, jacoco ant lib. Basically two jars. This will give you 99% success.
How does jacoco agent works?
You append a string
-javaagent:[your_path]/jacocoagent.jar=destfile=/jacoco.exec,output=tcpserver,address=*
to your application server JAVA_OPTS and restart it. In this string only [your_path] have to be replaced with the path to jacocoagent.jar, stored(store it!) on your VM where app server runs. Since that time you start app server, all applications that are deployed will be dynamically monitored and their activity (meaning code usage) will be ready for you to get in jacocos .exec format by tcl request.
Could I reset jacoco agent to start collecting execution data only since the time my test start?
Yes, for that purpose you need jacocoant.jar and ant build script located in your jenkins workspace.
So basically what I need from http://www.eclemma.org/jacoco/ is jacocoant.jar located in my jenkins workspace, and jacocoagent.jar located on my app server VM?
That's right.
I don't want to use ant, I've heard that jacoco maven plugin can do all the things too.
That's not right, jacoco maven plugin can collect unit test data and some integration tests data(see Arquillian Jacoco), but if you have for example rest assured tests as a separated build in jenkins, and want to show multi-module coverage, I can't see how maven plugin can help you.
What exactly does jacoco agent produce?
Only coverage data in .exec format. Sonar then can read it.
Does jacoco need to know where my java classes located are?
No, sonar does, but not jacoco. When you do mvn sonar:sonar path to classes comes into play.
So what about the ant script?
It has to be presented in your jenkins workspace. Mine ant script, I called it jacoco.xml looks like that:
<project name="Jacoco library to collect code coverage remotely" xmlns:jacoco="antlib:org.jacoco.ant">
<property name="jacoco.port" value="6300"/>
<property name="jacocoReportFile" location="${workspace}/it-jacoco.exec"/>
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath path="${workspace}/tools/jacoco/jacocoant.jar"/>
</taskdef>
<target name="jacocoReport">
<jacoco:dump address="${jacoco.host}" port="${jacoco.port}" dump="true" reset="true" destfile="${jacocoReportFile}" append="false"/>
</target>
<target name="jacocoReset">
<jacoco:dump address="${jacoco.host}" port="${jacoco.port}" reset="true" destfile="${jacocoReportFile}" append="false"/>
<delete file="${jacocoReportFile}"/>
</target>
</project>
Two mandatory params you should pass when invoking this script
-Dworkspace=$WORKSPACE
use it to point to your jenkins workspace and -Djacoco.host=yourappserver.com host without http://
Also notice that I put my jacocoant.jar to ${workspace}/tools/jacoco/jacocoant.jar
What should I do next?
Did you start your app server with jacocoagent.jar?
Did you put ant script and jacocoant.jar in your jenkins workspace?
If yes the last step is to configure a jenkins build. Here is the strategy:
Invoke ant target jacocoReset to reset all previously collected data.
Run your tests
Invoke ant target jacocoReport to get report
If everything is right, you will see it-jacoco.exec in your build workspace.
Look at the screenshot, I also have ant installed in my workspace in $WORKSPACE/tools/ant dir, but you can use one that is installed in your jenkins.
How to push this report in sonar?
Maven sonar:sonar will do the job (don't forget to configure it), point it to main pom.xml so it will run through all modules. Use sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.exec parameter to tell sonar where your integration test report is located. Every time it will analyse new module classes, it will look for information about coverage in it-jacoco.exec.
I already have jacoco.exec in my `target` dir, `mvn sonar:sonar` ignores/removes it
By default mvn sonar:sonar does clean and deletes your target dir, use sonar.dynamicAnalysis=reuseReports to avoid it.
I found another solution for new Sonar versions where JaCoCo's binary report format (*.exec) was deprecated and the preferred format is XML (SonarJava 5.12 and higher).
The solution is very simple and similar to the previous solution with *.exec reports in parent directory from this topic: https://stackoverflow.com/a/15535970/4448263.
Assuming that our project structure is:
moduleC - aggregate project's pom
|- moduleA - some classes without tests
|- moduleB - some classes depending from moduleA and tests for classes in both modules: moduleA and moduleB
You need following maven build plugin configuration in aggregate project's pom:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<executions>
<execution>
<id>prepare-and-report</id>
<goals>
<goal>prepare-agent</goal>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/../target/site/jacoco-aggregate</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Then build project with maven:
mvn clean verify
And for Sonar you should set property in administration GUI:
sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml,../target/site/jacoco-aggregate/jacoco.xml
or using command line:
mvn sonar:sonar -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml,../target/site/jacoco-aggregate/jacoco.xml
Description
This creates binary reports for each module in default directories: target/jacoco.exec. Then creates XML reports for each module in default directories: target/site/jacoco/jacoco.xml. Then creates an aggregate report for each module in custom directory ${project.basedir}/../target/site/jacoco-aggregate/ that is relative to parent directory for each module. For moduleA and moduleB this will be common path moduleC/target/site/jacoco-aggregate/.
As moduleB depends on moduleA, moduleB will be built last and its report will be used as an aggregate coverage report in Sonar for both modules A and B.
In addition to the aggregate report, we need a normal module report as JaCoCo aggregate reports contain coverage data only for dependencies.
Together, these two types of reports providing full coverage data for Sonar.
There is one little restriction: you should be able to write a report in the project's parent directory (should have permission). Or you can set property jacoco.skip=true in root project's pom.xml (moduleC) and jacoco.skip=false in modules with classes and tests (moduleA and moduleB).
I'll post my solution as it it subtly different from others and also took me a solid day to get right, with the assistance of the existing answers.
For a multi-module Maven project:
ROOT
|--WAR
|--LIB-1
|--LIB-2
|--TEST
Where the WAR project is the main web app, LIB 1 and 2 are additional modules the WAR depends on and TEST is where the integration tests live.
TEST spins up an embedded Tomcat instance (not via Tomcat plugin) and runs WAR project and tests them via a set of JUnit tests.
The WAR and LIB projects both have their own unit tests.
The result of all this is the integration and unit test coverage being separated and able to be distinguished in SonarQube.
ROOT pom.xml
<!-- Sonar properties-->
<sonar.jacoco.itReportPath>${project.basedir}/../target/jacoco-it.exec</sonar.jacoco.itReportPath>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
<sonar.language>java</sonar.language>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<!-- build/plugins (not build/pluginManagement/plugins!) -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.6.201602180812</version>
<executions>
<execution>
<id>agent-for-ut</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<append>true</append>
<destFile>${sonar.jacoco.reportPath}</destFile>
</configuration>
</execution>
<execution>
<id>agent-for-it</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<append>true</append>
<destFile>${sonar.jacoco.itReportPath}</destFile>
</configuration>
</execution>
</executions>
</plugin>
WAR, LIB and TEST pom.xml will inherit the the JaCoCo plugins execution.
TEST pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<skipTests>${skip.tests}</skipTests>
<argLine>${argLine} -Duser.timezone=UTC -Xms256m -Xmx256m</argLine>
<includes>
<includes>**/*Test*</includes>
</includes>
</configuration>
</execution>
</executions>
</plugin>
I also found Petri Kainulainens blog post 'Creating Code Coverage Reports for Unit and Integration Tests With the JaCoCo Maven Plugin' to be valuable for the JaCoCo setup side of things.
There is a way to accomplish this. The magic is to create a combined jacoco.exec file. And with maven 3.3.1 there is an easy way to get this. Here my profile:
<profile>
<id>runSonar</id>
<activation>
<property>
<name>runSonar</name>
<value>true</value>
</property>
</activation>
<properties>
<sonar.language>java</sonar.language>
<sonar.host.url>http://sonar.url</sonar.host.url>
<sonar.login>tokenX</sonar.login>
<sonar.jacoco.reportMissing.force.zero>true</sonar.jacoco.reportMissing.force.zero>
<sonar.jacoco.reportPath>${jacoco.destFile}</sonar.jacoco.reportPath>
<jacoco.destFile>${maven.multiModuleProjectDirectory}/target/jacoco_analysis/jacoco.exec</jacoco.destFile>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<append>true</append>
<destFile>${jacoco.destFile}</destFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.2</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.8</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
If you add this profile to your parent pom and call mvn clean install sonar:sonar -DrunSonar you get the complete coverage.
The magic here is maven.multiModuleProjectDirectory. This folder is always the folder where you started your maven build.
The configuration I use in my parent level pom where I have separate unit and integration test phases.
I configure the following properties in the parent POM
Properties
<maven.surefire.report.plugin>2.19.1</maven.surefire.report.plugin>
<jacoco.plugin.version>0.7.6.201602180812</jacoco.plugin.version>
<jacoco.check.lineRatio>0.52</jacoco.check.lineRatio>
<jacoco.check.branchRatio>0.40</jacoco.check.branchRatio>
<jacoco.check.complexityMax>15</jacoco.check.complexityMax>
<jacoco.skip>false</jacoco.skip>
<jacoco.excludePattern/>
<jacoco.destfile>${project.basedir}/../target/coverage-reports/jacoco.exec</jacoco.destfile>
<sonar.language>java</sonar.language>
<sonar.exclusions>**/generated-sources/**/*</sonar.exclusions>
<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
<sonar.coverage.exclusions>${jacoco.excludePattern}</sonar.coverage.exclusions>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.jacoco.reportPath>${project.basedir}/../target/coverage-reports</sonar.jacoco.reportPath>
<skip.surefire.tests>${skipTests}</skip.surefire.tests>
<skip.failsafe.tests>${skipTests}</skip.failsafe.tests>
I place the plugin definitions under plugin management.
Note that I define a property for surefire (surefireArgLine) and failsafe (failsafeArgLine) arguments to allow jacoco to configure the javaagent to run with each test.
Under pluginManagement
<build>
<pluginManagment>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<fork>true</fork>
<meminitial>1024m</meminitial>
<maxmem>1024m</maxmem>
<compilerArgument>-g</compilerArgument>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<forkCount>4</forkCount>
<reuseForks>false</reuseForks>
<argLine>-Xmx2048m ${surefireArgLine}</argLine>
<includes>
<include>**/*Test.java</include>
</includes>
<excludes>
<exclude>**/*IT.java</exclude>
</excludes>
<skip>${skip.surefire.tests}</skip>
</configuration>
</plugin>
<plugin>
<!-- For integration test separation -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.19.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.19.1</version>
</dependency>
</dependencies>
<configuration>
<forkCount>4</forkCount>
<reuseForks>false</reuseForks>
<argLine>${failsafeArgLine}</argLine>
<includes>
<include>**/*IT.java</include>
</includes>
<skip>${skip.failsafe.tests}</skip>
</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>
<plugin>
<!-- Code Coverage -->
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.plugin.version}</version>
<configuration>
<haltOnFailure>true</haltOnFailure>
<excludes>
<exclude>**/*.mar</exclude>
<exclude>${jacoco.excludePattern}</exclude>
</excludes>
<rules>
<rule>
<element>BUNDLE</element>
<limits>
<limit>
<counter>LINE</counter>
<value>COVEREDRATIO</value>
<minimum>${jacoco.check.lineRatio}</minimum>
</limit>
<limit>
<counter>BRANCH</counter>
<value>COVEREDRATIO</value>
<minimum>${jacoco.check.branchRatio}</minimum>
</limit>
</limits>
</rule>
<rule>
<element>METHOD</element>
<limits>
<limit>
<counter>COMPLEXITY</counter>
<value>TOTALCOUNT</value>
<maximum>${jacoco.check.complexityMax}</maximum>
</limit>
</limits>
</rule>
</rules>
</configuration>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${jacoco.destfile}</destFile>
<append>true</append>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${jacoco.destfile}</dataFile>
<outputDirectory>${sonar.jacoco.reportPath}</outputDirectory>
<skip>${skip.surefire.tests}</skip>
</configuration>
</execution>
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<destFile>${jacoco.destfile}</destFile>
<append>true</append>
<propertyName>failsafeArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>report-integration</goal>
</goals>
<configuration>
<dataFile>${jacoco.destfile}</dataFile>
<outputDirectory>${sonar.jacoco.reportPath}</outputDirectory>
<skip>${skip.failsafe.tests}</skip>
</configuration>
</execution>
<!-- Disabled until such time as code quality stops this tripping
<execution>
<id>default-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<dataFile>${jacoco.destfile}</dataFile>
</configuration>
</execution>
-->
</executions>
</plugin>
...
And in the build section
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<!-- for unit test execution -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<!-- For integration test separation -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
<plugin>
<!-- For code coverage -->
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
</plugin>
....
And in the reporting section
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>${maven.surefire.report.plugin}</version>
<configuration>
<showSuccess>false</showSuccess>
<alwaysGenerateFailsafeReport>true</alwaysGenerateFailsafeReport>
<alwaysGenerateSurefireReport>true</alwaysGenerateSurefireReport>
<aggregate>true</aggregate>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.plugin.version}</version>
<configuration>
<excludes>
<exclude>**/*.mar</exclude>
<exclude>${jacoco.excludePattern}</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</reporting>
As Sonars sonar.jacoco.reportPath, sonar.jacoco.itReportPath and sonar.jacoco.reportPaths have all been deprecated, you should use sonar.coverage.jacoco.xmlReportPaths now. This also has some impact if you want to configure a multi module maven project with Sonar and Jacoco.
As #Lonzak pointed out, since Sonar 0.7.7, you can use Sonars report aggragation goal. Just put in you parent pom the following dependency:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<executions>
<execution>
<id>report</id>
<goals>
<goal>report-aggregate</goal>
</goals>
<phase>verify</phase>
</execution>
</executions>
</plugin>
As current versions of the jacoco-maven-plugin are compatible with the xml-reports, this will create for every module in it's own target folder a site/jacoco-aggregate folder containing a jacoco.xml file.
To let Sonar combine all the modules, use following command:
mvn -Dsonar.coverage.jacoco.xmlReportPaths=full-path-to-module1/target/site/jacoco-aggregate/jacoco.xml,module2...,module3... clean verify sonar:sonar
To keep my answer short and precise, I did not mention the maven-surefire-plugin and
maven-failsafe-plugin dependencies. You can just add them without any other configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.22.2</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
<sonar.language>java</sonar.language>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.jacoco.reportPath>${user.dir}/target/jacoco.exec</sonar.jacoco.reportPath>
<sonar.jacoco.itReportPath>${user.dir}/target/jacoco-it.exec</sonar.jacoco.itReportPath>
<sonar.exclusions>
file:**/target/generated-sources/**,
file:**/target/generated-test-sources/**,
file:**/target/test-classes/**,
file:**/model/*.java,
file:**/*Config.java,
file:**/*App.java
</sonar.exclusions>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${sonar.jacoco.reportPath}</destFile>
<append>true</append>
<propertyName>surefire.argLine</propertyName>
</configuration>
</execution>
<execution>
<id>default-prepare-agent-integration</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<destFile>${sonar.jacoco.itReportPath}</destFile>
<append>true</append>
<propertyName>failsafe.argLine</propertyName>
</configuration>
</execution>
<execution>
<id>default-report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>default-report-integration</id>
<goals>
<goal>report-integration</goal>
</goals>
</execution>
</executions>
</plugin>
This sample works very well for me :
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2</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>
<!--<excludes>
<exclude>com.asimio.demo.rest</exclude>
<exclude>com.asimio.demo.service</exclude>
</excludes>-->
<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>**/*Test.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>
<includes>
<include>**/*IT.java</include>
</includes>
<!--<excludes>
<exclude>**/*UT*.java</exclude>
</excludes>-->
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
You can call a ant task called merge on maven, to put all coverage files (*.exec) together in the same file.
If you are run unit tests use the phase prepare-package, if you run integration test so use post-integration-test.
This site has an example to how call jacoco ant task in maven project
You can use this merged file on sonar.
to have unit-testing AND integration-testing you can use maven-surefire-plugin and maven-failsafe-plugin with restricted includes/excludes. I was playing with CDI while getting in touch with sonar/jacoco, so i ended up in this project:
https://github.com/FibreFoX/cdi-sessionscoped-login/
Maybe it helps you a little bit. in my pom.xml i use "-javaagent" implicit by setting the argLine-option in the configuration-section of the specified testing-plugins.
Explicit using ANT in MAVEN projects is something i would not give a try, for me its to much mixing two worlds.
I only have a single-module maven project, but maybe it helps you to adjust yours to work.
note: maybe not all maven-plugins are up2date, maybe some issues are fixed in later versions
As stated in the Jacoco Wiki, you could also generate a new reporting-module:
Strategy: Module with Dependencies: The problems with aggregator
projects can be solved with an extra "reporting" module. In a
multi-module Maven project a separate module is defined that does not
contribute actual content but creates a combined coverage report. It
defines a dependency to all the modules that should be included in the
combined report. The "reporting" module would be built after its
dependencies and have access to the exec files as well as class and
source files from projects it depends on. This strategy seems to work
best with the current Maven architecture. From a user's perspective
one could argue that such a separate module would bloat the build
definition. Or, that the separate module cannot have any submodules
from which it could consume exec or class files. However, compared to
the other strategies these drawbacks seem rather minor and can be
handled in a consistent manner.
This is especially helpful if your modularisation is more complex than one parent with some child modules.
Your reporting pom could look something like:
<dependencies>
<dependency>
<groupId>org.sonarqube</groupId>
<artifactId>module1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.sonarqube</groupId>
<artifactId>module2</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>report</id>
<goals>
<goal>report-aggregate</goal>
</goals>
<phase>verify</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>

Resources