병합 된 커버리지 보고서를 제공하기 위해 다중 모듈 Maven + Sonar + JaCoCo를 구성하는 방법은 무엇입니까?


128

나는 이것을 위해 인터넷을 위아래로 검색했습니다. 메이븐과 같은 속성과는 거기 절반 답변 많이있다 ${sonar.jacoco.reportPath}, 또는 org.jacoco:jacoco-maven-plugin:prepare-agent또는 설정 maven-surefire-plugin argLine와 함께 -javaagent.

이러한 답변 중 어느 것도 자체적으로 또는 조합하여 내가 추구하는 것을 생성하지 않는 방법 : 사용중인 엔티티와 같이 스택 상위 테스트에서 사용되는 경우 적용되는 클래스를 보여주는 커버리지 보고서 자체 모듈의 테스트로 완전히 다루지 않았지만 DAO에 의해.

이것을 달성하기 위해 어딘가에 확실한 구성이 있습니까?

답변:


164

나는 당신과 같은 상황에 있었고, 인터넷 전체에 흩어져있는 절반의 답변은 많은 사람들이 같은 문제를 가지고있는 것처럼 보였기 때문에 상당히 짜증났습니다. 그러나 아무도 그들이 어떻게 해결했는지 완전히 설명하지 못했습니다.

소나 문서는 참조 예와 GitHub의 프로젝트에 도움이됩니다. 이 문제를 해결하기 위해 한 것은 통합 테스트 논리를 정규 단위 테스트에 적용하는 것이 었습니다 (적절한 단위 테스트는 하위 모듈에 따라 다르지만 항상 그런 것은 아닙니다).

상위 pom.xml에서 다음 속성을 추가합니다.

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

이렇게하면 Sonar는 동일한 위치 (상위 프로젝트의 대상 폴더)에있는 모든 하위 모듈에 대한 단위 테스트 보고서를 선택합니다. 또한 Sonar에 자체 롤링 대신 수동으로 실행 된 보고서를 재사용하도록 지시합니다. 빌드 / 플러그인 내부의 부모 pom에이를 배치하여 모든 하위 모듈에 대해 jacoco-maven-plugin을 실행하면됩니다.

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

destFileSonar가 찾는 위치에 보고서 파일을 배치하고 append덮어 쓰지 않고 파일에 추가합니다. 이것은 동일한 파일의 모든 하위 모듈에 대한 모든 JaCoCo 보고서를 결합합니다.

Sonar는 위에서 지적한 것이기 때문에 각 하위 모듈에 대해 해당 파일을 살펴보고 Sonar의 다중 모듈 파일에 대한 결합 된 단위 테스트 결과를 제공합니다.


기이! 이것은 효과가 있습니다. 드디어! 나는 마법 내가 없어진 것이 중요 주문 누락 생각 WAS <APPEND> 진정한 </ APPEND>
스튜어트

효과가있다! 새 보고서 경로를 생성하려면 mvn package실행 mvn sonar:sonar하기 전에 새 작업을 수행해야했습니다 .
thomasa88

2
예에 따르면 "sonar.jacoco.itReportPath"속성을 사용하여 병합 된 결과를 "전체 코드 범위"로 가져와야합니다. 답변을 업데이트하십시오.
Yves Martin

4
"sonar.dynamicAnalysis"도되지 않습니다 : docs.sonarqube.org/display/SONAR/Release+4.3+Upgrade+Notes
이브 마틴


23

자주하는 질문

그때부터 머릿속에서 나오는 질문은 자 코코에 미쳐 버렸다.

이라크, 시리아에있는 내 애플리케이션 서버 (jBoss, Glassfish ..)는 무엇이든 .. 통합 테스트를 실행할 때 다중 모듈 커버리지를 얻을 수 있습니까? Jenkins와 Sonar도 다른 서버에 있습니다.

예. 당신은 사용할 필요가 jacoco 에이전트를 해당 모드에서 실행 output=tcpserver, jacoco 개미 LIB. 기본적으로 두 jars. 이것은 당신에게 99 %의 성공을 줄 것입니다.

jacoco 에이전트는 어떻게 작동합니까?

문자열을 추가합니다.

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

애플리케이션 서버 JAVA_OPTS에 연결하고 다시 시작하십시오. 이 문자열 [your_path]에서 앱 서버가 실행되는 VM에 저장된 (저장!) jacocoagent.jar의 경로 로만 교체하면됩니다. 그 이후로 앱 서버를 시작하면 배포 된 모든 애플리케이션이 동적으로 모니터링되고 해당 활동 (코드 사용을 의미)이 tcl 요청에 의해 jacocos .exec 형식으로 가져올 준비가됩니다.

테스트 시작 이후에만 실행 데이터 수집을 시작하도록 jacoco 에이전트를 재설정 할 수 있습니까?

예,이를 위해서는 jenkins 작업 공간에있는 jacocoant.jar 및 ant 빌드 스크립트가 필요합니다.

그래서 기본적으로 http://www.eclemma.org/jacoco/에서 필요한 것은 내 jenkins 작업 공간에있는 jacocoant.jar이고 내 앱 서버 VM에있는 jacocoagent.jar입니까?

맞습니다.

나는 개미를 사용하고 싶지 않다. 나는 jacoco maven 플러그인이 모든 것을 할 수 있다고 들었다.

맞지 않습니다. jacoco maven 플러그인은 단위 테스트 데이터와 일부 통합 테스트 데이터 ( Arquillian Jacoco 참조 )를 수집 할 수 있지만, 예를 들어 젠킨스에서 별도의 빌드로 안심하고 테스트 할 수 있고 다중 모듈 적용 범위를 표시하려면 다음을 수행 할 수 있습니다. maven 플러그인이 어떻게 당신을 도울 수 있는지 보지 못합니다.

jacoco 에이전트는 정확히 무엇을 생산합니까?

.exec형식의 커버리지 데이터 만 . 그러면 Sonar는이를 읽을 수 있습니다.

jacoco는 내 Java 클래스가 어디에 있는지 알아야합니까?

아니, 소나는 있지만 jacoco는 아닙니다. mvn sonar:sonar수업 을 할 때 경로가 작용합니다.

그렇다면 개미 스크립트는 어떻습니까?

그것은 당신의 젠킨스 작업 공간에 제시되어야합니다. 내 개미 스크립트, 나는 jacoco.xml다음과 같이 불렀다 .

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

이 스크립트를 호출 할 때 전달해야하는 두 개의 필수 매개 변수는이를 -Dworkspace=$WORKSPACE 사용하여 jenkins 작업 공간을 가리키고 -Djacoco.host=yourappserver.com호스트없이http://

또한 jacocoant.jar$ {workspace} /tools/jacoco/jacocoant.jar에 넣었습니다.

다음에 무엇을해야합니까?

jacocoagent.jar로 앱 서버를 시작 했습니까?

젠킨스 작업 공간에 ant 스크립트와 jacocoant.jar를 넣었습니까?

그렇다면 마지막 단계는 젠킨스 빌드를 구성하는 것입니다. 전략은 다음과 같습니다.

  1. ant target jacocoReset을 호출 하여 이전에 수집 된 모든 데이터를 재설정합니다.
  2. 테스트 실행
  3. ant target jacocoReport을 호출 하여 보고서를받습니다.

모든 것이 맞으면 it-jacoco.exec빌드 작업 공간에 표시됩니다.

스크린 샷을보세요. 저는 또한 dir의 ant내 작업 공간에 설치 $WORKSPACE/tools/ant했지만 젠킨스에 설치된 것을 사용할 수 있습니다.

여기에 이미지 설명 입력

이 보고서를 소나로 푸시하는 방법은 무엇입니까?

Maven sonar:sonar이 작업을 수행하고 (구성하는 것을 잊지 마십시오) 모든 모듈을 통해 실행되도록 main pom.xml을 가리 킵니다. sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.exec매개 변수를 사용 하여 통합 테스트 보고서의 위치를 ​​소나에 알립니다. 새 모듈 클래스를 분석 할 때마다 it-jacoco.exec.

이미`target` 디렉토리에 jacoco.exec가 있습니다.`mvn sonar : sonar`는이를 무시 / 제거합니다.

기본으로 mvn sonar:sonar수행 clean하고 대상 디렉토리를 삭제, 사용 sonar.dynamicAnalysis=reuseReports을 방지하기 위해.


20

버전 0.7.7 이후의 새로운 방법

버전 0.7.7부터 집계 보고서를 만드는 새로운 방법이 있습니다.

필요한 모든 보고서를 수집하는 별도의 '보고서'프로젝트를 만듭니다 (집 계기 프로젝트의 모든 목표는 해당 모듈 보다 먼저 실행 되므로 사용할 수 없습니다).

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

루트 치어 같은 외모 (모듈에서 새 보고서 모듈을 추가하는 것을 잊지 마세요)

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

각 하위 모듈의 poms는 전혀 변경할 필요가 없습니다. 보고서 모듈 의 pom은 다음과 같습니다.

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

전체 예제는 여기 에서 찾을 수 있습니다 .


3
작동합니다. 집계 보고서는 모든 모듈에 대한 누적 코드 적용 범위를 보여줍니다. Sonar에서이 누적 보고서를 보려고 시도한 적이 있습니까? sonar-qube를 사용하여 개별 보고서에 대한 jacoco.exec를 읽었지만이 보고서 집계에서는 보고서 모듈에서 집계 된 jacoco.exec를 볼 수 없습니다.
Swetha V

@SwethaV 이것에 성공? 우리는 같은 위치에 있으며 집계 된 exec를 생성하는 방법을 찾아야합니다. :)
Vinky

우리는 자체 테스트 커버리지 페이지가있는 sonar qube 버전 6.X를 사용하므로 거기에 jacoco가 필요하지 않습니다. 이전 버전의 경우이 기능도 제공하는 cobertura 플러그인을 설치했습니다 ...
Lonzak

11

다른 사람과 미묘하게 다른 내 솔루션을 게시하고 기존 답변의 도움을 받아 올바른 방법으로 하루를 보냈습니다.

다중 모듈 Maven 프로젝트의 경우 :

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

를 Where WAR프로젝트의 주요 웹 응용 프로그램입니다, LIB1과 2는 추가 모듈입니다 WAR에 따라 달라집니다 및 TEST통합 테스트가 사는 곳이다. TEST임베디드 Tomcat 인스턴스 (Tomcat 플러그인을 통하지 않음)를 회전시키고 WAR프로젝트를 실행 하고 JUnit 테스트 세트를 통해 테스트합니다. WARLIB프로젝트는 모두 자신의 단위 테스트가 있습니다.

이 모든 결과는 통합 및 단위 테스트 커버리지가 분리되어 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, LIBTEST pom.xml상기 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>

또한 Petri Kainulainens 블로그 게시물 'JaCoCo Maven 플러그인을 사용하여 단위 및 통합 테스트를위한 코드 커버리지 보고서 작성' 이 JaCoCo 설정 측면에 유용하다는 것을 발견했습니다.


이 게시물은 실제로 약간 차선책이므로 어떤 단계에서 업데이트해야합니다. 모듈 agent-for-it에서 테스트를 실행할 때만 필요 TEST하지만 현재 구성은 값이없는 다른 모든 모듈에 대해 실행됩니다. 개선 사항은 agent-for-ut다른 모든 모듈 agent-for-it에서 실행되고 TEST.
markdsievers

7

이를 수행하는 방법이 있습니다. 마법은 결합 된 jacoco.exec 파일을 만드는 것입니다. 그리고 maven 3.3.1에서는 이것을 얻는 쉬운 방법이 있습니다. 여기 내 프로필 :

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

이 프로필을 부모 pom에 추가하고 전화 mvn clean install sonar:sonar -DrunSonar하면 완전한 보장을 받게됩니다.

여기서 마법은 maven.multiModuleProjectDirectory입니다. 이 폴더는 항상 Maven 빌드를 시작한 폴더입니다.


이것은 수많은 다른 솔루션을 거친 후에 저에게 효과적이었습니다.
Jimson Kannanthara James

유일한 문제는 오류 mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.0.905:sonar -DrunSonar로 인해 명령 으로 소나를 실행해야한다는 것 A required class was missing while executing org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar: org/sonar/batch/bootstrapper/IssueListener입니다.
Jimson Kannanthara James

1
이 마법을 사용하지 마십시오. 주어진 속성은 구현 세부 사항이며 신뢰할 수 없습니다. -Maven 개발자 팀
Michael-O

6

별도의 단위 및 통합 테스트 단계가있는 부모 수준 pom에서 사용하는 구성입니다.

상위 POM 속성에서 다음 속성을 구성합니다.

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

플러그인 관리 아래에 플러그인 정의를 배치합니다.

jacoco가 각 테스트와 함께 실행되도록 javaagent를 구성 할 수 있도록 surefire (surefireArgLine) 및 failsafe (failsafeArgLine) 인수에 대한 속성을 정의합니다.

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

그리고 빌드 섹션에서

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

그리고보고 섹션에서

    <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
난 당신이 가지고 볼 <append>true</append>세 이하 설정 prepare-agent... 섹션
스튜어트

중요성. 다른 답변에 대한 내 의견을 읽으십시오. 그것은 다른 문서에서는 찾을 수없는 저에게 없어진 필수 요소였습니다.
Stewart

이것에 대한 github 링크가 있습니까? 나는 정확히 유사한 CONFIGS을하고 싶지
Rohit Kasat

@Rhit-아니요, 적어도 공개 저장소에는 없습니다.
sweetfa

이것은 Sonar Qube 버전 6.5 (빌드 27846)에서 매우 잘 작동합니다. ... : D 코드 커버리지가 올바르게 표시됩니다.
udoline

4

JaCoCo의 바이너리 보고서 형식 (* .exec)이 더 이상 사용되지 않고 선호되는 형식이 XML (SonarJava 5.12 이상) 인 새 Sonar 버전에 대한 또 다른 솔루션을 찾았습니다. 솔루션은 매우 간단하며이 주제의 상위 디렉토리에 * .exec 보고서가있는 이전 솔루션과 유사합니다. https://stackoverflow.com/a/15535970/4448263 .

프로젝트 구조가 다음과 같다고 가정합니다.

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

집계 프로젝트의 pom에 다음 Maven 빌드 플러그인 구성이 필요합니다.

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

그런 다음 maven으로 프로젝트를 빌드하십시오.

mvn clean verify

그리고 Sonar의 경우 관리 GUI에서 속성을 설정해야합니다.

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

또는 명령 줄 사용 :

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

기술

이렇게하면 기본 디렉토리에있는 각 모듈에 대한 바이너리 보고서가 생성 target/jacoco.exec됩니다. 그런 다음 기본 디렉토리에있는 각 모듈에 대한 XML 보고서를 만듭니다 target/site/jacoco/jacoco.xml.. 그런 다음 각 모듈의 ${project.basedir}/../target/site/jacoco-aggregate/상위 디렉터리에 상대적인 사용자 지정 디렉터리의 각 모듈에 대한 집계 보고서를 만듭니다 . moduleA 및 moduleB의 경우 이것은 공통 경로 moduleC/target/site/jacoco-aggregate/입니다.

moduleB는 moduleA에 종속되므로 moduleB는 마지막에 빌드되고 해당 보고서는 Sonar에서 모듈 A와 B 모두에 대해 집계 커버리지 보고서로 사용됩니다.

집계 보고서 외에도 JaCoCo 집계 보고서에는 종속성에 대한 커버리지 데이터 만 포함되므로 일반 모듈 보고서가 필요합니다.

이 두 가지 유형의 보고서는 Sonar에 대한 전체 범위 데이터를 제공합니다.

약간의 제한이 있습니다. 프로젝트의 상위 디렉토리에 보고서를 작성할 수 있어야합니다 (권한이 있어야 함). 또는 jacoco.skip=true루트 프로젝트의 pom.xml (moduleC)과 jacoco.skip=false클래스 및 테스트가있는 모듈 (moduleA 및 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

수중 음파 탐지기가로서 sonar.jacoco.reportPath, sonar.jacoco.itReportPath그리고 sonar.jacoco.reportPaths모두가 한 사용되지 않는 , 당신은 사용해야합니다 sonar.coverage.jacoco.xmlReportPaths지금. 이것은 또한 Sonar 및 Jacoco로 다중 모듈 메이븐 프로젝트를 구성하려는 경우 약간의 영향을 미칩니다.

@Lonzak이 지적했듯이 Sonar 0.7.7부터 Sonar 보고서 집계 목표를 사용할 수 있습니다. 다음 종속성을 부모 pom에 넣으십시오.

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

현재 버전의 jacoco-maven-plugin은 xml-reports와 호환되므로 자체 대상 폴더의 모든 모듈에 대해 jacoco.xml파일을 포함하는 site / jacoco-aggregate 폴더를 생성 합니다.

Sonar가 모든 모듈을 결합하게하려면 다음 명령을 사용하십시오.

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

내 대답을 짧고 정확하게 유지하기 위해 maven-surefire-plugin maven-failsafe-plugin종속성에 대해서는 언급하지 않았습니다 . 다른 구성없이 추가 할 수 있습니다.

<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

모든 커버리지 파일 (* .exec)을 동일한 파일에 모으기 위해 merge on maven 이라는 ant 작업을 호출 수 있습니다 .

단위 테스트 를 실행하는 경우 prepare-package 단계를 사용하고 통합 테스트를 실행하는 경우 post-integration-test를 사용하십시오 .

이 사이트 에는 maven 프로젝트에서 jacoco ant task를 호출하는 방법에 대한 예제가 있습니다.

이 병합 된 파일을 소나에서 사용할 수 있습니다.


0

단위 테스트 및 통합 테스트를 사용하려면 제한된 포함 / 제외와 함께 maven-surefire-plugin 및 maven-failsafe-plugin을 사용할 수 있습니다. 나는 소나 / 자 코코와 연락하는 동안 CDI를 가지고 놀았 기 때문에이 프로젝트에서 끝났다.

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

아마 도움이 될 것입니다. 내 pom.xml에서 지정된 테스트 플러그인의 구성 섹션에서 argLine- 옵션을 설정하여 암시 적으로 "-javaagent"를 사용합니다. MAVEN 프로젝트에서 ANT를 명시 적으로 사용하는 것은 두 가지 세계를 많이 혼합하는 것이므로 시도하지 않을 것입니다.

단일 모듈 메이븐 프로젝트 만 있지만 작업에 맞게 조정하는 데 도움이 될 수 있습니다.

참고 : 모든 maven-plugins가 up2date가 아닐 수 있으며 일부 문제는 이후 버전에서 수정 될 수 있습니다.


감사합니다. 제가 살펴보고 어떻게 작동하는지 알려 드리겠습니다. 하지만 이번 주가 아닐 수도 있습니다. :)
Stewart

0

이 샘플은 저에게 매우 잘 작동합니다.

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

답변에 대한 설명을 제공해주십시오
mishsx 2010 년

설명은 @mishsx의 좋은 기사 : natritmeyer.com/howto/...
SerhatTopkaya
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.