Як налаштувати мультимодульний Maven + Sonar + JaCoCo, щоб дати зведений звіт про покриття?


128

Я шукав цей Інтернет. Там багато половин відповідей там, щоб зробити з властивостями Maven , таких як ${sonar.jacoco.reportPath}, або org.jacoco:jacoco-maven-plugin:prepare-agentчи налаштування maven-surefire-plugin argLineз-javaagent .

Ось як, жоден із цих відповідей, ні самостійно, ні в поєднанні, не створює те, про що я пішов: Звіт про покриття, який показує клас як охоплений, якщо він використовується в тестах вище стека, таких як сутності, що використовуються DAO, хоча він не був повністю охоплений тестами у власному модулі.

Чи є десь остаточний конфігуратор, щоб досягти цього, будь ласка?

Відповіді:


164

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

Документи 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-плагін працювати для всіх підмодулів, помістивши це в батьківський пом, всередині 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.


Чудовий! Це спрацювало. Нарешті! Я думаю, що магія, що відсутня життєвий заклик, який я пропав, був <append> true </append>
Стюарт

Це працює! mvn packageПеред тим, як запустити, мені довелося зробити нове, mvn sonar:sonarщоб створити новий шлях до звіту.
thomasa88

2
Згідно з прикладом, властивість "sonar.jacoco.itReportPath" слід використовувати для об'єднання результатів у "загальне покриття коду". Оновіть відповідь.
Ів Мартін

4
"sonar.dynamicAnalysis" також застаріло: docs.sonarqube.org/display/SONAR/Release+4.3+Upgrade+Notes
Ів Мартін

3
Оновлене посилання: docs.sonarqube.org/display/SONARQUBE53/…
Лонзак

23

FAQ

Питання зверху в голові з того часу, як я з глузду зійшов з якоко.

Мій сервер додатків (jBoss, Glassfish ..), розташований в Іраку, Сирії, як би там не було .. Чи можливо отримати багатомодульне покриття під час запуску інтеграційних тестів на ньому? Дженкінс і Сонар також на різних серверах.

Так. Ви повинні використовувати агент, який працює в режимі output=tcpserver, мукомольна мурашка. В основному дваjar с. Це дасть вам 99% успіху.

Як діє агент «Якоко»?

Ви додаєте рядок

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

на сервер додатків JAVA_OPTS і перезавантажте його. Лише в цьому рядку[your_path] замінити шлях до jacocoagent.jar, зберігати (зберігати його!) У вашій машині вільного доступу, де працює сервер додатків. З цього часу, коли ви запускаєте сервер додатків, усі розгорнуті додатки будуть динамічно відстежуватися, і їх активність (тобто використання коду) буде готова до отримання у форматі jacocos .exec за запитом tcl.

Чи можу я скинути jacoco агент, щоб почати збирати дані про виконання лише з моменту початку мого тесту?

Так, для цього вам потрібен сценарій jacocoant.jar та мурахи, розташований у вашій робочій області jenkins.

Отже, що мені потрібно від http://www.eclemma.org/jacoco/, це jacocoant.jar, розташований у моїй робочій області jenkins, і jacocoagent.jar, розміщений на моєму сервері програм VM?

Це вірно.

Я не хочу використовувати мурашок, я чув, що плагін jacoco maven теж може робити все.

Це неправильно, плагін jacoco maven може збирати дані про тести блоку та деякі дані інтеграційних тестів (див. Arquillian Jacoco ), але якщо у вас є, наприклад, спокійні тести, як окрема збірка в джинкінах, і хочете показати багатомодульне покриття, я можу Не бачу, як плагін Maven може вам допомогти.

Що саме виробляє агент Якоко?

Лише дані покриття в .exec форматі. Тоді Сонар може це прочитати.

Чи потрібно якоко знати, де знаходяться мої класи java?

Ні, сонар робить, але не якоко. Коли ви робитеmvn sonar:sonar шлях до занять, вступає в гру.

То як щодо сценарію мурашок?

Він повинен бути представлений у вашому робочому просторі джинкінів. Сценарій моєї мурашки, я назвав це 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 використовуйте його для вказівки на робочу область і -Djacoco.host=yourappserver.comхост без jenkinshttp://

Також зауважте, що я помістив його jacocoant.jarв $ {workpace} /tools/jacoco/jacocoant.jar

Що мені робити далі?

Ви запустили свій сервер додатків з jacocoagent.jar?

Ви помістили мурашиний скрипт та jacocoant.jar у робочу область для дженкінсів?

Якщо так, то останнім кроком є ​​налаштування збірки джинкінів. Ось стратегія:

  1. Викликати мурашину ціль, jacocoResetщоб скинути всі раніше зібрані дані.
  2. Запустіть свої тести
  3. Викликайте мурашку, jacocoReportщоб отримати звіт

Якщо все в порядку, ви побачите it-jacoco.exec у робочій області побудови.

Подивіться на скріншот, я також antвстановив у своїй робочій області в режимі $WORKSPACE/tools/antdir, але ви можете використовувати той, який встановлений у ваших джинкінах.

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

Як просунути цей звіт у сонарі?

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

У мене вже є jacoco.exec у своєму `target 'dir,` mvn sonar: sonar` ігнорує / видаляє його

За замовчуванням mvn sonar:sonarробить cleanі видаляє цільовий режим, використовуйте, sonar.dynamicAnalysis=reuseReportsщоб уникнути цього.


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>

Poms з кожного підмодуля взагалі не потрібно міняти. Пом з модуля звіту виглядає так:

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

Повний приклад можна знайти тут .


3
Це працює. Зведений звіт показує сукупне покриття коду для всіх модулів. Ви коли-небудь намагалися переглянути цей накопичувальний звіт у Sonar? Я використовував sonar-qube для читання jacoco.exec для окремих звітів, однак у цій сукупності звітів я не бачу зведеного jacoco.exec у модулі звітів.
Swetha V

@SwethaV Будь-який успіх у цьому? Ми в такому ж становищі і нам потрібно знайти спосіб генерувати зведений exec :)
Vinky

Ми використовуємо Sonar qube версії 6.X, яка має власну сторінку тестового покриття, тому мені там не потрібно якоко. Для старішої версії ми встановили плагін Cobertura, який також забезпечував цю функціональність ...
Lonzak

11

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

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

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

Там, де WARпроект є основним веб-додатком, LIB1 і 2 - це додаткові модулі, WARзалежить від того TEST, де проходять інтеграційні тести. TESTзапускає вбудований екземпляр Tomcat (не через плагін Tomcat) і запускає WARпроект і тестує їх за допомогою набору тестів JUnit. The 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.


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

7

Є спосіб досягти цього. Магія полягає у створенні комбінованого файлу 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>

Якщо ви додасте цей профіль до свого батьківського пам’яті та зателефонуйте 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

    <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 для запуску кожного тесту.

Під плагіном Управління

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

1
Я бачу, ви маєте <append>true</append>конфігурацію під prepare-agentрозділами ...
Стюарт

Наголос. Прочитайте мій коментар до іншої відповіді. Це був найважливіший інгредієнт для мене, який не можна знайти в інших документах.
Стюарт

у вас для цього є посилання github? Хочу зробити точно подібні
конфігурації

@Rhit - ні, я, принаймні, не в публічному сховищі.
sweetfa

Це дуже добре працює з Sonar Qube версії 6.5 (збірка 27846) ...: D Покриття коду буде правильно відображено.
удолін

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 build в сукупності пам’яті проекту:

<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/який є відносним до батьківського каталогу кожного модуля. Для модуляA та moduleB це буде загальний шляхmoduleC/target/site/jacoco-aggregate/ .

Оскільки moduleB залежить від moduleA, moduleB буде побудований останнім, і його звіт буде використовуватися як сукупний звіт про покриття в Sonar для обох модулів A і B.

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

Ці два типи разом надають повні дані про покриття для Sonar.

Існує одне невелике обмеження: ви повинні мати можливість написати звіт у батьківському каталозі проекту (повинен мати дозвіл). Або ви можете встановити властивість jacoco.skip=trueу корінному проекті pom.xml (moduleC) та jacoco.skip=falseу модулях із класами та тестами (moduleA та moduleB).


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>             

2

Оскільки "Сонари" sonar.jacoco.reportPath, sonar.jacoco.itReportPathі sonar.jacoco.reportPathsвсі вони застарілі , вам слід скористатися sonar.coverage.jacoco.xmlReportPathsзараз. Це також має певний вплив, якщо ви хочете налаштувати багатомодульний проект maven з Sonar та Jacoco.

Як зазначав @Lonzak , оскільки Sonar 0.7.7 ви можете використовувати ціль загострення звітів Sonars. Просто поставте до вас батьків наступну залежність:

<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 сумісні з xml-звітами, це створить для кожного модуля в його власній цільовій папці сайт / папку jacoco-агрегат, що містить 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>

1

Ви можете викликати мурашину задачу злиття on maven, щоб зібрати всі файли покриття (* .exec) разом у одному файлі.

Якщо ви виконуєте тестові одиниці, використовуйте пакет підготовки фаз , якщо ви запускаєте тест інтеграції після інтеграції .

Цей сайт є приклад того, як викликати завдання мурашки з джакоко в проект Maven

Ви можете використовувати цей об'єднаний файл у сонарі.


0

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

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

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

У мене є лише одномодульний проект Maven, але, можливо, він допоможе вам налаштувати свою роботу.

Примітка: можливо, не всі Maven-плагіни оновлені2, можливо, деякі проблеми виправлені в пізніших версіях


Дякую за це; Я погляну і повідомлю, як це виходить. Можливо, цього тижня не буде :)
Стюарт

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>

Будь ласка, надайте пояснення до своєї відповіді
mishsx

@mishsx Приємна стаття для пояснення: natritmeyer.com/howto/…
SerhatTopkaya
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.