Como configurar o Maven + Sonar + JaCoCo de vários módulos para fornecer um relatório de cobertura mesclado?

128

Eu procurei acima e abaixo na internet para este. Há muita meias-respostas lá fora, para fazer com propriedades Maven como ${sonar.jacoco.reportPath}, ou org.jacoco:jacoco-maven-plugin:prepare-agentou configuração maven-surefire-plugin argLinecom -javaagent.

De alguma forma, nenhuma dessas respostas, por si só ou em combinação, está produzindo o que eu estou procurando: Um relatório de cobertura que mostra uma classe como coberta se for usada em testes mais altos da pilha, como entidades sendo usadas por DAOs, mesmo que não tenha sido totalmente coberto por testes em seu próprio módulo.

Existe uma configuração definitiva em algum lugar, para conseguir isso, por favor?

Stewart
fonte

Respostas:

164

Eu estava na mesma situação que você, as meias respostas espalhadas por toda a Internet eram bastante irritantes, pois parecia que muitas pessoas tinham o mesmo problema, mas ninguém podia se dar ao trabalho de explicar completamente como o resolveram.

Os documentos do Sonar se referem a um projeto do GitHub com exemplos úteis. O que fiz para resolver isso foi aplicar a lógica dos testes de integração aos testes de unidade regulares (embora os testes de unidade adequados devam ser específicos ao submódulo, esse nem sempre é o caso).

No pai pom.xml, adicione estas propriedades:

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

Isso fará com que o Sonar obtenha relatórios de teste de unidade para todos os submódulos no mesmo local (uma pasta de destino no projeto pai). Também diz ao Sonar para reutilizar os relatórios executados manualmente, em vez de rodar por conta própria. Nós só precisamos executar o jacoco-maven-plugin para todos os submódulos, colocando-o no pom pai, 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 o arquivo de relatório no local em que o Sonar o procurará e appendo anexará ao arquivo em vez de substituí-lo. Isso combinará todos os relatórios da JaCoCo para todos os submódulos no mesmo arquivo.

O Sonar examinará esse arquivo para cada submódulo, já que foi o que indicamos acima, fornecendo resultados combinados de testes de unidade para arquivos com vários módulos no Sonar.

mpontes
fonte
Maravilhoso! Isso deu certo. Finalmente! Eu acho que a magia faltando encantamento vital que eu estava faltando era <append> true </ Anexar>
Stewart
Funciona! Eu tive que fazer um novo mvn packageantes de executar mvn sonar:sonarpara obter o novo caminho do relatório gerado.
thomasa88
2
De acordo com o exemplo, a propriedade "sonar.jacoco.itReportPath" deve ser usada para obter resultados mesclados em "cobertura geral de código". Atualize a resposta.
Yves Martin
4
"sonar.dynamicAnalysis" também está obsoleta: docs.sonarqube.org/display/SONAR/Release+4.3+Upgrade+Notes
Yves Martin
3
Link atualizado: docs.sonarqube.org/display/SONARQUBE53/…
Lonzak
23

Perguntas frequentes

Perguntas do alto da minha cabeça desde aquela época eu enlouqueci com o jacoco.

Meu servidor de aplicativos (jBoss, Glassfish ..) localizado no Iraque, na Síria, seja o que for. É possível obter cobertura de vários módulos ao executar testes de integração nele? Jenkins e Sonar também estão em servidores diferentes.

Sim. Você precisa usar o agente jacoco que roda no modo output=tcpserverjacoco ant lib. Basicamente doisjar s. Isso lhe dará 99% de sucesso.

Como o agente jacoco funciona?

Você anexa uma string

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

para o servidor de aplicativos JAVA_OPTS e reinicie-o. Nesta cadeia, apenas [your_path]deve ser substituído pelo caminho para jacocoagent.jar, armazenado (armazene-o!) Na sua VM onde o servidor de aplicativos é executado. Desde o momento em que você inicia o servidor de aplicativos, todos os aplicativos implantados serão monitorados dinamicamente e suas atividades (significando uso de código) estarão prontas para você entrar no formato jacocos .exec por solicitação tcl.

Posso redefinir o agente jacoco para começar a coletar dados de execução apenas desde o início do teste?

Sim, para esse propósito, você precisa do script jacocoant.jar e ant build, localizado no seu espaço de trabalho jenkins.

Então, basicamente, o que eu preciso de http://www.eclemma.org/jacoco/ é o jacocoant.jar localizado no meu espaço de trabalho jenkins e o jacocoagent.jar localizado na minha VM do servidor de aplicativos?

Está certo.

Eu não quero usar ant, ouvi dizer que o plugin jacoco maven também pode fazer todas as coisas.

Isso não está certo, o plug-in jacoco maven pode coletar dados de teste de unidade e alguns dados de testes de integração (consulte Arquillian Jacoco ), mas se você tiver, por exemplo, testes seguros como uma compilação separada no jenkins e quiser mostrar a cobertura de vários módulos, eu posso veja como o maven plugin pode ajudá-lo.

O que exatamente o agente jacoco produz?

Somente dados de cobertura em .execformato. O sonar pode então lê-lo.

O jacoco precisa saber onde estão minhas classes java?

Não, sonar faz, mas não jacoco. Quando você fazmvn sonar:sonar caminho para as aulas, entra em jogo.

E o roteiro das formigas?

Ele deve ser apresentado no seu espaço de trabalho do jenkins. Meu script formiga, eu chamei jacoco.xmlassim:

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

Dois parâmetros obrigatórios que você deve passar ao chamar esse script, -Dworkspace=$WORKSPACE use-o para apontar para o espaço de trabalho do jenkins e para o -Djacoco.host=yourappserver.comhost semhttp://

Observe também que coloquei meu jacocoant.jarem $ {workspace} /tools/jacoco/jacocoant.jar

O que eu devo fazer a seguir?

Você iniciou seu servidor de aplicativos com jacocoagent.jar?

Você colocou script ant e jacocoant.jar no seu espaço de trabalho de jenkins?

Se sim, a última etapa é configurar uma compilação do jenkins. Aqui está a estratégia:

  1. Invoque o alvo formiga jacocoResetpara redefinir todos os dados coletados anteriormente.
  2. Execute seus testes
  3. Invoque o alvo formiga jacocoReportpara obter o relatório

Se tudo estiver certo, você verá it-jacoco.exec no seu espaço de trabalho de construção.

Olhe para a captura de tela, eu também antinstalei no meu espaço de trabalho no $WORKSPACE/tools/antdiretório, mas você pode usar um que esteja instalado no seu jenkins.

insira a descrição da imagem aqui

Como empurrar este relatório no sonar?

O Maven sonar:sonarfará o trabalho (não esqueça de configurá-lo), aponte-o para o pom.xml principal para que ele execute todos os módulos. Use o sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.execparâmetro para informar ao sonar onde seu relatório de teste de integração está localizado. Toda vez que analisará novas classes de módulos, buscará informações sobre a cobertura no it-jacoco.exec.

Eu já tenho o jacoco.exec no meu diretório `target`, o` mvn sonar: sonar` o ignora / remove

Por padrão, mvn sonar:sonarfaz cleane exclui o diretório de destino, use sonar.dynamicAnalysis=reuseReportspara evitá-lo.

ZuzEL
fonte
20

NOVA MANEIRA DESDE A VERSÃO 0.7.7

Desde a versão 0.7.7, há uma nova maneira de criar um relatório agregado:

Você cria um projeto separado de 'relatório' que coleta todos os relatórios necessários (qualquer objetivo no projeto agregador é executado antes de seus módulos, portanto, não pode ser usado).

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

O pom raiz se parece com isso (não se esqueça de adicionar o novo módulo de relatório nos 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>

Os poms de cada submódulo não precisam ser alterados. O pom do módulo de relatório fica assim:

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

Um exemplo completo pode ser encontrado aqui .

Lonzak
fonte
3
Isso funciona. O relatório agregado mostra a cobertura cumulativa de código para todos os módulos. Você já tentou visualizar este relatório cumulativo no Sonar? Usei o sonar-qube para ler o jacoco.exec para relatórios individuais, mas com este relatório agregado, não vejo um jacoco.exec agregado no módulo de relatório.
precisa saber é o seguinte
@SwethaV Algum sucesso nisso? Nós estamos na mesma posição e precisa encontrar uma maneira de gerar o agregado exec :)
Vinky
Usamos o sonar qube versão 6.X, que tem sua própria página de cobertura de teste, portanto, não preciso do jacoco lá. Para uma versão mais antiga que instalado o plugin cobertura que também forneceu esta funcionalidade ...
Lonzak
11

Vou postar minha solução, pois ela é sutilmente diferente das outras e também me levou um dia sólido para acertar, com a ajuda das respostas existentes.

Para um projeto Maven com vários módulos:

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

Onde o WARprojeto é o aplicativo Web principal, LIB1 e 2 são módulos adicionais dos quais WARdepende e TESTé onde os testes de integração residem. TESTgira uma instância incorporada do Tomcat (não pelo plug-in do Tomcat) e executa o WARprojeto e os testa por meio de um conjunto de testes JUnit. O WAReLIB projetos têm seus próprios testes de unidade.

O resultado de tudo isso é a integração e a cobertura do teste de unidade serem separadas e poderem ser distinguidas no 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.xmlherdará o a plugins execução 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>

Também achei a publicação no blog de Petri Kainulainens, 'Criando relatórios de cobertura de código para testes de unidade e integração com o JaCoCo Maven Plugin', valiosa para o lado da configuração da JaCoCo.

markdsievers
fonte
Preciso atualizar este post em algum momento, pois ele é um pouco abaixo do ideal. agent-for-ité necessário apenas ao executar os testes no TESTmódulo, mas a configuração atual o executa para todos os outros módulos, nos quais não tem valor. A melhoria seria ter agent-for-utexecutado em todos os outros módulos e agent-for-itsomente executado TEST.
MarkSievers #
7

Existe uma maneira de conseguir isso. A mágica é criar um arquivo jacoco.exec combinado. E com o maven 3.3.1 existe uma maneira fácil de conseguir isso. Aqui meu 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>

Se você adicionar esse perfil ao pom pai e ligar para mvn clean install sonar:sonar -DrunSonar para obter a cobertura completa.

A mágica aqui é maven.multiModuleProjectDirectory. Essa pasta é sempre a pasta em que você iniciou sua compilação.

Sven Oppermann
fonte
Isso funcionou para mim, depois de passar por várias outras soluções.
Jimson Kannanthara James
O único problema foi que tive que executar o sonar com comando, mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.0.905:sonar -DrunSonardevido a A required class was missing while executing org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar: org/sonar/batch/bootstrapper/IssueListenererro.
Jimson Kannanthara James
1
Não use essa mágica. A propriedade fornecida é um detalhe de implementação e não deve ser invocada. - Equipe de desenvolvedores do Maven
Michael-O
6

A configuração que uso no meu pom de nível pai, onde tenho fases de teste de unidade e integração separadas.

Eu configuro as seguintes propriedades no pai POM Properties

    <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 as definições de plug-in sob gerenciamento de plugins.

Observe que eu defino uma propriedade para os argumentos surefire (surefireArgLine) e failafe (failafeArgLine) para permitir que o jacoco configure o javaagent para executar com cada teste.

Em 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 na seção de compilação

 <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 na seção de relatórios

    <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
fonte
1
Vejo que você tem a <append>true</append>configuração de acordo com as prepare-agentseções ...
Stewart
Ênfase. Leia meu comentário para outra resposta. Era o ingrediente vital que faltava para mim, não encontrado em outros documentos.
Stewart
você tem um link no github para isso? Eu quero fazer configurações exatamente semelhantes
Rohit Kasat
@Rhit - não, não, pelo menos não em um repositório público.
sweetfa
Isso funciona muito bem com o Sonar Qube Versão 6.5 (compilação 27846) ...: D A Cobertura de código será exibida corretamente.
Udoline
4

Encontrei outra solução para as novas versões do Sonar em que o formato de relatório binário da JaCoCo (* .exec) estava obsoleto e o formato preferido é XML (SonarJava 5.12 e superior). A solução é muito simples e semelhante à solução anterior com relatórios * .exec no diretório pai deste tópico: https://stackoverflow.com/a/15535970/4448263 .

Supondo que nossa estrutura de projeto seja:

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

Você precisa da seguinte configuração do plug-in do maven build no pom do projeto 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>

Em seguida, crie um projeto com o maven:

mvn clean verify

E para o Sonar, você deve definir propriedades na GUI de administração:

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

ou usando a linha de comando:

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

Descrição

Isso cria relatórios binários para cada módulo em diretórios padrão: target/jacoco.exec. Em seguida, cria relatórios XML para cada módulo em diretórios padrão: target/site/jacoco/jacoco.xml. Em seguida, cria um relatório agregado para cada módulo no diretório personalizado ${project.basedir}/../target/site/jacoco-aggregate/que é relativo ao diretório pai de cada módulo. Para o módulo A e o módulo B, este será o caminho comummoduleC/target/site/jacoco-aggregate/ .

Como o módulo B depende do módulo A, o módulo B será construído por último e seu relatório será usado como um relatório de cobertura agregado no Sonar para os módulos A e B.

Além do relatório agregado, precisamos de um relatório normal do módulo, pois os relatórios agregados da JaCoCo contêm dados de cobertura apenas para dependências.

Juntos, esses dois tipos de relatórios fornecem dados de cobertura completa para o Sonar.

Há uma pequena restrição: você deve poder escrever um relatório no diretório pai do projeto (deve ter permissão). Ou você pode definir a propriedade jacoco.skip=trueno pom.xml (moduleC) do projeto raiz e jacoco.skip=falsenos módulos com classes e testes (moduleA e moduleB).

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

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

Como sonares sonar.jacoco.reportPath, sonar.jacoco.itReportPathe sonar.jacoco.reportPathstodos foram preteridos , você deve usar sonar.coverage.jacoco.xmlReportPathsagora. Isso também tem algum impacto se você deseja configurar um projeto de maven de múltiplos módulos com o Sonar e o Jacoco.

Como o @Lonzak apontou , desde o Sonar 0.7.7, você pode usar o objetivo de agregação de relatórios do Sonars. Basta colocar no seu pai pom a seguinte dependência:

<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 as versões atuais do jacoco-maven-plugin são compatíveis com o xml-reports, isso criará para cada módulo em sua própria pasta de destino uma pasta agregada site / jacoco contendo um jacoco.xmlarquivo.

Para permitir que o Sonar combine todos os módulos, use o seguinte comando:

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

Para manter minha resposta curta e precisa, não mencionei as dependências maven-surefire-plugine maven-failsafe-plugin. Você pode apenas adicioná-los sem nenhuma outra configuração:

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

Você pode chamar uma tarefa ant chamada mesclagem no maven, para reunir todos os arquivos de cobertura (* .exec) no mesmo arquivo.

Se você estiver executando testes de unidade, use o pacote de preparação da fase ; se você executar o teste de integração, use o pós-teste de integração .

Esse site tem um exemplo de como chamar tarefa jacoco form no projeto maven

Você pode usar esse arquivo mesclado no sonar.

Andre Piantino
fonte
0

para ter testes de unidade E testes de integração, você pode usar o maven-surefire-plugin e o maven-failafe-plugin com inclusões / exclusões restritas. Eu estava tocando com o CDI enquanto entrava em contato com o sonar / jacoco, então acabei neste projeto:

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

Talvez isso te ajude um pouco. no meu pom.xml, uso "-javaagent" implícito, definindo a opção argLine na seção de configuração dos plug-ins de teste especificados. Explícito usando ANT em projetos MAVEN é algo que eu não tentaria, para mim é muito misturar dois mundos.

Eu só tenho um projeto de módulo único, mas talvez ajude você a ajustar o seu para funcionar.

nota: talvez nem todos os plug-ins do maven estejam atualizados, talvez alguns problemas sejam corrigidos nas versões posteriores

FibreFoX
fonte
Obrigado por isso; Vou dar uma olhada e informá-lo como funciona. Pode não ser esta semana embora :)
Stewart
0

Este exemplo funciona muito bem para mim:

<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
fonte
Por favor, forneça algumas explicações para a sua resposta
mishsx 04/10/19
@mishsx Um bom artigo para explicações: natritmeyer.com/howto/…
SerhatTopkaya