Покрытие кода в сборке Maven - Пропуск выполнения JaCoCo из-за отсутствия каталога классов

Я могу получить покрытие кода, работающее нормально, если у меня есть один проект, но теперь у меня есть многомодульный проект.

Мое приложение построено в проекте api, и все мои интеграционные тесты выполняются в отдельном проекте, в котором используется артефакт, созданный как предыдущий модуль.

Сборка выполняется, но я не получаю отчет о покрытии кода, вместо этого я получаю информационное сообщение:

Пропуск выполнения JaCoCo из-за отсутствия каталога классов

Мой файл отчета о покрытии jacoco-it.exec создан, но похоже, что плагину jacoco требуются классы в проекте, в котором выполняются тесты.

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

1 ответ

Решение

Мне удалось получить обходной путь через проб и ошибок.

Кажется, плагин jacoco счастлив создать exec-файл без классов, но он не создаст отчет без них, я не понимаю, как работает jacoco, поэтому, если кто-то знает, не могли бы вы объяснить это?

Я также не уверен, что то, что я сделал, является надежным, но, похоже, оно сообщает об охвате моих тестов на селен.

Мое (возможное) решение, которое я придумал сам, - это использовать плагин ресурсов maven, чтобы скопировать классы, которые были разобраны из файла war в моем каталоге target\cargo.., в каталог target \ classes:

 <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <version>2.7</version>
        <executions>
          <execution>
            <id>copy-resources</id>             
            <phase>pre-integration-test</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>${basedir}/target/classes</outputDirectory>
              <resources>          
                <resource>
                  <directory>${basedir}/target/cargo/configurations/tomcat7x/webapps/calculator-api/WEB-INF/classes</directory>
                  <filtering>false</filtering>
                  <excludes>
                        <exclude>**/*Config*.*</exclude>
                        <exclude>**/*Initialiser*.*</exclude>
                  </excludes>
                </resource>
              </resources>              
            </configuration>            
          </execution>
        </executions>
    </plugin>

Это, кажется, делает плагин jacoco счастливым, и я получаю покрытие кода, хотя кажется, что плагин теперь игнорирует мой список исключений.

Кто-нибудь знает, если это действительно решение, оно "кажется" работает, но я не могу найти где-нибудь в Интернете, где это рекомендуемый подход, и я также не уверен, почему опция exclude в настройке агента jacoco больше не работает.

Мне удалось обойти плагин jacoco, не исключая файлы, просто не копируя их с плагином ресурсов, но я до сих пор не понимаю, как именно работает jacoco.

Даже не смотря на jacoco:report-aggregate предназначался для агрегированного отчета по зависимостям, в моем случае он не работал - я использую структуру проекта, например:

project
└─ module-api   ⇦ API definition
└─ module-spec  ⇦ module with black box tests through the API
└─ module-impl1 ⇦ implementation 1 of the API
└─ module-impl2 ⇦ another implementation of the API
└─ module-test1 ⇦ some dependencies + impl1, apply the tests from spec
└─ module-test2 ⇦ some dependencies + impl2, apply the tests from spec

В этом случае report-aggregateсформировал пустой отчет. Проекты module-test1 и module-test2 имеют тип упаковки POM, который не подходит для запуска.report на них тоже, поскольку для этого требуются классы в каталоге target / classes.

Мое решение

Я настроил плагин jacoco, чтобы выгрузить классы, которые он использует в каталоге target / classes проекта, добавив:<classDumpDir>${project.build.outputDirectory}</classDumpDir>

Это позволило регулярному reportцель работать. Полный код:

<plugin>
  <groupId>org.jacoco</groupId>
  <artifactId>jacoco-maven-plugin</artifactId>
  <version>0.8.5</version>
  <configuration>
    <destFile>${project.build.directory}/coverage-reports/code-coverage.exec</destFile>
    <dataFile>${project.build.directory}/coverage-reports/code-coverage.exec</dataFile>
    <outputDirectory>${project.reporting.outputDirectory}/code-coverage</outputDirectory>
    <propertyName>jacocoArgLine</propertyName>
    <classDumpDir>${project.build.outputDirectory}</classDumpDir>
  </configuration>
  <executions>
    <execution>
      <id>prepare-jacoco-agent</id>
      <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>

Обратите внимание, что инструментированные классы принадлежат ко всем зависимостям, поэтому потребуется некоторая фильтрация, чтобы сузить область действия отчета. См. https://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html

У меня аналогичная структура проекта - основной код находится в одном модуле, а тесты - в другом - и возникла аналогичная проблема с отчетами jacoco.

Мое решение 1:

Просто скопируйте /classes папка для тестирования модуля maven-resources-plugin.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.1.0</version>
    <executions>
       <execution>
         <id>copy-classes-to-test-module</id>
         <goals>
             <goal>testResources</goal>
         </goals>
         <configuration>
             <resources>
                 <resource>
                     <directory>${project.basedir}/../main-module/target/classes</directory>
                 </resource>
             </resources>
             <outputDirectory>
                    ${project.build.outputDirectory}
             </outputDirectory>
          </configuration>
        </execution>
     </executions>
</plugin>

Но если ваш код содержит лямбды, анонимные классы и т. Д., То отчет о результатах может не охватывать некоторые классы, потому что это будут разные классы из-за разных prepare-agent бежит.

Мое решение 2:

Использовать report-aggregate Цель.

В родительском POM у меня есть такая конфигурация:

<plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.3</version>
        <configuration>
            <append>true</append>
        </configuration>
        <executions>
            <execution>
                <id>prepare-agent</id>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
            </execution>
        </executions>
</plugin>

И POM тестового модуля содержит следующие строки:

        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <executions>
                <execution>
                    <id>report</id>
                    <phase>test</phase>
                    <goals>
                        <goal>report-aggregate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

Помните, что область зависимости важна для report-aggregateцель (jacoco docs). Если ваш тестовый модуль имеет только зависимости в тестовой области, вы получите пустой отчет. Следовательно, вы должны установить область для компиляции, выполнения или предоставления тех артефактов, которые вы хотите видеть в отчете. Например:

    <dependency>
        <groupId>my.project</groupId>
        <artifactId>main-module-classes</artifactId>
        <version>${project.version}</version>
        <scope>provided</scope>
    </dependency>

Вы можете использовать цель jacoco:report-aggregate который как раз предназначен для создания отчетов о покрытии в отдельном тестовом модуле.

Вот пример:

project
└─ module      ⇦ module with sources
└─ module-test ⇦ module with tests

Тогда все, что вам нужно сделать, это использовать эту цель в pom.xml файла "module-test":

    <build>
        <plugins>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco.version}</version>
                <executions>
                    <execution>
                        <id>jacoco-report-aggregate</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>report-aggregate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

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

Другие вопросы по тегам