マルチモジュールMaven + Sonar + JaCoCoを構成して、カバレッジレポートをマージするにはどうすればよいですか?


128

これをインターネットで検索しました。Mavenのような性質を行うにはそこに半分の答えがたくさん、あります${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に指示します。build / plugins内の親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のマルチモジュールファイルの単体テスト結果を組み合わせたものです。


素晴らしい!これはうまくいきました。最後に!欠けていた重要な呪文が欠けていた魔法は<append> true </ append>だったと思います
Stewart

できます!新しいレポートパスを生成するには、mvn package実行mvn sonar:sonarする前に新しく実行する必要がありました。
thomasa88 2014年

2
例によると、「sonar.jacoco.itReportPath」プロパティを使用して、マージされた結果を「全体的なコードカバレッジ」に取得する必要があります。回答を更新してください。
イヴ・マーティン

4
「sonar.dynamicAnalysis」も非推奨になりました:docs.sonarqube.org/display/SONAR/Release+4.3+Upgrade+Notes
Yves Martin

3
更新されたリンク:docs.sonarqube.org/display/SONARQUBE53/...
Lonzak

23

よくある質問

その時から頭のてっぺんからの質問は、ジャココに夢中になりました。

私のアプリケーションサーバー(jBoss、Glassfish ..)はシリア、イラクなどにあります。統合テストを実行するときにマルチモジュールカバレッジを取得することは可能ですか?JenkinsとSonarも異なるサーバー上にあります。

はい。モードで実行するjacocoエージェントoutput=tcpserver、jacoco ant lib を使用する必要があります。基本的に2つjarです。これにより、99%の成功率が得られます。

jacocoエージェントはどのように機能しますか?

文字列を追加します

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

アプリケーションサーバーJAVA_OPTSに追加し、再起動します。この文字列で[your_path]は、jacocoagent.jarへのパスに置き換えるだけでよく、アプリサーバーが実行されているVMに保存(store it!)します。アプリサーバーを起動すると、デプロイされたすべてのアプリケーションが動的に監視され、そのアクティビティ(コードの使用を意味する)は、tclリクエストによってjacocos .exec形式で取得できるようになります。

テストが開始されてから、jacocoエージェントをリセットして実行データの収集を開始できますか?

はい、そのためには、jacocoant.jarおよびantビルドスクリプトがjenkinsワークスペースに配置されている必要があります。

基本的に、http://www.eclemma.org/jacoco/から必要なのは、jenkinsワークスペースにあるjacocoant.jarと、アプリサーバーVMにあるjacocoagent.jarです。

そのとおり。

私はantを使いたくない、jacoco mavenプラグインもすべてのことができると聞きました。

そうではありません、jacoco mavenプラグインは単体テストデータといくつかの統合テストデータを収集できます(Arquillian Jacocoを参照)。たとえば、テストをjenkinsの個別のビルドとして保証し、マルチモジュールカバレッジを表示したい場合は、 mavenプラグインがどのように役立つかわかりません。

ジャココエージェントは正確には何を生成しますか?

.exec形式のカバレッジデータのみ。その後、ソナーはそれを読み取ることができます。

jacocoは私のJavaクラスがどこにあるかを知る必要がありますか?

いいえ、ソナーにはありますが、ジャココにはありません。あなたがmvn sonar:sonarクラスへのパスを行うとき、出てくる。

では、antスクリプトはどうでしょうか。

jenkinsワークスペースに表示する必要があります。私の蟻のスクリプト、私はそれを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>

このスクリプトを呼び出すときに渡す必要のある2つの必須 -Dworkspace=$WORKSPACE パラメーターは、それを使用してjenkinsワークスペースをポイントし、-Djacoco.host=yourappserver.comホストなしでホストします。http://

jacocoant.jar$ {workspace} /tools/jacoco/jacocoant.jar に配置したことにも注意してください

次に何をすればいいですか?

アプリサーバーをjacocoagent.jarで起動しましたか?

JenkinsワークスペースにAntスクリプトとjacocoant.jarを配置しましたか?

はいの場合、最後のステップはjenkinsビルドを構成することです。ここに戦略があります:

  1. antターゲットjacocoResetを呼び出して、以前に収集されたすべてのデータをリセットします。
  2. テストを実行する
  3. antターゲットjacocoReportを呼び出してレポートを取得する

すべてが正しい場合はit-jacoco.exec、ビルドワークスペースに表示されます。

スクリーンショットを見てください。antワークスペースの$WORKSPACE/tools/antdir にもインストールしていますが、jenkinsにインストールされているものを使用できます。

ここに画像の説明を入力してください

このレポートをソナーでプッシュする方法は?

Maven sonar:sonarがジョブを実行し(設定を忘れないでください)、メインのpom.xmlをポイントして、すべてのモジュールで実行されるようにします。sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.execパラメータを使用して、統合テストレポートの場所をソナーに伝えます。新しいモジュールクラスを分析するたびに、カバレッジに関する情報を探しますit-jacoco.exec

私はすでに `target`ディレクトリにjacoco.execを持っています、` mvn sonar:sonar`はそれを無視/削除します

デフォルトでmvn sonar:sonarclean、ターゲットディレクトリを実行して削除しますsonar.dynamicAnalysis=reuseReports。これを回避するには、を使用します。


20

NEW WAY SINCE VERSION 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>

各サブモジュールのpomを変更する必要はありません。レポートモジュールの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-qubeを使用して個々のレポートのjacoco.execを読みましたが、このレポート集計では、レポートモジュールに集計されたjacoco.execが表示されません。
Swetha V 2017

@SwethaVこれで何か成功した?私たちは同じ立場にあり、集約されたexecを生成する方法を見つける必要があります:)
Vinky

独自のテストカバレッジページがあるsonar qubeバージョン6.Xを使用しているため、そこにjacocoは必要ありません。古いバージョンでは、この機能も提供するcoberturaプラグインをインストールしました...
Lonzak

11

他のソリューションとは微妙に異なるソリューションを投稿します。また、既存の回答の助けを借りて、解決までに1日かかりました。

マルチモジュールMavenプロジェクトの場合:

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

どこWARプロジェクトは、メインのWebアプリケーションで、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>

WARLIB およびTEST pom.xmlJaCoCoプラグインの実行を継承します。

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

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

強調。別の答えに対する私のコメントを読んでください。他のドキュメントにはない、私にとって欠けている重要な成分でした。
Stewart

これのgithubリンクはありますか?まったく同じような構成を実行したい
Rohit Kasat

@Rhit-いいえ、できません。少なくともパブリックリポジトリにはありません。
sweetfa 2016年

これは、Sonar Qubeバージョン6.5(ビルド27846)で非常にうまく機能します...:Dコードカバレッジが正しく表示されます。
udoline 2018

6

これを達成する方法があります。魔法は、結合された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 2018

唯一の問題は、エラーの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
ジムソンカンナンタラジェームズ2018

1
この魔法を使わないでください。指定されたプロパティは実装の詳細であり、依存しないでください。-Maven開発チーム
Michael-O

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集計レポートには依存関係のカバレッジデータのみが含まれるため、通常のモジュールレポートが必要です。

これら2つのタイプのレポートを合わせて、Sonarの完全なカバレッジデータを提供します。

小さな制限が1つあります。プロジェクトの親ディレクトリにレポートを書き込むことができるはずです(権限が必要です)。または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

Sonars と同様にsonar.jacoco.reportPath、すべて非推奨となったので、今すぐ使用する必要があります。これは、SonarとJacocoを使用してマルチモジュールのmavenプロジェクトを構成する場合にも影響します。sonar.jacoco.itReportPathsonar.jacoco.reportPathssonar.coverage.jacoco.xmlReportPaths

@Lonzakが指摘したように、Sonar 0.7.7以降、Sonarsレポート集計目標を使用できます。親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

mavenでmergeというantタスクを呼び出して、すべてのカバレッジファイル(* .exec)を同じファイルにまとめることができます。

単体テストを実行している場合はフェーズprepare-packageを使用し、統合テストを実行している場合はpost-integration-testを使用します。

このサイトには、mavenプロジェクトでjacoco ant taskを呼び出す方法の例があります

このマージされたファイルをソナーで使用できます。


0

単体テストと統合テストを行うには、maven-surefire-pluginとmaven-failsafe-pluginを制限付きのinclude / excludesで使用できます。私はソナー/ジャココと連絡を取りながらCDIで遊んでいたので、このプロジェクトに行き着きました:

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

多分それはあなたに少し役立ちます。私のpom.xmlで、指定したtesting-pluginsのconfiguration-sectionにargLine-optionを設定することにより、暗黙的に「-javaagent」を使用します。MAVENプロジェクトでANTを明示的に使用することは、私が試してはいけないことです。

私は単一モジュールのmavenプロジェクトしか持っていませんが、作業に合わせて調整するのに役立つかもしれません。

注:多分すべてのmavenプラグインが最新ではないかもしれません。おそらくいくつかの問題は新しいバージョンで修正されています


これをありがとう; 調べて、どのように機能するかをお知らせします。しかし今週はそうではないかもしれません:)
スチュワート

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

@mishsx説明のための素晴らしい記事:natritmeyer.com/howto/...
SerhatTopkaya
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.