¿Cómo configurar el módulo múltiple Maven + Sonar + JaCoCo para proporcionar un informe de cobertura combinado?

128

He buscado en internet por este. Hay muchas respuestas a medias por ahí, que ver con propiedades de Maven como ${sonar.jacoco.reportPath}, o con org.jacoco:jacoco-maven-plugin:prepare-agentconfiguración .maven-surefire-plugin argLine-javaagent

De alguna manera, ninguna de estas respuestas, ya sea por sí mismas o en combinación, está produciendo lo que busco: un informe de cobertura que muestra una clase como cubierta si se usa en pruebas más arriba en la pila, como las entidades que se usan por DAO, a pesar de que no estaba completamente cubierto por las pruebas en su propio módulo.

¿Hay una configuración definitiva en alguna parte, para lograr esto, por favor?

Stewart
fuente

Respuestas:

164

Estaba en la misma situación que usted, las medias respuestas dispersas en Internet eran bastante molestas, ya que parecía que muchas personas tenían el mismo problema, pero nadie podía molestarse en explicar por completo cómo lo resolvieron.

Los documentos de Sonar se refieren a un proyecto de GitHub con ejemplos que son útiles. Lo que hice para resolver esto fue aplicar la lógica de las pruebas de integración a las pruebas unitarias regulares (aunque las pruebas unitarias adecuadas deberían ser específicas de submódulos, este no es siempre el caso).

En el padre pom.xml, agregue estas propiedades:

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

Esto hará que Sonar recoja informes de prueba de unidad para todos los submódulos en el mismo lugar (una carpeta de destino en el proyecto principal). También le dice a Sonar que reutilice los informes que se ejecutan manualmente en lugar de lanzarlos por su cuenta. Solo necesitamos hacer que jacoco-maven-plugin se ejecute para todos los submódulos colocando esto en el pom padre, dentro 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>

destFilecoloca el archivo de informe en el lugar donde Sonar lo buscará y appendlo adjuntará al archivo en lugar de sobrescribirlo. Esto combinará todos los informes de JaCoCo para todos los submódulos en el mismo archivo.

Sonar examinará ese archivo para cada submódulo, ya que eso es lo que le señalamos anteriormente, dándonos resultados de pruebas de unidades combinadas para archivos de módulos múltiples en Sonar.

mpontes
fuente
¡Maravilloso! Esto ha funcionado. ¡Finalmente! Creo que la magia que faltaba el encantamiento vital que me faltaba era <append> true </append>
Stewart
¡Funciona! Tuve que hacer un nuevo mvn packageantes de ejecutar mvn sonar:sonarpara obtener la nueva ruta del informe generado.
thomasa88
2
Según el ejemplo, la propiedad "sonar.jacoco.itReportPath" se debe utilizar para obtener resultados combinados en "cobertura de código general". Por favor actualice la respuesta.
Yves Martin
44
"sonar.dynamicAnalysis" también está en desuso: docs.sonarqube.org/display/SONAR/Release+4.3+Upgrade+Notes
Yves Martin
3
Enlace actualizado: docs.sonarqube.org/display/SONARQUBE53/…
Lonzak
23

Preguntas más frecuentes

Preguntas desde lo alto de mi cabeza desde entonces me volví loco con jacoco.

Mi servidor de aplicaciones (jBoss, Glassfish ...) ubicado en Iraq, Siria, lo que sea ... ¿Es posible obtener una cobertura de varios módulos al ejecutar pruebas de integración? Jenkins y Sonar también están en diferentes servidores.

Si. Debe usar el agente jacoco que se ejecuta en modo output=tcpserverjacoco ant lib. Básicamente dos jars. Esto te dará un 99% de éxito.

¿Cómo funciona el agente jacocó?

Anexas una cuerda

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

a su servidor de aplicaciones JAVA_OPTS y reinícielo. En esta cadena solo [your_path]hay que reemplazarla por la ruta a jacocoagent.jar, almacenada (¡almacénela!) En su VM donde se ejecuta el servidor de aplicaciones. Desde el momento en que inicie el servidor de aplicaciones, todas las aplicaciones que se implementen serán monitoreadas dinámicamente y su actividad (es decir, el uso del código) estará lista para que usted obtenga en formato jacocos .exec por solicitud tcl.

¿Podría restablecer el agente de jacoco para comenzar a recopilar datos de ejecución solo desde el momento en que comienza mi prueba?

Sí, para ese propósito necesita el script jacocoant.jar y ant build ubicado en su espacio de trabajo jenkins.

Entonces, ¿básicamente lo que necesito de http://www.eclemma.org/jacoco/ es jacocoant.jar ubicado en mi espacio de trabajo de jenkins y jacocoagent.jar ubicado en la máquina virtual de mi servidor de aplicaciones?

Así es.

No quiero usar hormiga, he oído que el complemento jacoco maven también puede hacer todas las cosas.

Eso no está bien, el complemento jacoco maven puede recopilar datos de pruebas unitarias y algunos datos de pruebas de integración (consulte Arquillian Jacoco ), pero si tiene, por ejemplo, las pruebas seguras como una compilación separada en jenkins y desea mostrar una cobertura de varios módulos, puedo No veo cómo el complemento Maven puede ayudarte.

¿Qué produce exactamente el agente jacocó?

Solo datos de cobertura en .execformato. Sonar entonces puede leerlo.

¿Necesita saber jacoco dónde están ubicadas mis clases de Java?

No, el sonar sí, pero no el jacoco. Cuando haces mvn sonar:sonarcamino a las clases entra en juego.

¿Y qué hay del guión de hormigas?

Tiene que presentarse en su espacio de trabajo jenkins. El guión de mi hormiga, lo llamé jacoco.xmlasí:

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

Dos parámetros obligatorios que debe pasar al invocar este script, -Dworkspace=$WORKSPACE úselo para señalar su espacio de trabajo jenkins y -Djacoco.host=yourappserver.comhost sinhttp://

Observe también que puse mi jacocoant.jaren $ {workspace} /tools/jacoco/jacocoant.jar

¿Qué debería hacer después?

¿Comenzaste tu servidor de aplicaciones con jacocoagent.jar?

¿Puso ant script y jacocoant.jar en su espacio de trabajo de jenkins?

En caso afirmativo, el último paso es configurar una compilación jenkins. Aquí está la estrategia:

  1. Invoque el objetivo ant jacocoResetpara restablecer todos los datos recopilados previamente.
  2. Ejecute sus pruebas
  3. Invocar hormiga objetivo jacocoReportpara obtener informe

Si todo está bien, verá it-jacoco.execen su espacio de trabajo de compilación.

Mire la captura de pantalla, también la antinstalé en mi espacio de trabajo en $WORKSPACE/tools/antdir, pero puede usar una que esté instalada en su jenkins.

ingrese la descripción de la imagen aquí

¿Cómo impulsar este informe en sonar?

Maven sonar:sonarhará el trabajo (no olvide configurarlo), apúntelo a pom.xml principal para que se ejecute en todos los módulos. Use el sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.execparámetro para indicarle al sonar dónde se encuentra su informe de prueba de integración. Cada vez que analizará nuevas clases de módulos, buscará información sobre la cobertura en it-jacoco.exec.

Ya tengo jacoco.exec en mi directorio `target`,` mvn sonar: sonar` lo ignora / elimina

De manera predeterminada mvn sonar:sonar, cleanelimina y elimina su directorio de destino, use sonar.dynamicAnalysis=reuseReportspara evitarlo.

ZuzEL
fuente
20

NUEVO CAMINO DESDE LA VERSIÓN 0.7.7

Desde la Versión 0.7.7 hay una nueva forma de crear un informe agregado:

Se crea un proyecto de 'informe' separado que recopila todos los informes necesarios (cualquier objetivo en el proyecto agregador se ejecuta antes de sus módulos, por lo tanto, no se puede usar).

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

El pom raíz se ve así (no olvide agregar el nuevo módulo de informe en los módulos):

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

No es necesario cambiar los poms de cada submódulo. El pom del módulo de informe se ve así:

<!-- 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 ejemplo completo se puede encontrar aquí .

Lonzak
fuente
3
Esto funciona. El informe agregado muestra la cobertura del código acumulativo para todos los módulos. ¿Alguna vez intentó ver este informe acumulativo en Sonar? Utilicé sonar-qube para leer jacoco.exec para informes individuales, pero con este agregado de informe, no veo un jacoco.exec agregado en el módulo de informe.
Swetha V
@SwethaV ¿Algún éxito en esto? Estamos en la misma posición y necesitamos encontrar una manera de generar el ejecutivo agregado :)
Vinky
Utilizamos sonar qube versión 6.X que tiene su propia página de cobertura de prueba, por lo que no necesito jacoco allí. Para una versión anterior, instalamos el complemento de cobertura que también proporcionaba esta funcionalidad ...
Lonzak
11

Publicaré mi solución, ya que es sutilmente diferente de las demás y también me tomó un día sólido para hacerlo bien, con la ayuda de las respuestas existentes.

Para un proyecto Maven de varios módulos:

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

Donde el WARproyecto es la aplicación web principal, LIB1 y 2 son módulos adicionales de los que WARdepende y TESTdonde viven las pruebas de integración. TESTgira una instancia de Tomcat incrustada (no a través del complemento de Tomcat) y ejecuta el WARproyecto y los prueba a través de un conjunto de pruebas JUnit. Los proyectos WARy LIBambos tienen sus propias pruebas unitarias.

El resultado de todo esto es que la cobertura de integración y prueba unitaria se separa y puede distinguirse en 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 y TEST pom.xmlheredará la ejecución de los complementos de 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>

También encontré que la publicación del blog de Petri Kainulainens 'Creación de informes de cobertura de código para pruebas de unidad e integración con el complemento JaCoCo Maven' es valiosa para el lado de configuración de JaCoCo.

Markdsievers
fuente
Necesito actualizar esta publicación en algún momento, ya que en realidad es un poco subóptima. agent-for-itsolo es necesario cuando se ejecutan las pruebas en el TESTmódulo, pero la configuración actual lo tiene ejecutándose para cualquier otro módulo, donde no tiene ningún valor. La mejora sería haber agent-for-utcorrido en todos los demás módulos y agent-for-itsolo en TEST.
markdsievers
7

Hay una manera de lograr esto. La magia es crear un archivo jacoco.exec combinado. Y con Maven 3.3.1 hay una manera fácil de obtener esto. Aquí mi perfil:

<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 agrega este perfil a su padre pom y llama mvn clean install sonar:sonar -DrunSonar, obtendrá la cobertura completa.

La magia aquí es maven.multiModuleProjectDirectory. Esta carpeta es siempre la carpeta donde comenzó su compilación Maven.

Sven Oppermann
fuente
Esto funcionó para mí, después de pasar por muchas otras soluciones.
Jimson Kannanthara James
El único problema fue que tuve que ejecutar la sonda con el comando mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.0.905:sonar -DrunSonardebido a un A required class was missing while executing org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar: org/sonar/batch/bootstrapper/IssueListenererror.
Jimson Kannanthara James
1
No uses esta magia. La propiedad dada es un detalle de implementación y no se debe confiar en ella. - El equipo de desarrolladores de Maven
Michael-O
6

La configuración que uso en mi pom de nivel primario donde tengo fases separadas de prueba de unidad e integración.

Configuro las siguientes propiedades en las propiedades POM principales

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

Coloco las definiciones de complementos bajo administración de complementos.

Tenga en cuenta que defino una propiedad para los argumentos surefire (surefireArgLine) y failsafe (failsafeArgLine) para permitir que jacoco configure el javaagent para que se ejecute con cada prueba.

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

Y en la sección de construcción

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

Y en la sección de informes

    <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
fuente
1
Veo que tienes la <append>true</append>configuración en las prepare-agentsecciones ...
Stewart
Énfasis. Lee mi comentario a otra respuesta. Era el ingrediente vital que faltaba para mí, no encontrado en otros documentos.
Stewart
¿tienes un enlace github para esto? Quiero hacer exactamente configuraciones similares
Rohit Kasat
@Rhit: no, no lo hago, al menos no en un repositorio público.
sweetfa
Esto funciona muy bien con Sonar Qube Versión 6.5 (compilación 27846) ...: D La cobertura del código se mostrará correctamente.
udoline
4

Encontré otra solución para las nuevas versiones de Sonar donde el formato de informe binario de JaCoCo (* .exec) fue obsoleto y el formato preferido es XML (SonarJava 5.12 y superior). La solución es muy simple y similar a la solución anterior con informes * .exec en el directorio principal de este tema: https://stackoverflow.com/a/15535970/4448263 .

Asumiendo que nuestra estructura de proyecto es:

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

Necesita la siguiente configuración del complemento de compilación maven en el pom del proyecto agregado:

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

Luego construya el proyecto con maven:

mvn clean verify

Y para Sonar, debe establecer la propiedad en la GUI de administración:

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

o usando la línea de comando:

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

Descripción

Esto crea informes binarios para cada módulo en directorios por defecto: target/jacoco.exec. A continuación, crea informes XML para cada módulo en directorios por defecto: target/site/jacoco/jacoco.xml. Luego crea un informe agregado para cada módulo en el directorio personalizado ${project.basedir}/../target/site/jacoco-aggregate/que es relativo al directorio principal para cada módulo. Para el módulo A y el módulo B, esta será una ruta común moduleC/target/site/jacoco-aggregate/.

Como el módulo B depende del módulo A, el módulo B se construirá en último lugar y su informe se utilizará como un informe de cobertura agregado en Sonar para los módulos A y B.

Además del informe agregado, necesitamos un informe de módulo normal ya que los informes agregados de JaCoCo contienen datos de cobertura solo para dependencias.

Juntos, estos dos tipos de informes proporcionan datos de cobertura completa para Sonar.

Hay una pequeña restricción: debe poder escribir un informe en el directorio principal del proyecto (debe tener permiso). O puede establecer la propiedad jacoco.skip=trueen pom.xml (moduleC) del proyecto raíz y jacoco.skip=falseen módulos con clases y pruebas (moduleA y moduleB).

keddok
fuente
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>             
Miguel
fuente
2

Como Sonars sonar.jacoco.reportPath, sonar.jacoco.itReportPathy sonar.jacoco.reportPathstodos han quedado en desuso , deberías usarlos sonar.coverage.jacoco.xmlReportPathsahora. Esto también tiene algún impacto si desea configurar un proyecto maven de módulos múltiples con Sonar y Jacoco.

Como señaló @Lonzak , desde Sonar 0.7.7, puede usar el objetivo de agregación de informes de Sonars. Simplemente ponga en su padre pom la siguiente dependencia:

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

Como las versiones actuales de jacoco-maven-plugin son compatibles con los informes xml, esto creará para cada módulo en su propia carpeta de destino una carpeta de sitio / jacoco-agregado que contiene un jacoco.xmlarchivo.

Para permitir que Sonar combine todos los módulos, use el siguiente comando:

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

Para mantener mi respuesta breve y precisa, no mencioné las dependencias maven-surefire-pluginy maven-failsafe-plugin. Simplemente puede agregarlos sin ninguna otra configuración:

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

Puede llamar a una tarea de hormiga llamada fusionar en maven, para poner todos los archivos de cobertura (* .exec) juntos en el mismo archivo.

Si ejecuta pruebas unitarias, utilice el paquete de preparación de fase , si ejecuta la prueba de integración, utilice la prueba de integración posterior .

Este sitio tiene un ejemplo de cómo llamar a jacoco ant task en maven project

Puede usar este archivo combinado en la sonda.

Andre Piantino
fuente
0

para tener pruebas unitarias Y pruebas de integración, puede usar maven-surefire-plugin y maven-failsafe-plugin con restricciones / inclusiones excluidas. Estaba jugando con CDI mientras me ponía en contacto con sonar / jacoco, así que terminé en este proyecto:

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

Quizás te ayude un poco. en mi pom.xml utilizo "-javaagent" implícito al configurar la opción argLine en la sección de configuración de los plugins de prueba especificados. El uso explícito de ANT en proyectos MAVEN es algo que no probaría, para mí es mucho mezclar dos mundos.

Solo tengo un proyecto Maven de módulo único, pero tal vez te ayude a ajustar el tuyo para que funcione.

nota: tal vez no todos los complementos de maven estén actualizados, tal vez algunos problemas se solucionen en versiones posteriores

FibreFoX
fuente
Gracias por esto; Echaré un vistazo y te diré cómo funciona. Aunque podría no ser esta semana :)
Stewart
0

Esta muestra me funciona muy bien:

<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
fuente
Proporcione alguna explicación a su respuesta
Mishsx
@mishsx Un buen artículo para explicación: natritmeyer.com/howto/…
SerhatTopkaya