Как настроить многомодульный Maven + Sonar + JaCoCo для выдачи объединенного отчета о покрытии?

128

Я искал это в Интернете. Есть много полуответов, связанных со свойствами Maven, такими как ${sonar.jacoco.reportPath}, или org.jacoco:jacoco-maven-plugin:prepare-agentили настройка maven-surefire-plugin argLineс помощью -javaagent.

Каким-то образом ни один из этих ответов, ни сам по себе, ни в сочетании, не дает того, что мне нужно: отчет о покрытии, который показывает класс как покрытый, если он используется в тестах выше по стеку, например, используемые сущности от DAO, хотя он не был полностью покрыт тестами в собственном модуле.

Есть ли где-нибудь окончательная конфигурация для этого, пожалуйста?

Стюарт
источник

Ответы:

165

Я был в той же ситуации, что и вы, полуответы, разбросанные по всему Интернету, довольно раздражали, поскольку казалось, что у многих людей была такая же проблема, но никого не удосужилось полностью объяснить, как они ее решили.

Документы Sonar относятся к проекту GitHub с полезными примерами . Для решения этой проблемы я применил логику интеграционных тестов к обычным модульным тестам (хотя правильные модульные тесты должны быть специфичными для подмодуля, это не всегда так).

В родительский файл pom.xml добавьте следующие свойства:

<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>

Это заставит Sonar собирать отчеты модульного тестирования для всех подмодулей в одном месте (целевая папка в родительском проекте). Он также сообщает Sonar о необходимости повторного использования отчетов, запускаемых вручную, вместо создания собственных отчетов. Нам просто нужно запустить jacoco-maven-plugin для всех подмодулей, поместив его в родительский pom внутри 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помещает файл отчета в то место, где Sonar будет его искать, и appendдобавляет к файлу, а не перезаписывает его. Это объединит все отчеты JaCoCo для всех подмодулей в одном файле.

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

mpontes
источник
Замечательное! Это сработало. В заключение! Я думаю, что магия, лишенная жизненного заклинания, которого я не хватало, была <append> истинной </append>
Стюарт
Оно работает! Мне пришлось сделать новое mvn packageперед запуском, mvn sonar:sonarчтобы сгенерировать новый путь отчета.
thomasa88
2
Согласно примеру, свойство sonar.jacoco.itReportPath следует использовать для получения объединенных результатов в «общее покрытие кода». Пожалуйста, обновите ответ.
Ив Мартин
4
"sonar.dynamicAnalysis" также устарел: docs.sonarqube.org/display/SONAR/Release+4.3+Upgrade+Notes
Yves Martin
3
Обновлено Ссылка: docs.sonarqube.org/display/SONARQUBE53/...
Lonzak
23

Вопросы-Ответы

Вопросы в голове с тех пор, как я сошел с ума от жакоко.

Мой сервер приложений (jBoss, Glassfish ..) находится в Ираке, Сирии, где угодно .. Можно ли получить многомодульное покрытие при выполнении интеграционных тестов? Jenkins и Sonar также находятся на разных серверах.

Да. Вы должны использовать агент jacoco, который работает в режиме output=tcpserverjacoco ant lib. В основном два jarс. Это даст вам 99% успеха.

Как работает jacoco agent?

Вы добавляете строку

-javaagent:[your_path]/jacocoagent.jar=destfile=/jacoco.exec,output=tcpserver,address=*

к серверу приложений JAVA_OPTS и перезапустите его. В этой строке [your_path]необходимо заменить только путь к jacocoagent.jar, который хранится (хранится!) На вашей виртуальной машине, на которой работает сервер приложений. С того момента, как вы запустите сервер приложений, все развернутые приложения будут динамически отслеживаться, и их активность (то есть использование кода) будет готова для вас, чтобы вы могли получить в формате jacocos .exec по запросу tcl.

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

Да, для этого вам понадобится jacocoant.jar и скрипт сборки ant, расположенный в вашем рабочем пространстве jenkins.

Итак, в основном то, что мне нужно от http://www.eclemma.org/jacoco/, - это jacocoant.jar, расположенный в моем рабочем пространстве jenkins, и jacocoagent.jar, расположенный на моей виртуальной машине сервера приложений?

Это правильно.

Я не хочу использовать ant, я слышал, что плагин jacoco maven тоже может все.

Это неправильно, плагин jacoco maven может собирать данные модульных тестов и некоторые данные интеграционных тестов (см. Arquillian Jacoco ), но если у вас, например, есть тесты в виде отдельной сборки в jenkins, и вы хотите показать многомодульное покрытие, я могу Не понимаю, чем плагин maven может вам помочь.

Что именно производит агент jacoco?

Только данные о покрытии в .execформате. После этого сонар сможет это прочитать.

Нужно ли jacoco знать, где находятся мои классы Java?

Нет, эхолот, но не jacoco. Когда вы делаете mvn sonar:sonarэто, в игру вступает путь к классам.

Так что насчет сценария муравья?

Он должен быть представлен в вашем рабочем пространстве jenkins. Мой скрипт муравья, я его назвал, jacoco.xmlвыглядит так:

<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>

Два обязательных параметра, которые вы должны передать при вызове этого скрипта, -Dworkspace=$WORKSPACE используйте его, чтобы указать на вашу рабочую область jenkins и -Djacoco.host=yourappserver.comхост безhttp://

Также обратите внимание, что я помещаю свой jacocoant.jarв $ {workspace} /tools/jacoco/jacocoant.jar

Что я должен делать дальше?

Вы запустили сервер приложений с jacocoagent.jar?

Вы поместили ant script и jacocoant.jar в рабочее пространство jenkins?

Если да, последний шаг - настроить сборку jenkins. Вот стратегия:

  1. Вызов ant target jacocoResetдля сброса всех ранее собранных данных.
  2. Проведите свои тесты
  3. Вызвать цель муравья, jacocoReportчтобы получить отчет

Если все в порядке, вы увидите it-jacoco.execв своем рабочем пространстве сборки.

Посмотрите на снимок экрана, я также antустановил в своей рабочей области в $WORKSPACE/tools/antкаталоге, но вы можете использовать тот, который установлен в ваших jenkins.

введите описание изображения здесь

Как протолкнуть этот отчет в сонар?

Maven sonar:sonarвыполнит задание (не забудьте настроить его), направьте его на главный pom.xml, чтобы он прошел через все модули. Используйте sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.execпараметр, чтобы сообщить эхолоту, где находится ваш отчет о тестировании интеграции. Каждый раз, когда он будет анализировать новые классы модулей, он будет искать информацию о покрытии в it-jacoco.exec.

У меня уже есть jacoco.exec в моем каталоге `target`,` mvn sonar: sonar` игнорирует / удаляет его

По умолчанию mvn sonar:sonarделает cleanи удаляет ваш целевой каталог, используйте, sonar.dynamicAnalysis=reuseReportsчтобы избежать этого.

ZuzEL
источник
20

НОВЫЙ СПОСОБ С ВЕРСИИ 0.7.7

Начиная с версии 0.7.7 появился новый способ создания агрегированного отчета:

Вы создаете отдельный проект «отчет», который собирает все необходимые отчеты (любая цель в проекте агрегатора выполняется до его модулей, поэтому его нельзя использовать).

aggregator pom
  |- parent pom
  |- module a
  |- module b
  |- report module 

В корне POM выглядит следующим образом (не забудьте добавить новый модуль отчета под модулями):

<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>

Помы из каждого подмодуля вообще не нужно менять. Пом из модуля отчета выглядит так:

<!-- 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>

Полный пример можно найти здесь .

Lonzak
источник
3
Это работает. В сводном отчете показано совокупное покрытие кода для всех модулей. Вы когда-нибудь пытались просмотреть этот сводный отчет в Sonar? Я использовал sonar-qube для чтения jacoco.exec для отдельных отчетов, но с этим сводным отчетом я не вижу агрегированный jacoco.exec в модуле отчетов.
Swetha V 07
@SwethaV Есть в этом успехи? Мы находимся в таком же положении, и нам нужно найти способ сгенерировать агрегированный exec :)
Vinky
Мы используем sonar qube версии 6.X, у которого есть собственная страница тестового покрытия, поэтому мне не нужен jacoco. Для более старой версии мы установили плагин cobertura, который также обеспечивал эту функциональность ...
Лонзак,
12

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

Для многомодульного проекта Maven:

ROOT
|--WAR
|--LIB-1
|--LIB-2
|--TEST

Если WARпроект является основным веб-приложением, LIB1 и 2 являются дополнительными модулями, от которых WARзависят TESTинтеграционные тесты. TESTзапускает встроенный экземпляр Tomcat (не через плагин Tomcat), запускает WARпроект и тестирует его с помощью набора тестов JUnit. WARИ LIBпроекты оба имеют свои собственные модульные тесты.

Результатом всего этого является разделение покрытия интеграции и модульного тестирования, которое можно различить в 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 и TEST pom.xmlунаследует выполнение плагинов JaCoCo.

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>

Я также обнаружил, что сообщение в блоге Петри Кайнулайненса «Создание отчетов о покрытии кода для модульных и интеграционных тестов с помощью подключаемого модуля JaCoCo Maven» было ценным для установки JaCoCo.

markdsievers
источник
Мне нужно обновить этот пост на каком-то этапе, поскольку он на самом деле немного неоптимален. agent-for-itтребуется только при запуске тестов в TESTмодуле, но в текущей конфигурации он выполняется для всех остальных модулей, где он не имеет значения. Улучшение состояло бы в том, чтобы agent-for-utработать во всех других модулях и agent-for-itтолько в них TEST.
markdsievers
8

Есть способ добиться этого. Магия заключается в создании комбинированного файла jacoco.exec. И с maven 3.3.1 есть простой способ получить это. Вот мой профиль:

<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>

Если вы добавите этот профиль в свой родительский pom и позвоните, mvn clean install sonar:sonar -DrunSonarвы получите полное покрытие.

Магия здесь есть maven.multiModuleProjectDirectory. Эта папка всегда является папкой, в которой вы начали сборку maven.

Свен Опперманн
источник
Это сработало для меня после того, как я перебрал множество других решений.
Джимсон Каннантара Джеймс
Единственная проблема заключалась в том, что мне пришлось запустить сонар с командой mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.0.905:sonar -DrunSonarиз-за A required class was missing while executing org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar: org/sonar/batch/bootstrapper/IssueListenerошибки.
Джимсон Каннантара Джеймс
1
Не используйте эту магию. Данное свойство является деталью реализации и на него нельзя полагаться. - Команда разработчиков Maven
Michael-O
6

Конфигурация, которую я использую в моем pom родительского уровня, где у меня есть отдельные этапы модульного и интеграционного тестирования.

Я настраиваю следующие свойства в родительских свойствах POM

    <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>

Я помещаю определения плагинов в раздел управления плагинами.

Обратите внимание, что я определяю свойство для аргументов surefire (surefireArgLine) и failsafe (failsafeArgLine), чтобы позволить jacoco настроить javaagent для работы с каждым тестом.

Под 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>
            ...

И в разделе сборки

 <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>
        ....

И в разделе отчетов

    <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>
sweetfa
источник
1
Я вижу, у вас есть <append>true</append>конфиг в prepare-agentразделах ...
Стюарт
Особое внимание. Прочтите мой комментарий к другому ответу. Для меня это был недостающий жизненно важный ингредиент, которого нет в других документах.
Стюарт
у вас есть для этого ссылка на github? Я хочу сделать точно такие же конфиги
Рохит Касат 05
@Rhit - нет, по крайней мере, не в публичном репозитории.
sweetfa 05
Это очень хорошо работает с Sonar Qube версии 6.5 (сборка 27846) ...: D Покрытие кода будет отображаться правильно.
udoline
4

Я нашел другое решение для новых версий Sonar, в которых формат двоичного отчета JaCoCo (* .exec) устарел, а предпочтительным форматом является XML (SonarJava 5.12 и выше). Решение очень простое и похоже на предыдущее решение с отчетами * .exec в родительском каталоге из этой темы: https://stackoverflow.com/a/15535970/4448263 .

Предполагая, что структура нашего проекта:

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

Вам нужна следующая конфигурация плагина сборки maven в совокупном 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>

Затем создайте проект с помощью maven:

mvn clean verify

А для Sonar вы должны установить свойство в графическом интерфейсе администрирования:

sonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml,../target/site/jacoco-aggregate/jacoco.xml

или используя командную строку:

mvn sonar:sonar -Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml,../target/site/jacoco-aggregate/jacoco.xml

Описание

Это создает бинарные отчеты для каждого модуля в каталогах по умолчанию: target/jacoco.exec. Затем создает отчеты XML для каждого модуля в каталогах по умолчанию: target/site/jacoco/jacoco.xml. Затем создает сводный отчет для каждого модуля в пользовательском каталоге ${project.basedir}/../target/site/jacoco-aggregate/относительно родительского каталога для каждого модуля. Для moduleA и moduleB это будет общий путь moduleC/target/site/jacoco-aggregate/.

Поскольку модуль B зависит от модуля A, модуль B будет построен последним, и его отчет будет использоваться в качестве сводного отчета о покрытии в Sonar для модулей A и B.

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

Вместе эти два типа отчетов предоставляют данные полного покрытия для Sonar.

Есть одно небольшое ограничение: вы должны иметь возможность писать отчет в родительском каталоге проекта (при наличии разрешения). Или вы можете установить свойство jacoco.skip=trueв корневом проекте pom.xml (moduleC) и jacoco.skip=falseв модулях с классами и тестами (moduleA и moduleB).

Кэддок
источник
3

Как Гидролокаторы sonar.jacoco.reportPath, sonar.jacoco.itReportPathи sonar.jacoco.reportPathsвсе были устаревшими , вы должны использовать в sonar.coverage.jacoco.xmlReportPathsнастоящее время. Это также имеет некоторое влияние, если вы хотите настроить многомодульный проект maven с помощью Sonar и Jacoco.

Как отметил @Lonzak , начиная с Sonar 0.7.7, вы можете использовать цель обострения отчетов Sonar. Просто введите в родительский объект следующую зависимость:

<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>

Поскольку текущие версии jacoco-maven-plugin совместимы с xml-отчетами, это создаст для каждого модуля в его собственной целевой папке папку site / jacoco-aggregate, содержащую jacoco.xmlфайл.

Чтобы позволить Sonar объединить все модули, используйте следующую команду:

mvn -Dsonar.coverage.jacoco.xmlReportPaths=full-path-to-module1/target/site/jacoco-aggregate/jacoco.xml,module2...,module3... clean verify sonar:sonar

Для того, чтобы сохранить мой ответ короткий и точные, я не говоря уже о maven-surefire-pluginи maven-failsafe-pluginзависимости. Вы можете просто добавить их без какой-либо другой конфигурации:

<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>
Якоб ван Линген
источник
2
    <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>             
Майк
источник
1

Вы можете вызвать в maven задачу ant под названием merge , чтобы собрать все файлы покрытия (* .exec) в один файл.

Если вы запускаете модульные тесты, используйте пакет подготовки фазы , если вы запускаете интеграционный тест, используйте post-integration-test .

На этом сайте есть пример вызова задачи jacoco ant в проекте maven.

Вы можете использовать этот объединенный файл на эхолоте.

Андре Пиантино
источник
1

чтобы иметь модульное тестирование И интеграционное тестирование, вы можете использовать maven-surefire-plugin и maven-failsafe-plugin с ограниченными включениями / исключениями. Я играл с CDI, пока контактировал с сонаром / jacoco, поэтому я оказался в этом проекте:

https://github.com/FibreFoX/cdi-sessionscoped-login/

Может, это тебе немного поможет. в моем pom.xml я использую "-javaagent" неявно, устанавливая параметр argLine в разделе конфигурации указанных плагинов тестирования. Явное использование ANT в проектах MAVEN - это то, что я бы не стал пробовать, для меня это слишком много смешивания двух миров.

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

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

FibreFoX
источник
Спасибо за это; Я посмотрю и дам вам знать, как это работает. Возможно, не на этой неделе :)
Стюарт
0

Этот образец мне очень подходит:

<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>
SerhatTopkaya
источник
Пожалуйста, объясните свой ответ
mishsx
@mishsx Хорошая статья для объяснения: natritmeyer.com/howto/…
SerhatTopkaya