Question

J'ai un projet Maven avec 4 modules - 3 d’entre eux contiennent du code et des tests (testing égaux et hashcode des classes) alors que le 4ème module est destiné à tester les 3 autres modules.

Maintenant, je veux utiliser l'outil de couverture de code cobertura pour avoir un aperçu des classes qui ont été bien testées et de celles qui ne le sont pas. J'ai effectué des recherches sur ce sujet et il semble que cobertura n'ait pas conscience de générer les bons pourcentages de couverture de code et de couverture de ligne, si certaines sources testées sont situées dans d'autres modules.

J'ai lu des liens tels que SeamTestCoverageWithCobertura et Utilisation du plugin Couverture dans un multi -module Maven 2 , mais il doit exister une solution prête à l'emploi. Quelqu'un peut-il signaler de nouvelles orientations sur ce sujet? Ou existe-t-il des outils tels que cobertura? Je suis tombé sur emma mais cet outil n’offre pas de couverture en ligne ...

Était-ce utile?

La solution

Depuis la version 2.6, une option d'agrégat peut être définie sur true dans le pom parent:

<reporting>
<plugins>
  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>cobertura-maven-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <outputDirectory>./target/tmpCobertura</outputDirectory>
        <formats>
            <format>html</format>
        </formats>
        <aggregate>true</aggregate>
    </configuration>
  </plugin>
</plugins>
</reporting>

Autres conseils

Nous n’avons pas de sonar ici et pour l’instant, nous ne pouvons pas l’installer. Je devais donc trouver une solution de contournement et en obtenir un. Cette solution fonctionne avec un simple mvn clean install -DrunCobertura=true dans un projet multi-module. Vous devez seulement ajouter ce profil à votre super pom.xml de votre projet, définir la propriété working.dir et cela devrait fonctionner.

<profile>
    <id>runCobertura</id>
    <activation>
        <property>
            <name>runCobertura</name>
            <value>true</value>
        </property>
    </activation>
    <properties>
        <cobertura.format>html</cobertura.format>
        <cobertura.working.dir>${working.dir}/${project.version}/cobertura</cobertura.working.dir>
        <cobertura.complete.ser.file>${cobertura.working.dir}/complete.ser</cobertura.complete.ser.file>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.4.1</version>
                <inherited>false</inherited>
                <configuration>
                    <filesets>
                        <fileset>
                            <directory>.</directory>
                            <includes>
                                <include>cobertura.ser</include>
                            </includes>
                        </fileset>
                        <fileset>
                                <directory>${cobertura.working.dir}</directory>
                            </fileset>
                    </filesets>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.7</version>
                <executions>
                    <execution>
                        <id>cobertura-Instrument</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <taskdef resource="tasks.properties"/>
                                <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                <if>
                                    <available file="${project.build.outputDirectory}"/>
                                    <then>
                                        <cobertura-instrument>
                                            <fileset dir="${project.build.outputDirectory}">
                                                <include name="**/*.class"/>
                                            </fileset>
                                        </cobertura-instrument>
                                    </then>
                                </if>
                            </target>
                        </configuration>
                    </execution>
                    <execution>
                        <id>cobertura-createCombinedSerFile</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <taskdef resource="tasks.properties"/>
                                <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                <if>
                                    <available file="${cobertura.complete.ser.file}"/>
                                    <then>
                                        <cobertura-merge datafile="${basedir}/tmp.ser">
                                            <fileset file="${cobertura.complete.ser.file}"/>
                                            <fileset file="${basedir}/cobertura.ser"/>
                                        </cobertura-merge>
                                        <move file="${basedir}/tmp.ser" tofile="${basedir}/cobertura.ser"/>
                                    </then>
                                </if>
                            </target>
                        </configuration>
                    </execution>
                    <execution>
                        <id>cobertura-copyResultSerFileAndSources</id>
                        <phase>test</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <taskdef resource="tasks.properties"/>
                                <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                <if>
                                    <available file="${basedir}/cobertura.ser"/>
                                    <then>
                                        <move file="${basedir}/cobertura.ser" tofile="${cobertura.complete.ser.file}"/>
                                        <mkdir dir="${cobertura.working.dir}/source"/>
                                        <if>
                                            <available file="${basedir}/src/main/java"/>
                                            <then>
                                                <copy todir="${cobertura.working.dir}/source">
                                                    <fileset dir="src/main/java">
                                                        <include name="**/*.java"/>
                                                    </fileset>
                                                </copy>
                                            </then>
                                        </if>
                                        <cobertura-report datafile="${cobertura.complete.ser.file}" format="${cobertura.format}" destdir="${cobertura.working.dir}/report">
                                            <fileset dir="${cobertura.working.dir}/source"/>
                                        </cobertura-report>
                                    </then>
                                </if>
                            </target>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>net.sourceforge.cobertura</groupId>
                        <artifactId>cobertura</artifactId>
                        <version>1.9.4.1</version>
                    </dependency>
                    <dependency>
                        <groupId>ant-contrib</groupId>
                        <artifactId>ant-contrib</artifactId>
                        <version>20020829</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>net.sourceforge.cobertura</groupId>
            <artifactId>cobertura</artifactId>
            <version>1.9.4.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</profile>

Qu'est-ce que ça fait:

1. @process-classes - Instrumentez les classes compilées du module.

2. @generate-test-sources - Fusionne le fichier .ser des modules précédents avec le fichier créé de ce module pour obtenir la couverture complète du code.

3. @test - Crée le rapport de couverture de code. Devrait être appelé dans le dernier module, mais étant donné que le dernier module peut changer, je l’appelle toujours et les rapports précédents seront écrasés. Si vous utilisez le rapport au format xml (pour Jenkins), il est rapide, donc cela n'a pas d'importance.

Selon MCOBERTURA-65 , le plugin maven cobertura ne sait toujours pas comment agréger les rapports de sous-modules dans un rapport consolidé. Des travaux ont été effectués pour mettre en œuvre une cible merge sur le plug-in maven cobertura (voir MCOBERTURA-33 ) mais ce code n’a pas encore été inclus dans le plug-in. Je n'ai pas testé le patch moi-même et je ne peux pas dire si ça vaut le coup d'essayer.

En conséquence, beaucoup de gens suggèrent en effet d'utiliser le maven plugin de tableau de bord mais Personnellement, je resterais loin de cela car ce n’était pas très satisfaisant à long terme et j’étais confronté à de nombreux problèmes (problèmes techniques, perte d’histoire, ...). Au lieu de cela, je recommande vivement Sonar . Consultez Nemo , une instance publique de la dernière version de Sonar, pour une démonstration en direct de cette version. outil. Voir par exemple le projet Commons Digester et le explorer la couverture de code .

Il existe quelques plugins qui agrègent les rapports Cobertura (et autres). Consultez le sonar et plugins XRadar . Il existe également le plug-in de tableau de bord , mais il est un peu maladroit.

FWIW Emma fait la couverture de ligne .

Je voudrais vraiment remercier Sven Oppermann d’avoir présenté sa solution de profil runCobertura. Cela a aidé Je résous la question de savoir comment obtenir des rapports de couverture globale pour des projets multi-modules alors que vous n'êtes peut-être pas capable d'utiliser Sonar.

J'ai créé un exemple qui montre comment créer des projets multi-modules produisant des rapports de couverture de code qui évaluent non seulement la couverture de test unitaire (dans tous les sous-modules), mais également la couverture des TESTS D'INTÉGRATION UP VOTRE APPLICATION COMME UNE .WAR IN JETTY. L'exemple est hébergé ici:

        http://dl.dropbox.com/u/9940067/code/multi-module-cobertura.zip 

La recette que je vous donne est plutôt réutilisable si vous copiez le profil runCobertura indiqué ci-dessous (basé sur celui fournir par Sven.)

Voici quelques notes qui vous aideront à utiliser ce profil:

  • le module de test d'intégration qui lance jetty (et définit les tests exécutés contre   la production .war) doit être nommé Web-test-pilote-pour-code-couverture, ou vous    doit modifier les instructions du bloc de configuration runCobertura.

  • vos rapports de couverture apparaissent chaque fois que vous définissez votre variable

  • vous DEVEZ inclure "clean" sur la ligne de commande lorsque vous exécutez votre construction pour la couverture de code. 'clean' supprimera les fichiers cobertura.ser précédents,   qui, si on le laisse traîner, peut causer des rapports très déroutants    généré (un signe que vous devez "nettoyer" est que les rapports montrent   Couverture à 100% pour tout, y compris les éléments dont vous n’avez jamais entendu parler.

      mvn -PrunCobertura clean install      # gives you the aggregate reports.
    
  • le module pilote de test de code pour le code-couverture définit un écouteur de contexte de servlet qui vide explicitement les métriques de cobertura sur le disque.   lorsque le serveur Web est arrêté. Soi-disant, le conteneur est censé le faire automatiquement, mais cela n’a pas fonctionné pour moi, alors   J'ai dû prendre l'appel explicite pour vider les métriques.

  • les tests d’intégration se font en groovy car j’ai basé cela sur des squelettes de projets maven qui utilisaient déjà groovy.   Désolé pour le fouillis ajouté, mais cela vous montre comment faire vos tests dans groovy (ce qui est de toute façon hautement recommandé.)

  • Notez que lorsque vous compilez avec le profil runCobertura, tous vos artefacts sont créés avec l'instrumentation cobertura, même votre   Fichier .war. Vous ne voulez JAMAIS laisser cela entrer dans la production bien sûr (pour une chose, cela fonctionnerait très lentement.) Je n'ai pas   pourtant trouvé un moyen alimentaire pour obtenir les artefacts de se renommer afin que le «cobertura-ness» est évident.

    <profiles>
    <profile>
        <id>runCobertura</id>
        <activation>
            <property>
                <name>runCobertura</name>
                <value>true</value>
            </property>
        </activation>
        <properties>
            <cobertura.format>html</cobertura.format>
            <working.dir>/tmp</working.dir>
            <cobertura.working.dir>${working.dir}/${project.version}/cobertura</cobertura.working.dir>
            <cobertura.complete.ser.file>${cobertura.working.dir}/complete.ser</cobertura.complete.ser.file>
    
            <!-- scope which determines whether or not cobertura is included in .war file: overriden here -->
            <cobertura.dependency.scope>compile</cobertura.dependency.scope>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>2.4.1</version>
                    <inherited>false</inherited>
                    <configuration>
                        <filesets>
                            <fileset>
                                <directory>.</directory>
                                <includes>
                                    <include>**/cobertura.ser</include>
                                </includes>
                            </fileset>
                            <fileset>
                                    <directory>${cobertura.working.dir}</directory>
                                </fileset>
                        </filesets>
                    </configuration>
                </plugin>
    
    
    
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <version>1.7</version>
                    <executions>
                        <execution>
                            <id>cobertura-Instrument</id>
                            <phase>process-classes</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <taskdef resource="tasks.properties"/>
                                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                    <echo message="::PROCESS CLASSES: ${artifactId}"/>
    
                                    <if>
                                      <equals arg1="${artifactId}" arg2="web-test-driver-for-code-coverage" />
                                        <then>
                                            <echo message="::SKIPPING PHASE for integration test"/>
                                        </then>
                                        <else>
                                            <if>
                                                <available file="${project.build.outputDirectory}"/>
                                                <then>
                                                    <echo message="::BEFORE INSTRUMENT"/>
                                                    <cobertura-instrument>
                                                        <fileset dir="${project.build.outputDirectory}">
                                                            <include name="**/*.class"/>
                                                        </fileset>
                                                    </cobertura-instrument>
                                                </then>
                                            </if>
                                        </else>
                                    </if>
    
    
                                </target>
                            </configuration>
                        </execution>
                        <execution>
                            <id>cobertura-createCombinedSerFile</id>
                            <phase>generate-test-sources</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <taskdef resource="tasks.properties"/>
                                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
                                    <echo message=":::generate-test-sources"/>
    
    
                                    <if>
                                      <equals arg1="${artifactId}" arg2="web-test-driver-for-code-coverage" />
                                        <then>
                                            <echo message="::SHORT CIRCUIT COMBINE PHASE for integration test"/>
                                            <echo  message="source - ${cobertura.complete.ser.file} dest - ${basedir}/cobertura.ser"/>
                                            <copy file="${cobertura.complete.ser.file}" tofile="${basedir}/cobertura.ser"/>
                                        </then>
                                        <else>
                                            <if>
                                                <available file="${basedir}/cobertura.ser"/>
                                                <then>
                                                    <echo message="::: Is available ${basedir}/cobertura.ser"/>
                                                </then>
                                            </if>
    
                                            <if>
                                                <available file="${cobertura.complete.ser.file}"/>
                                                <then>
                                                    <echo message="before merge1"/>
                                                    <cobertura-merge datafile="${basedir}/tmp.ser">
                                                        <fileset file="${cobertura.complete.ser.file}"/>
                                                        <fileset file="${basedir}/cobertura.ser"/>
                                                    </cobertura-merge>
                                                    <echo message="move temp.ser to ${basedir}/cobertura.ser"/>
                                                    <move file="${basedir}/tmp.ser" tofile="${basedir}/cobertura.ser"/>
                                                </then>
                                            </if>
                                        </else>
                                    </if>
                                </target>
                            </configuration>
                        </execution>
                        <execution>
                            <id>cobertura-copyResultSerFileAndSources</id>
                            <phase>verify</phase>
                            <goals>
                                <goal>run</goal>
                            </goals>
                            <configuration>
                                <target>
                                    <taskdef resource="tasks.properties"/>
                                    <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
    
                                    <echo message=":::copyResultSerFileAndSources -beforeIf"/>
                                    <if>
                                        <available file="${basedir}/cobertura.ser"/>
                                        <then>
                                            <echo message="move1"/>
                                            <move file="${basedir}/cobertura.ser" tofile="${cobertura.complete.ser.file}"/>
                                            <mkdir dir="${cobertura.working.dir}/source"/>
                                            <if>
                                                <available file="${basedir}/src/main/java"/>
                                                <then>
                                                    <copy todir="${cobertura.working.dir}/source">
                                                        <fileset dir="src/main/java">
                                                            <include name="**/*.java"/>
                                                        </fileset>
                                                    </copy>
                                                </then>
                                            </if>
                                            <echo message="runreport"/>
                                            <cobertura-report datafile="${cobertura.complete.ser.file}" format="${cobertura.format}" destdir="${cobertura.working.dir}/report">
                                                <fileset dir="${cobertura.working.dir}/source"/>
                                            </cobertura-report>
                                        </then>
                                    </if>
                                </target>
                            </configuration>
                        </execution>
                    </executions>
                    <dependencies>
                        <dependency>
                            <groupId>net.sourceforge.cobertura</groupId>
                            <artifactId>cobertura</artifactId>
                            <version>1.9.4.1</version>
                        </dependency>
                        <dependency>
                            <groupId>ant-contrib</groupId>
                            <artifactId>ant-contrib</artifactId>
                            <version>20020829</version>
                        </dependency>
                    </dependencies>
                </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>net.sourceforge.cobertura</groupId>
                <artifactId>cobertura</artifactId>
                <version>1.9.4.1</version>
            </dependency>
        </dependencies>
    </profile>
    </profiles>
    

Thomas Sundberg offre une solution intéressante dans laquelle l'instrumentation et le rapport de test sont effectués via ant, mais tous les tests et la gestion des dépendances via mvn.

Vérifiez ici: thomassundberg wordpress

Cela signifie que vous devez exécuter les commandes ci-dessous au niveau parent dans l'ordre suivant:

mvn clean compile
ant instrument
mvn test
ant report

L’intégration de ces étapes dans sonar est décrite par Martijn Stelinga.

test-coverage-in -projets multi-modules

Je pourrais implémenter quelque chose d'assez similaire à ce dont vous avez besoin grâce à cette réponse: Maven - ajout de la dépendance à la source d'artefact

Je viens d'ajouter <classifier>sources</classifier> et cobertura inclut également des classes de dépendances.

Cordialement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top