I have a maven project and I want to use jacoco
for code coverage. Here is the relevant section of my pom
I solved the duplication issue by adding <phase>prepare-package</phase>
to the report execution task:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
** is for traversing into underlying directories and different than * which is a character wild card for names. Avoiding ** can result into undesirable effect.
Property excludes
of report
goal specifies which files should be excluded from analysis during generation of report. In case of /path/tp/my/project/target/classes/META-INF/bundled-dependencies/some-third-party-1-jar-with-dependencies.jar@org/slf4j/event/EventConstants.class
file is /path/tp/my/project/target/classes/META-INF/bundled-dependencies/some-third-party-1-jar-with-dependencies.jar
, and the rest is about class in JAR file.
Therefore as one of examples of correct configuration:
<configuration>
<excludes>
<exclude>META-INF/**</exclude>
</excludes>
</configuration>
As a proof having pom.xml
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>example</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.1</version>
</plugin>
</plugins>
</build>
</project>
src/main/java/Example.java
public class Example {
}
and src/test/java/ExampleTest.java
public class ExampleTest {
@org.junit.Test
public void test() {
}
}
Execution of
mvn clean jacoco:prepare-agent package
mkdir target/classes/META-INF/
cp ~/.m2/repository/org/slf4j/slf4j-api/1.4.2/slf4j-api-1.4.2.jar target/classes
cp ~/.m2/repository/org/slf4j/slf4j-api/1.7.7/slf4j-api-1.7.7.jar target/classes/META-INF
mvn jacoco:report
will fail with message
Error while analyzing /private/tmp/j/target/classes/slf4j-api-1.4.2.jar@org/slf4j/helpers/BasicMarker.class. Can't add different class with same name: org/slf4j/helpers/BasicMarker
while same execution with pom.xml
containing exclusion of META-INF/**
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>example</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.1</version>
<configuration>
<excludes>
<exclude>META-INF/**</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
will succeed.
As a side note: semantic of property excludes of prepare-agent goal is different - it specifies class names (regardless of their on-disk location) that should be excluded from instrumentation during execution of tests.