Comment configurer Maven + Sonar + JaCoCo multi-module pour donner un rapport de couverture fusionnée?

128

J'ai cherché celui-ci sur Internet. Il y a beaucoup de demi-réponses, à voir avec les propriétés Maven telles que ${sonar.jacoco.reportPath}, ou org.jacoco:jacoco-maven-plugin:prepare-agentou maven-surefire-plugin argLineavec -javaagent.

Certains comment, aucune de ces réponses, seules ou en combinaison, ne produit ce que je cherche: un rapport de couverture qui montre une classe comme couverte si elle est utilisée dans des tests plus haut dans la pile, comme les entités utilisées par les DAO, même s'il n'a pas été entièrement couvert par des tests dans son propre module.

Y a-t-il une configuration définitive quelque part, pour y parvenir, s'il vous plaît?

Stewart
la source

Réponses:

165

J'étais dans la même situation que vous, les demi-réponses éparpillées sur Internet étaient assez ennuyeuses, car il semblait que beaucoup de gens avaient le même problème, mais personne ne pouvait être dérangé d'expliquer pleinement comment ils l'ont résolu.

La documentation Sonar fait référence à un projet GitHub avec des exemples utiles. Ce que j'ai fait pour résoudre ce problème, c'était d'appliquer la logique des tests d'intégration aux tests unitaires réguliers (bien que les tests unitaires appropriés devraient être spécifiques au sous-module, ce n'est pas toujours le cas).

Dans le pom.xml parent, ajoutez ces propriétés:

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

Cela permettra à Sonar de récupérer les rapports de test unitaire pour tous les sous-modules au même endroit (un dossier cible dans le projet parent). Il indique également à Sonar de réutiliser les rapports exécutés manuellement au lieu de lancer les siens. Nous avons juste besoin de faire fonctionner jacoco-maven-plugin pour tous les sous-modules en le plaçant dans le pom parent, à l'intérieur de 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>

destFileplace le fichier de rapport à l'endroit où Sonar le recherchera et le appendfait ajouter au fichier plutôt que de l'écraser. Cela combinera tous les rapports JaCoCo pour tous les sous-modules dans le même fichier.

Sonar examinera ce fichier pour chaque sous-module, car c'est ce que nous lui avons indiqué ci-dessus, nous donnant des résultats de tests unitaires combinés pour les fichiers multi-modules dans Sonar.

mpontes
la source
Merveilleux! Cela a fonctionné. Finalement! Je pense que l'incantation vitale magique manquante qui me manquait était <append> vraie </append>
Stewart
Ça marche! J'ai dû faire un nouveau mvn packageavant de courir mvn sonar:sonarpour obtenir le nouveau chemin du rapport généré.
thomasa88
2
Selon l'exemple, la propriété "sonar.jacoco.itReportPath" doit être utilisée pour obtenir les résultats fusionnés en "couverture globale du code". Veuillez mettre à jour la réponse.
Yves Martin
4
"sonar.dynamicAnalysis" est également obsolète: docs.sonarqube.org/display/SONAR/Release+4.3+Upgrade+Notes
Yves Martin
3
Lien mis à jour: docs.sonarqube.org/display/SONARQUBE53/…
Lonzak
23

FAQ

Des questions du haut de ma tête depuis que je suis devenu fou de jacoco.

Mon serveur d'application (jBoss, Glassfish ..) situé en Irak, en Syrie, peu importe .. Est-il possible d'obtenir une couverture multi-module lors de l'exécution de tests d'intégration? Jenkins et Sonar sont également sur des serveurs différents.

Oui. Vous devez utiliser l' agent jacoco qui s'exécute en mode output=tcpserver, jacoco ant lib. Fondamentalement, deux jars. Cela vous donnera 99% de succès.

Comment fonctionne l'agent Jacoco?

Vous ajoutez une chaîne

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

sur votre serveur d'applications JAVA_OPTS et redémarrez-le. Dans cette chaîne, il suffit [your_path]de remplacer le chemin vers jacocoagent.jar, stocké (stockez-le!) Sur votre machine virtuelle où le serveur d'applications s'exécute. Depuis que vous démarrez le serveur d'applications, toutes les applications déployées seront surveillées de manière dynamique et leur activité (c'est-à-dire l'utilisation du code) sera prête pour que vous puissiez obtenir le format jacocos .exec par requête tcl.

Puis-je réinitialiser l'agent jacoco pour commencer à collecter les données d'exécution uniquement depuis le début de mon test?

Oui, pour cela, vous avez besoin du script jacocoant.jar et ant build situé dans votre espace de travail jenkins.

Donc, fondamentalement, ce dont j'ai besoin de http://www.eclemma.org/jacoco/ est jacocoant.jar situé dans mon espace de travail jenkins et jacocoagent.jar situé sur ma VM de serveur d'applications?

C'est vrai.

Je ne veux pas utiliser fourmi, j'ai entendu dire que le plugin jacoco maven peut faire toutes les choses aussi.

Ce n'est pas vrai, le plugin jacoco maven peut collecter des données de test unitaire et des données de tests d'intégration (voir Arquillian Jacoco ), mais si vous avez par exemple des tests rassurés en tant que build séparé dans jenkins, et que vous souhaitez afficher une couverture multi-module, je peux ne voyez pas comment le plugin maven peut vous aider.

Que produit exactement l'agent jacoco?

Uniquement les données de couverture au .execformat. Sonar peut alors le lire.

Jacoco a-t-il besoin de savoir où se trouvent mes classes Java?

Non, le sonar le fait, mais pas le jacoco. Lorsque vous faites le mvn sonar:sonarchemin vers les classes entre en jeu.

Alors qu'en est-il du script de fourmi?

Il doit être présenté dans votre espace de travail jenkins. Mine script de fourmi, j'ai appelé ça jacoco.xmlressemble à ça:

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

Deux paramètres obligatoires que vous devez passer lors de l'appel de ce script, -Dworkspace=$WORKSPACE utilisez-le pour pointer vers votre espace de travail jenkins et l' -Djacoco.host=yourappserver.comhôte sanshttp://

Notez également que j'ai placé mon jacocoant.jardans $ {workspace} /tools/jacoco/jacocoant.jar

Que devrais-je faire ensuite?

Avez-vous démarré votre serveur d'applications avec jacocoagent.jar?

Avez-vous mis le script ant et jacocoant.jar dans votre espace de travail jenkins?

Si oui, la dernière étape consiste à configurer une version jenkins. Voici la stratégie:

  1. Appelez la cible fourmi jacocoResetpour réinitialiser toutes les données précédemment collectées.
  2. Exécutez vos tests
  3. Invoquer la cible fourmi jacocoReportpour obtenir le rapport

Si tout est correct, vous verrez it-jacoco.execdans votre espace de travail de construction.

Regardez la capture d'écran, j'ai également antinstallé dans mon espace de travail dans $WORKSPACE/tools/antdir, mais vous pouvez en utiliser un qui est installé dans votre jenkins.

entrez la description de l'image ici

Comment pousser ce rapport dans sonar?

Maven sonar:sonarfera le travail (n'oubliez pas de le configurer), pointez-le vers le pom.xml principal pour qu'il s'exécute à travers tous les modules. Utilisez le sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.execparamètre pour indiquer au sondeur où se trouve votre rapport de test d'intégration. Chaque fois qu'il analysera de nouvelles classes de modules, il recherchera des informations sur la couverture dans it-jacoco.exec.

J'ai déjà jacoco.exec dans mon répertoire `target`,` mvn sonar: sonar` l'ignore / le supprime

Par défaut mvn sonar:sonarfait cleanet supprime votre répertoire cible, utilisez sonar.dynamicAnalysis=reuseReportspour l'éviter.

ZuzEL
la source
20

NOUVELLE FAÇON DEPUIS LA VERSION 0.7.7

Depuis la version 0.7.7, il existe une nouvelle façon de créer un rapport agrégé:

Vous créez un projet 'rapport' séparé qui rassemble tous les rapports nécessaires (tout objectif du projet d'agrégateur est exécuté avant ses modules, il ne peut donc pas être utilisé).

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

Le pom racine ressemble à ceci (n'oubliez pas d'ajouter le nouveau module de rapport sous modules):

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

Les poms de chaque sous-module n'ont pas du tout besoin d'être modifiés. Le pom du module de rapport ressemble à ceci:

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

Un exemple complet peut être trouvé ici .

Lonzak
la source
3
Cela marche. Le rapport agrégé montre la couverture de code cumulée pour tous les modules. Avez-vous déjà essayé d'afficher ce rapport cumulatif dans Sonar? J'ai utilisé sonar-qube pour lire jacoco.exec pour les rapports individuels, mais avec cet agrégat de rapport, je ne vois pas de jacoco.exec agrégé dans le module de rapport.
Swetha V
@SwethaV Quel est le succès dans ce domaine? Nous sommes dans la même position et devons trouver un moyen de générer l'
exécutable
Nous utilisons la version 6.X de sonar qube qui a sa propre page de couverture de test, donc je n'ai pas besoin de jacoco. Pour une version plus ancienne, nous avons installé le plugin cobertura qui fournissait également cette fonctionnalité ...
Lonzak
12

Je posterai ma solution car elle est subtilement différente des autres et m'a également pris une journée solide pour bien faire, avec l'aide des réponses existantes.

Pour un projet Maven multi-modules:

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

Lorsque le WARprojet est l'application Web principale, LIB1 et 2 sont des modules supplémentaires dont WARdépend etTEST où les tests d'intégration se déroulent. TESTlance une instance Tomcat intégrée (pas via le plugin Tomcat) et exécute le WARprojet et les teste via un ensemble de tests JUnit. Les WARet les LIBprojets ont tous deux leurs propres tests unitaires.

Le résultat de tout cela est que l'intégration et la couverture des tests unitaires sont séparées et peuvent être distinguées dans 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 et TEST pom.xmlhéritera de l'exécution des plugins 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>

J'ai également trouvé que l' article de blog de Petri Kainulainens «Création de rapports de couverture de code pour les tests unitaires et d'intégration avec le plugin JaCoCo Maven» était précieux pour le côté configuration de JaCoCo.

Markdsievers
la source
J'ai besoin de mettre à jour ce post à un moment donné car il est en fait un peu sous-optimal. agent-for-itn'est nécessaire que lors de l'exécution des tests dans le TESTmodule, mais la configuration actuelle le fait fonctionner pour tous les autres modules, où il n'a aucune valeur. L'amélioration serait d'avoir agent-for-utexécuté dans tous les autres modules et agent-for-itseulement fonctionner TEST.
markdsievers
8

Il existe un moyen d'accomplir cela. La magie est de créer un fichier jacoco.exec combiné. Et avec maven 3.3.1, il existe un moyen facile d'obtenir cela. Voici mon profil:

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

Si vous ajoutez ce profil à votre pom parent et appelez mvn clean install sonar:sonar -DrunSonar vous obtenez une couverture complète.

La magie ici est maven.multiModuleProjectDirectory. Ce dossier est toujours le dossier dans lequel vous avez démarré votre build maven.

Sven Oppermann
la source
Cela a fonctionné pour moi, après avoir traversé de nombreuses autres solutions.
Jimson Kannanthara James
Le seul problème était que je devais exécuter le sondeur avec commande, en mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.0.905:sonar -DrunSonarraison d'une A required class was missing while executing org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar: org/sonar/batch/bootstrapper/IssueListenererreur.
Jimson Kannanthara James
1
N'utilisez pas cette magie. La propriété donnée est un détail d'implémentation et ne doit pas être invoquée. - L'équipe de développement Maven
Michael-O
6

La configuration que j'utilise dans mon pom de niveau parent où j'ai des phases de test d'unité et d'intégration séparées.

Je configure les propriétés suivantes dans les propriétés du POM parent

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

Je place les définitions de plugin sous la gestion des plugins.

Notez que je définis une propriété pour les arguments surefire (surefireArgLine) et failafe (failafeArgLine) pour permettre à jacoco de configurer le javaagent pour qu'il s'exécute avec chaque test.

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

Et dans la section construction

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

Et dans la section reporting

    <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
la source
1
Je vois que vous avez la <append>true</append>config sous les prepare-agentsections ...
Stewart
Accentuation. Lisez mon commentaire sur une autre réponse. C'était l'ingrédient vital manquant pour moi, introuvable dans d'autres documents.
Stewart
avez-vous un lien github pour cela? Je veux faire des configs exactement similaires
Rohit Kasat
@Rhit - non je ne le fais pas, du moins pas dans un référentiel public.
sweetfa
Cela fonctionne très bien avec Sonar Qube Version 6.5 (build 27846) ...: D La couverture du code sera correctement affichée.
udoline
4

J'ai trouvé une autre solution pour les nouvelles versions de Sonar où le format de rapport binaire de JaCoCo (* .exec) était obsolète et le format préféré est XML (SonarJava 5.12 et supérieur). La solution est très simple et similaire à la solution précédente avec des rapports * .exec dans le répertoire parent de cette rubrique: https://stackoverflow.com/a/15535970/4448263 .

En supposant que la structure de notre projet est:

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

Vous avez besoin de la configuration suivante du plugin maven build dans le pom du projet global:

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

Puis construisez un projet avec maven:

mvn clean verify

Et pour Sonar, vous devez définir la propriété dans l'interface graphique d'administration:

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

ou en utilisant la ligne de commande:

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

La description

Cela crée des rapports binaires pour chaque module dans les répertoires par défaut: target/jacoco.exec. Crée ensuite des rapports XML pour chaque module dans les répertoires par défaut: target/site/jacoco/jacoco.xml. Crée ensuite un rapport agrégé pour chaque module dans le répertoire personnalisé ${project.basedir}/../target/site/jacoco-aggregate/relatif au répertoire parent de chaque module. Pour moduleA et moduleB, ce sera le chemin communmoduleC/target/site/jacoco-aggregate/ .

Comme moduleB dépend du moduleA, moduleB sera construit en dernier et son rapport sera utilisé comme un rapport de couverture agrégé dans Sonar pour les modules A et B.

En plus du rapport agrégé, nous avons besoin d'un rapport de module normal car les rapports agrégés JaCoCo contiennent des données de couverture uniquement pour les dépendances.

Ensemble, ces deux types de rapports fournissent des données de couverture complète pour Sonar.

Il y a une petite restriction: vous devriez pouvoir écrire un rapport dans le répertoire parent du projet (devrait avoir la permission). Ou vous pouvez définir la propriété jacoco.skip=truedans le pom.xml du projet racine (moduleC) et jacoco.skip=falsedans les modules avec des classes et des tests (moduleA et moduleB).

keddok
la source
3

En tant que Sonars sonar.jacoco.reportPath, sonar.jacoco.itReportPathet sonar.jacoco.reportPathsont tous été obsolètes , vous devriez les utiliser sonar.coverage.jacoco.xmlReportPathsmaintenant. Cela a également un impact si vous souhaitez configurer un projet maven multi-modules avec Sonar et Jacoco.

Comme @Lonzak l'a souligné , depuis Sonar 0.7.7, vous pouvez utiliser l'objectif d'agrégation des rapports Sonars. Mettez simplement dans votre pom parent la dépendance suivante:

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

Comme les versions actuelles du plugin jacoco-maven sont compatibles avec les rapports xml, cela créera pour chaque module de son propre dossier cible un dossier site / jacoco-aggregate contenant unjacoco.xml fichier.

Pour permettre à Sonar de combiner tous les modules, utilisez la commande suivante:

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

Pour garder ma réponse courte et précise, je n'ai pas mentionné les dépendances maven-surefire-pluginet maven-failsafe-plugin. Vous pouvez simplement les ajouter sans aucune autre configuration:

<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>
Jacob van Lingen
la source
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>             
Mike
la source
1

Vous pouvez appeler une tâche fourmi appelée fusion sur maven, pour regrouper tous les fichiers de couverture (* .exec) dans le même fichier.

Si vous exécutez des tests unitaires, utilisez le package de préparation de phase , si vous exécutez un test d'intégration, utilisez le test de post-intégration .

Ce site a un exemple de comment appeler la tâche de fourmi jacoco dans le projet maven

Vous pouvez utiliser ce fichier fusionné sur le sondeur.

André Piantino
la source
1

pour avoir des tests unitaires ET des tests d'intégration, vous pouvez utiliser maven-surefire-plugin et maven-failafe-plugin avec des inclusions / exclusions restreintes. Je jouais avec CDI en entrant en contact avec sonar / jacoco, donc je me suis retrouvé dans ce projet:

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

Peut-être que cela vous aide un peu. dans mon pom.xml, j'utilise "-javaagent" implicite en définissant l'option argLine dans la section de configuration des plugins de test spécifiés. L'utilisation explicite d'ANT dans les projets MAVEN est quelque chose que je ne voudrais pas essayer, pour moi, c'est trop mélanger deux mondes.

Je n'ai qu'un projet maven à module unique, mais peut-être que cela vous aide à adapter le vôtre au travail.

Remarque: peut-être que tous les plugins maven ne sont pas up2date, peut-être que certains problèmes sont résolus dans les versions ultérieures

FibreFoX
la source
Merci pour cela; Je vais jeter un oeil et vous dire comment cela fonctionne. Peut-être pas cette semaine cependant :)
Stewart
0

Cet exemple fonctionne très bien pour moi:

<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
la source
Veuillez expliquer votre réponse
mishsx
@mishsx Un bel article pour l'explication: natritmeyer.com/howto/…
SerhatTopkaya