jacoco: нельзя исключить классы

У меня есть проект maven, и я хочу использовать jacoco для покрытия кода. Вот соответствующий раздел моей помпы

          <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.7.5.201505241946</version>
                <executions>
                    <execution>
                        <id>pre-my-test</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <append>true</append>
                            <destFile>${project.build.directory}/jacoco-it.exec</destFile>
                            <propertyName>failsafeArgLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>post-my-test</id>
                        <phase>post-my-test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                        <configuration>
                            <dataFile>${project.build.directory}/jacoco-it.exec</dataFile>
                            <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Так что я могу нормально запускать свои тесты, а также отлично строить проект. Тогда я бегу

mvn clean verify org.jacoco:jacoco-maven-plugin:prepare-agent

Я продолжаю получать такие ошибки, как

ERROR] Failed to execute goal org.jacoco:jacoco-maven-plugin:0.7.5.201505241946:
report (post-my-test) on project my-project: 
An error has occurred in JaCoCo Test report generation. 
Error while creating report: 
Error while analyzing class /path/tp/my/project/target/classes/META-INF/
bundled-dependencies/some-third-party-1-jar-with-dependencies.jar@org/slf4j/event/
EventConstants.class. Can't add different class with same name: 
org/slf4j/event/EventConstants -> [Help 1]

some-third-party-1-jar-with-dependencies.jar - это внешняя зависимость, которая у меня есть. Это банка uber / затемненная. Так что я подумал, что some-third-party-1-jar-with-dependencies.jar также должен иметь org.slf4j, отсюда и конфликт. Поэтому я внес изменения в пом как

            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.7.5.201505241946</version>
                <configuration>
                    <excludes>
                        <exclude>**/org/slf4j/event/EventConstants.*</exclude>
                    </excludes>
                </configuration>
                <executions>
                    <execution>
                        <id>pre-integration-test</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <append>true</append>
                            <destFile>${project.build.directory}/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}/jacoco-it.exec</dataFile>
                            <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

но я все равно получаю ту же ошибку. Как я могу убедиться, что jacoco игнорирует все повторяющиеся зависимости? Я тоже пробовал

<dependency>
            <groupId>some.third.party</groupId>
            <artifactId>some-third-party</artifactId>
            <version>1</version>
            <classifier>jar-with-dependencies</classifier>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-simple</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

но это не сработало. Возможны ли исключения из затененных / убер-банок?

Кроме того, почему жакоко заботится? Есть ли способ исправить или игнорировать эти ошибки? Как я могу решить эту проблему?


person AbtPst    schedule 03.05.2018    source источник
comment
Исключение зависимости не сработает, если она находится в реальном Uber JAR. Вы пробовали решение, описанное здесь: stackoverflow.com/questions/9133116/?   -  person Dennis Hunziker    schedule 03.05.2018
comment
спасибо, я не смотрел этот пост. но где мне положить <sourcefiles> <zipfileset> <fileset dir="foo.jar"> <exclude name="org/jboss/osgi/framework/main/**/AbstractPackageAttribute*.*"/> </fileset> </zipfileset> </sourcefiles>?   -  person AbtPst    schedule 04.05.2018
comment
я имею в виду под каким тегом?   -  person AbtPst    schedule 04.05.2018
comment
Неважно, это существует только в версии ant, и вы используете фактический плагин Maven. Глядя на сообщения об ошибках, я не совсем уверен, как он будет относиться к вашему пути, поскольку он содержит @ и путь в JAR. Я бы попробовал более общее исключение, например **/event/EventConstants* или аналогичный вариант.   -  person Dennis Hunziker    schedule 04.05.2018
comment
спасибо, я попробовал **/event/EventConstants*, но это не сработало   -  person AbtPst    schedule 04.05.2018
comment
Посмотрите, найдете ли вы здесь подсказку: stackoverflow.com/questions/11673356/   -  person AKS    schedule 07.05.2018


Ответы (3)


Свойство excludes цели report указывает, какие файлы следует исключить из анализа при формировании отчета. В случае /path/tp/my/project/target/classes/META-INF/bundled-dependencies/some-third-party-1-jar-with-dependencies.jar@org/slf4j/event/EventConstants.class файл - это /path/tp/my/project/target/classes/META-INF/bundled-dependencies/some-third-party-1-jar-with-dependencies.jar, а остальное - о классе в файле JAR.

Поэтому как один из примеров правильной конфигурации:

<configuration>
  <excludes>
    <exclude>META-INF/**</exclude>
  </excludes>
</configuration>

В доказательство наличия 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 {
}

и src/test/java/ExampleTest.java

public class ExampleTest {
  @org.junit.Test
  public void test() {
  }
}

Исполнение

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

потерпит неудачу с сообщением

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

то же исполнение с pom.xml, содержащим исключение 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>

преуспеет.

В качестве примечания: семантика свойства excludes от prepare-agent цели отличается - он определяет имена классов (независимо от их расположения на диске), которые должны быть исключены из инструментария во время выполнения тестов.

person Godin    schedule 11.05.2018

Я решил проблему дублирования, добавив <phase>prepare-package</phase> в задачу выполнения отчета:

<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>
person Antonio Petricca    schedule 27.05.2020

/ ** предназначен для перехода в базовые каталоги и отличается от *, который является символом подстановки для имен. Отказ от ** может привести к нежелательному эффекту.

person Smart Coder    schedule 08.01.2020
comment
Кажется, что это не ответ на исходный вопрос, но это общий совет. - person RubioRic; 14.05.2021