Come configurare Maven + Sonar + JaCoCo multi-modulo per fornire un report di copertura unito?


128

Ho cercato su e giù per Internet per questo. C'è un sacco di mezze risposte là fuori, da fare con le proprietà Maven, come ${sonar.jacoco.reportPath}, o org.jacoco:jacoco-maven-plugin:prepare-agento l'impostazione maven-surefire-plugin argLinecon -javaagent.

Alcuni come, nessuna di queste risposte, da soli o in combinazione, stanno producendo ciò che sto cercando: un rapporto di copertura che mostra una classe come coperta se viene utilizzata nei test più in alto nello stack, come le entità utilizzate dai DAO, anche se non è stato completamente coperto dai test nel proprio modulo.

C'è una configurazione definitiva da qualche parte, per raggiungere questo obiettivo, per favore?

Risposte:


164

Ero nella tua stessa situazione, le mezze risposte sparse su Internet erano piuttosto fastidiose, dal momento che sembrava che molte persone avessero lo stesso problema, ma nessuno poteva essere disturbato a spiegare appieno come l'hanno risolto.

I documenti Sonar si riferiscono a un progetto GitHub con esempi che sono utili. Quello che ho fatto per risolvere questo problema è stato applicare la logica dei test di integrazione ai test unitari regolari (sebbene i test unitari corretti debbano essere specifici del sottomodulo, non è sempre così).

Nel pom.xml padre, aggiungi queste proprietà:

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

Questo farà sì che Sonar raccolga i rapporti di test delle unità per tutti i sottomoduli nello stesso posto (una cartella di destinazione nel progetto principale). Indica inoltre a Sonar di riutilizzare i report eseguiti manualmente anziché eseguirne il rollup. Dobbiamo solo far funzionare jacoco-maven-plugin per tutti i sottomoduli posizionandolo nel pom principale, all'interno di 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>

destFileposiziona il file di report nel punto in cui Sonar lo cercherà e lo appendfarà accodare al file anziché sovrascriverlo. Questo combinerà tutti i report JaCoCo per tutti i sottomoduli nello stesso file.

Il sonar esaminerà quel file per ciascun sottomodulo, poiché è quello che abbiamo indicato sopra, dandoci risultati di test unitari combinati per i file multi modulo in Sonar.


Meravigliosa! Questo ha funzionato Finalmente! Penso che l'incantesimo vitale mancante di magia che mi mancava fosse <append> vero </append>
Stewart

Funziona! Ho dovuto fare un nuovo mvn packageprima di correre mvn sonar:sonarper generare il nuovo percorso del rapporto.
thomasa88,

2
Secondo l'esempio, la proprietà "sonar.jacoco.itReportPath" dovrebbe essere utilizzata per ottenere risultati uniti nella "copertura del codice globale". Si prega di aggiornare la risposta.
Yves Martin,

4
Anche "sonar.dynamicAnalysis" è deprecato: docs.sonarqube.org/display/SONAR/Release+4.3+Upgrade+Notes
Yves Martin


23

FAQ

Domande dalla parte superiore della mia testa da quel momento sono impazzito con Jacoco.

Il mio server delle applicazioni (jBoss, Glassfish ..) si trova in Iraq, in Siria, qualunque cosa ... È possibile ottenere una copertura multi-modulo durante l'esecuzione di test di integrazione su di esso? Anche Jenkins e Sonar si trovano su server diversi.

Sì. Devi usare l'agente jacoco che gira in modalità output=tcpserver, jacoco ant lib. Fondamentalmente duejar secondi. Questo ti darà il 99% di successo.

Come funziona l'agente Jacoco?

Aggiungi una stringa

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

sul server delle applicazioni JAVA_OPTS e riavviarlo. Solo in questa stringa[your_path] deve essere sostituito solo con il percorso di jacocoagent.jar, archiviato (memorizzalo!) Nella VM in cui è in esecuzione il server delle app. Da quel momento in cui avvii il server delle app, tutte le applicazioni distribuite verranno monitorate in modo dinamico e la loro attività (che significa utilizzo del codice) sarà pronta per ottenere in formato jacocos .exec su richiesta tcl.

Posso ripristinare l'agente jacoco per iniziare a raccogliere i dati di esecuzione solo dal momento in cui è iniziato il mio test?

Sì, a tale scopo hai bisogno di jacocoant.jar e dello script di build ant situati nell'area di lavoro di jenkins.

Quindi, in pratica, ciò di cui ho bisogno da http://www.eclemma.org/jacoco/ è che jacocoant.jar si trova nell'area di lavoro di jenkins e jacocoagent.jar si trova sulla VM del mio server di app?

Giusto.

Non voglio usare la formica, ho sentito che anche il plugin jacoco maven può fare tutto.

Non è vero, il plug-in Jacoco Maven può raccogliere i dati dei test unitari e alcuni dati dei test di integrazione (vedi Arquillian Jacoco ), ma se ad esempio hai dei test sicuri come build separato in jenkins e vuoi mostrare la copertura multi-modulo, posso vedrai come il plugin Maven può aiutarti.

Cosa produce esattamente l'agente Jacoco?

Solo i dati di copertura in .exec formato. Il sonar può quindi leggerlo.

Jacoco deve sapere dove si trovano le mie lezioni di java?

No, sonar, ma non Jacoco. Quando fai il mvn sonar:sonarpercorso per le lezioni entra in gioco.

E la sceneggiatura della formica?

Deve essere presentato nell'area di lavoro di jenkins. Il mio script di formica, l'ho chiamato jacoco.xmlsembra così:

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

Due parametri obbligatori che dovresti passare quando invochi questo script lo -Dworkspace=$WORKSPACE usano per indicare lo spazio di lavoro di jenkins e l' -Djacoco.host=yourappserver.comhost senzahttp://

Nota anche che ho messo my jacocoant.jarin $ {workspace} /tools/jacoco/jacocoant.jar

Cosa dovrei fare dopo?

Hai avviato l'app server con jacocoagent.jar?

Hai inserito script di formiche e jacocoant.jar nell'area di lavoro di jenkins?

Se sì, l'ultimo passaggio è configurare una build jenkins. Ecco la strategia:

  1. Richiama il bersaglio formica jacocoResetper ripristinare tutti i dati precedentemente raccolti.
  2. Esegui i tuoi test
  3. Richiama il bersaglio di formica jacocoReportper ottenere il rapporto

Se tutto va bene, vedrai it-jacoco.exec nel tuo spazio di lavoro di compilazione.

Guarda lo screenshot, ho anche antinstallato nel mio spazio di lavoro in $WORKSPACE/tools/antdir, ma puoi usarne uno installato nei tuoi jenkins.

inserisci qui la descrizione dell'immagine

Come inviare questo rapporto nel sonar?

Maven sonar:sonarfarà il lavoro (non dimenticare di configurarlo), lo punta su pom.xml principale in modo che esegua tutti i moduli. Utilizzare il sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.execparametro per indicare al sonar dove si trova il report del test di integrazione. Ogni volta che analizzerà nuove classi di moduli, cercherà informazioni sulla copertura in it-jacoco.exec.

Ho già jacoco.exec nella mia directory `target`,` sonar mvn: sonar` lo ignora / rimuove

Per impostazione predefinita mvn sonar:sonar, cleanelimina la directory di destinazione, utilizzare sonar.dynamicAnalysis=reuseReportsper evitarlo.


20

NUOVO MODO DALLA VERSIONE 0.7.7

Dalla versione 0.7.7 esiste un nuovo modo per creare un report aggregato:

Si crea un progetto 'report' separato che raccoglie tutti i report necessari (qualsiasi obiettivo nel progetto aggregatore viene eseguito prima dei suoi moduli, quindi non può essere utilizzato).

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

Il root pom è simile al seguente (non dimenticare di aggiungere il nuovo modulo di report sotto i moduli):

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

Non è necessario cambiare i pom di ciascun sottomodulo. Il pom del modulo di report è simile al seguente:

<!-- 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 esempio completo può essere trovato qui .


3
Questo funziona Il rapporto aggregato mostra la copertura cumulativa del codice per tutti i moduli. Hai mai provato a visualizzare questo rapporto cumulativo nel sonar? Ho usato sonar-qube per leggere jacoco.exec per i singoli report, ma con questo report aggregato, non vedo un jacoco.exec aggregato nel modulo del report.
Swetha V

@SwethaV Qualche successo in questo? Siamo nella stessa posizione e dobbiamo trovare un modo per generare il exec aggregato :)
Vinky

Usiamo sonar qube versione 6.X che ha una propria pagina di copertura del test, quindi non ho bisogno di Jacoco. Per una versione precedente abbiamo installato il plugin cobertura che forniva anche questa funzionalità ...
Lonzak,

11

Pubblicherò la mia soluzione perché è leggermente diversa dalle altre e mi ha anche preso una buona giornata per ottenere il giusto, con l'assistenza delle risposte esistenti.

Per un progetto Maven multi-modulo:

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

Laddove il WARprogetto è l'app Web principale, LIB1 e 2 sono moduli aggiuntivi da cui WARdipende ed TESTè dove vivono i test di integrazione. TESTesegue il rollup di un'istanza Tomcat incorporata (non tramite plug-in Tomcat) ed esegue il WARprogetto e li verifica tramite una serie di test JUnit. Il WAReLIB progetti hanno entrambi i propri test unitari.

Il risultato di tutto ciò è l'integrazione e la copertura dei test unitari separati e che possono essere distinti in 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 E TEST pom.xmlerediterà il il plugin esecuzione 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>

Ho anche scoperto che il post sul blog di Petri Kainulainens "Creazione di rapporti sulla copertura del codice per test di unità e integrazione con il plug-in JaCoCo Maven" è prezioso per il lato di installazione di JaCoCo.


Ho bisogno di aggiornare questo post ad un certo punto in quanto è in realtà un po 'non ottimale. agent-for-itè necessario solo quando si eseguono i test nel TESTmodulo ma la configurazione corrente lo ha in esecuzione per ogni altro modulo, dove non ha valore. Il miglioramento dovrebbe essere agent-for-uteseguito in tutti gli altri moduli e agent-for-itsolo in esecuzione TEST.
markdsievers,

7

C'è un modo per raggiungere questo obiettivo. La magia è creare un file jacoco.exec combinato. E con Maven 3.3.1 c'è un modo semplice per ottenere questo. Ecco il mio profilo:

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

Se aggiungi questo profilo al tuo genitore e chiami mvn clean install sonar:sonar -DrunSonar , otterrai la copertura completa.

La magia qui è maven.multiModuleProjectDirectory. Questa cartella è sempre la cartella in cui è stata avviata la creazione di Maven.


Questo ha funzionato per me, dopo aver esaminato numerose altre soluzioni.
Jimson Kannanthara James,

L'unico problema era che dovevo eseguire il sonar con comando, a mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.0.905:sonar -DrunSonarcausa di un A required class was missing while executing org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar: org/sonar/batch/bootstrapper/IssueListenererrore.
Jimson Kannanthara James,

1
Non usare questa magia. La proprietà fornita è un dettaglio di implementazione e non deve essere considerata attendibile. - Il team di sviluppatori Maven
Michael-O,

6

La configurazione che uso nel mio pom di livello genitore in cui ho fasi di test unità e integrazione separate.

Configuro le seguenti proprietà nelle proprietà POM principali

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

Metto le definizioni dei plugin sotto la gestione dei plugin.

Si noti che definisco una proprietà per gli argomenti surefire (surefireArgLine) e fail-safe (failafeArgLine) per consentire a jacoco di configurare javaagent per l'esecuzione con ogni test.

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

E nella sezione build

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

E nella sezione di segnalazione

    <reporting>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-report-plugin</artifactId>
            <version>${maven.surefire.report.plugin}</version>
            <configuration>
                <showSuccess>false</showSuccess>
                <alwaysGenerateFailsafeReport>true</alwaysGenerateFailsafeReport>
                <alwaysGenerateSurefireReport>true</alwaysGenerateSurefireReport>
                <aggregate>true</aggregate>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco.plugin.version}</version>
            <configuration>
                <excludes>
                    <exclude>**/*.mar</exclude>
                    <exclude>${jacoco.excludePattern}</exclude>
                </excludes>
            </configuration>
        </plugin>
     </plugins>
  </reporting>

1
Vedo che hai la <append>true</append>configurazione sotto le prepare-agentsezioni ...
Stewart,

L'enfasi. Leggi il mio commento ad un'altra risposta. Era l'ingrediente vitale mancante per me, non trovato in altri documenti.
Stewart,

hai un link github per questo? Voglio fare
configurazioni

@Rhit - no non lo faccio, almeno non in un repository pubblico.
Sweetfa,

Funziona molto bene con Sonar Qube Versione 6.5 (build 27846) ...: D La copertura del codice verrà visualizzata correttamente.
udoline,

4

Ho trovato un'altra soluzione per le nuove versioni di Sonar in cui il formato di report binario di JaCoCo (* .exec) era obsoleto e il formato preferito è XML (SonarJava 5.12 e versioni successive). La soluzione è molto semplice e simile alla precedente con report * .exec nella directory principale da questo argomento: https://stackoverflow.com/a/15535970/4448263 .

Supponendo che la struttura del nostro progetto sia:

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

È necessario seguire la configurazione del plug-in di maven build nel pom del progetto aggregato:

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

Quindi crea un progetto con Maven:

mvn clean verify

E per Sonar è necessario impostare la proprietà nella GUI di amministrazione:

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

o usando la riga di comando:

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

Descrizione

Questo crea rapporti binari per ciascun modulo in directory di default: target/jacoco.exec. Poi crea report XML per ciascun modulo in directory di default: target/site/jacoco/jacoco.xml. Quindi crea un report aggregato per ciascun modulo nella directory personalizzata ${project.basedir}/../target/site/jacoco-aggregate/relativo alla directory principale per ciascun modulo. Per moduleA e moduleB questo sarà il percorso comunemoduleC/target/site/jacoco-aggregate/ .

Poiché il modulo B dipende dal modulo A, il modulo B verrà creato per ultimo e il suo rapporto verrà utilizzato come rapporto di copertura aggregato nel sonar per entrambi i moduli A e B.

Oltre al report aggregato, abbiamo bisogno di un normale report del modulo poiché i report aggregati JaCoCo contengono dati di copertura solo per le dipendenze.

Insieme, questi due tipi di rapporti forniscono dati completi sulla copertura del sonar.

C'è una piccola restrizione: dovresti essere in grado di scrivere un rapporto nella directory principale del progetto (dovrebbe avere l'autorizzazione). Oppure puoi impostare la proprietà jacoco.skip=truenel pom.xml del progetto di root (moduleC) e jacoco.skip=falsenei moduli con classi e test (moduleA e moduleB).


2
    <sonar.language>java</sonar.language>
    <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
    <sonar.jacoco.reportPath>${user.dir}/target/jacoco.exec</sonar.jacoco.reportPath>
    <sonar.jacoco.itReportPath>${user.dir}/target/jacoco-it.exec</sonar.jacoco.itReportPath>
    <sonar.exclusions>
        file:**/target/generated-sources/**,
        file:**/target/generated-test-sources/**,
        file:**/target/test-classes/**,
        file:**/model/*.java,
        file:**/*Config.java,
        file:**/*App.java
    </sonar.exclusions>

            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.7.9</version>
                <executions>
                    <execution>
                        <id>default-prepare-agent</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <destFile>${sonar.jacoco.reportPath}</destFile>
                            <append>true</append>
                            <propertyName>surefire.argLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>default-prepare-agent-integration</id>
                        <goals>
                            <goal>prepare-agent-integration</goal>
                        </goals>
                        <configuration>
                            <destFile>${sonar.jacoco.itReportPath}</destFile>
                            <append>true</append>
                            <propertyName>failsafe.argLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>default-report</id>
                        <goals>
                            <goal>report</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>default-report-integration</id>
                        <goals>
                            <goal>report-integration</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>             

2

Come Sonar sonar.jacoco.reportPath, sonar.jacoco.itReportPathe sonar.jacoco.reportPathssono stati tutti deprecati , dovresti usarli sonar.coverage.jacoco.xmlReportPathsora. Ciò ha anche un certo impatto se si desidera configurare un progetto maven multi modulo con Sonar e Jacoco.

Come sottolineato da @Lonzak , dal Sonar 0.7.7, è possibile utilizzare l'obiettivo di aggregazione del rapporto Sonar. Inserisci nel tuo genitore la seguente dipendenza:

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

Poiché le versioni correnti del plug-in jacoco-maven sono compatibili con i report xml, questo creerà per ogni modulo nella propria cartella di destinazione una cartella site / jacoco-aggregate contenente un jacoco.xmlfile.

Per consentire a Sonar di combinare tutti i moduli, utilizzare il comando seguente:

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

Per mantenere la mia risposta breve e preciso, non ho menzionato l' maven-surefire-plugine maven-failsafe-plugindipendenze. Puoi semplicemente aggiungerli senza altre configurazioni:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.22.2</version>
    <executions>
        <execution>
        <id>integration-test</id>
            <goals>
                <goal>integration-test</goal>
            </goals>
        </execution>
    </executions>
</plugin>

1

Puoi chiamare un'attività di formica chiamata unisci on maven, per tutti i file di copertura (* .exec) nello stesso file.

Se si eseguono test di unità, utilizzare il pacchetto preparazione fase , se si esegue il test di integrazione, utilizzare il test post-integrazione .

Questo sito ha un esempio di come chiamare l'attività formica jacoco nel progetto maven

È possibile utilizzare questo file unito sul sonar.


0

per avere unit test e test di integrazione è possibile utilizzare maven-surefire-plugin e maven-failafe-plugin con include / esclusi limitati. Stavo giocando con il CDI mentre mi mettevo in contatto con il sonar / jacoco, quindi sono finito in questo progetto:

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

Forse ti aiuta un po '. nel mio pom.xml uso "-javaagent" implicito impostando l'opzione argLine nella sezione di configurazione dei plugin di test specificati. L'uso esplicito di ANT nei progetti MAVEN è qualcosa che non vorrei provare, per me è mescolare molto due mondi.

Ho solo un progetto maven a modulo singolo, ma forse ti aiuta ad adattare il tuo al lavoro.

nota: forse non tutti i plugin di maven sono aggiornati2, forse alcuni problemi sono stati risolti nelle versioni successive


Grazie per questo; Dò un'occhiata e ti faccio sapere come funziona. Potrebbe non essere questa settimana però :)
Stewart,

0

Questo esempio funziona molto bene per me:

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

Fornisci una spiegazione alla tua risposta
mishsx,

@mishsx Un bell'articolo per spiegazioni: natritmeyer.com/howto/…
SerhatTopkaya
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.