Bagaimana cara mengkonfigurasi multi-modul Maven + Sonar + JaCoCo untuk memberikan laporan cakupan gabungan?

128

Saya telah mencari dari atas ke bawah di internet untuk yang ini. Ada banyak setengah-jawaban di luar sana, yang harus dilakukan dengan sifat Maven seperti ${sonar.jacoco.reportPath}, atau org.jacoco:jacoco-maven-plugin:prepare-agentatau pengaturan maven-surefire-plugin argLinedengan -javaagent.

Entah bagaimana, tidak satu pun dari jawaban ini, baik sendiri, atau kombinasi, menghasilkan apa yang saya cari: Laporan cakupan yang menunjukkan kelas yang tercakup jika digunakan dalam tes yang lebih tinggi, seperti entitas yang digunakan oleh DAO, meskipun tidak sepenuhnya dicakup oleh pengujian di modulnya sendiri.

Apakah ada konfigurasi yang pasti di suatu tempat, untuk mencapai ini?

Stewart
sumber

Jawaban:

165

Saya berada dalam situasi yang sama dengan Anda, setengah jawaban yang tersebar di seluruh Internet cukup menjengkelkan, karena tampaknya banyak orang memiliki masalah yang sama, tetapi tidak ada yang dapat peduli untuk menjelaskan sepenuhnya bagaimana mereka menyelesaikannya.

Dokumen Sonar merujuk ke proyek GitHub dengan contoh-contoh yang berguna. Apa yang saya lakukan untuk menyelesaikan ini adalah menerapkan logika tes integrasi ke tes unit biasa (meskipun tes unit yang tepat harus spesifik submodule, ini tidak selalu terjadi).

Di pom.xml induk, tambahkan properti ini:

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

Ini akan membuat Sonar mengambil laporan pengujian unit untuk semua submodul di tempat yang sama (folder target di proyek induk). Ini juga memberi tahu Sonar untuk menggunakan kembali laporan yang dijalankan secara manual alih-alih menggulirkannya sendiri. Kita hanya perlu membuat jacoco-maven-plugin berjalan untuk semua submodul dengan menempatkan ini di pom induk, di dalam 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>

destFilemenempatkan file laporan di tempat Sonar akan mencarinya dan appendmembuatnya ditambahkan ke file daripada menimpanya. Ini akan menggabungkan semua laporan JaCoCo untuk semua submodul dalam file yang sama.

Sonar akan melihat file itu untuk setiap submodule, karena itulah yang kami tunjukkan di atas, memberi kami hasil pengujian unit gabungan untuk file multi modul di Sonar.

mpontes.dll
sumber
Menakjubkan! Ini berhasil. Akhirnya! Saya pikir sihir yang hilang dari mantra penting yang saya lewatkan adalah <append> benar </append>
Stewart
Berhasil! Saya harus melakukan yang baru mvn packagesebelum menjalankan mvn sonar:sonaruntuk mendapatkan jalur laporan baru yang dibuat.
thomasa88
2
Menurut contoh, properti "sonar.jacoco.itReportPath" harus digunakan untuk mendapatkan hasil yang digabungkan menjadi "cakupan kode keseluruhan". Harap perbarui jawaban.
Yves Martin
4
"sonar.dynamicAnalysis" juga tidak digunakan lagi: docs.sonarqube.org/display/SONAR/Release+4.3+Upgrade+Notes
Yves Martin
3
Tautan Diperbarui: docs.sonarqube.org/display/SONARQUBE53/…
Lonzak
23

FAQ

Pertanyaan dari atas kepala saya sejak saat itu saya menjadi gila dengan jacoco.

Server aplikasi saya (jBoss, Glassfish ..) berlokasi di Irak, Suriah, apa saja .. Apakah mungkin mendapatkan cakupan multi-modul saat menjalankan uji integrasi? Jenkins dan Sonar juga berada di server yang berbeda.

Iya. Anda harus menggunakan agen jacoco yang berjalan dalam mode output=tcpserver, jacoco ant lib. Pada dasarnya dua jars. Ini akan memberi Anda 99% kesuksesan.

Bagaimana cara kerja agen jacoco?

Anda menambahkan string

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

ke server aplikasi Anda JAVA_OPTS dan mulai ulang. Dalam string ini saja[your_path] perlu diganti dengan jalur ke jacocoagent.jar, disimpan (simpan!) Di VM Anda tempat server aplikasi berjalan. Sejak saat itu Anda memulai server aplikasi, semua aplikasi yang diterapkan akan dipantau secara dinamis dan aktivitasnya (yang berarti penggunaan kode) akan siap untuk Anda dapatkan dalam format jacocos .exec oleh permintaan tcl.

Bisakah saya mengatur ulang agen jacoco untuk mulai mengumpulkan data eksekusi hanya sejak pengujian saya dimulai?

Ya, untuk itu Anda membutuhkan skrip jacocoant.jar dan ant build yang terletak di ruang kerja jenkins Anda.

Jadi pada dasarnya yang saya butuhkan dari http://www.eclemma.org/jacoco/ adalah jacocoant.jar terletak di ruang kerja jenkins saya, dan jacocoagent.jar ada di VM server aplikasi saya?

Betul sekali.

Saya tidak ingin menggunakan semut, saya pernah mendengar bahwa plugin jacoco maven dapat melakukan semua hal juga.

Itu tidak benar, plugin jacoco maven dapat mengumpulkan data pengujian unit dan beberapa data pengujian integrasi (lihat Arquillian Jacoco ), tetapi jika Anda misalnya memiliki pengujian terjamin sebagai build terpisah di jenkins, dan ingin menunjukkan cakupan multi-modul, saya bisa Saya tidak melihat bagaimana plugin maven dapat membantu Anda.

Apa sebenarnya yang diproduksi oleh agen jacoco?

Hanya data cakupan dalam .execformat. Sonar kemudian bisa membacanya.

Apakah jacoco perlu tahu di mana lokasi kelas java saya?

Tidak, sonar melakukannya, tapi tidak jacoco. Saat kamu melakukanmvn sonar:sonar jalur ke kelas mulai berlaku.

Lalu bagaimana dengan skrip semut?

Itu harus disajikan di ruang kerja jenkins Anda. Skrip semut saya, saya menyebutnya jacoco.xmlterlihat seperti itu:

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

Dua parameter wajib yang harus Anda lewati saat menjalankan skrip ini, -Dworkspace=$WORKSPACE gunakan untuk mengarahkan ke ruang kerja jenkins dan -Djacoco.host=yourappserver.comtanpa hosthttp://

Juga perhatikan bahwa saya meletakkan saya jacocoant.jarke $ {workspace} /tools/jacoco/jacocoant.jar

Apa yang harus saya lakukan selanjutnya?

Apakah Anda memulai server aplikasi Anda dengan jacocoagent.jar?

Apakah Anda meletakkan skrip semut dan jacocoant.jar di ruang kerja jenkins Anda?

Jika ya, langkah terakhir adalah mengkonfigurasi build jenkins. Berikut strateginya:

  1. Panggil target semut jacocoResetuntuk mengatur ulang semua data yang dikumpulkan sebelumnya.
  2. Jalankan pengujian Anda
  3. Panggil target semut jacocoReportuntuk mendapatkan laporan

Jika semuanya benar, Anda akan lihat it-jacoco.exec di ruang kerja build Anda.

Lihat tangkapan layar, saya juga telah antmenginstal di ruang kerja saya di $WORKSPACE/tools/antdir, tetapi Anda dapat menggunakan yang diinstal di jenkins Anda.

masukkan deskripsi gambar di sini

Bagaimana cara mendorong laporan ini di sonar?

Maven sonar:sonarakan melakukan pekerjaan itu (jangan lupa untuk mengkonfigurasinya), arahkan ke pom.xml utama sehingga akan dijalankan melalui semua modul. Gunakan sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.execparameter untuk memberi tahu sonar di mana laporan pengujian integrasi Anda berada. Setiap kali akan menganalisis kelas modul baru, ia akan mencari informasi tentang cakupan di it-jacoco.exec.

Saya sudah memiliki jacoco.exec di direktori `target` saya,` mvn sonar: sonar` mengabaikan / menghapusnya

Secara default mvn sonar:sonartidak cleandan menghapus direktori target Anda, gunakan sonar.dynamicAnalysis=reuseReportsuntuk menghindarinya.

ZuzEL
sumber
20

CARA BARU SEJAK VERSI 0.7.7

Sejak Versi 0.7.7, ada cara baru untuk membuat laporan gabungan:

Anda membuat proyek 'laporan' terpisah yang mengumpulkan semua laporan yang diperlukan (Sasaran apa pun dalam proyek agregator dijalankan sebelum modulnya sehingga tidak dapat digunakan).

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

The akar pom terlihat seperti ini (jangan lupa untuk menambahkan modul laporan baru di bawah modul):

<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 dari setiap sub modul tidak perlu diubah sama sekali. Pom dari modul laporan terlihat seperti ini:

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

Contoh lengkap dapat ditemukan di sini .

Lonzak
sumber
3
Ini bekerja. Laporan gabungan menunjukkan cakupan kode kumulatif untuk semua modul. Apakah Anda pernah mencoba melihat laporan kumulatif ini di Sonar? Saya menggunakan sonar-qube untuk membaca jacoco.exec untuk laporan individual, tetapi dengan kumpulan laporan ini, saya tidak melihat jacoco.exec gabungan di modul laporan.
Swetha V
@SwethaV Ada yang sukses dalam hal ini? Kami berada di posisi yang sama dan perlu menemukan cara untuk menghasilkan exec teragregasi :)
Vinky
Kami menggunakan sonar qube versi 6.X yang memiliki halaman cakupan pengujian sendiri sehingga saya tidak perlu jacoco di sana. Untuk versi yang lebih lama kami menginstal plugin cobertura yang juga menyediakan fungsionalitas ini ...
Lonzak
11

Saya akan memposting solusi saya karena sedikit berbeda dari yang lain dan juga membutuhkan waktu seharian untuk melakukannya dengan benar, dengan bantuan jawaban yang ada.

Untuk proyek Maven multi-modul:

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

Jika WARproyek adalah aplikasi web utama, LIB1 dan 2 adalah modul tambahan yang WARbergantung pada dan TESTtempat uji integrasi dijalankan. TESTmemutar instance Tomcat yang disematkan (bukan melalui plugin Tomcat) dan menjalankan WARproyek dan mengujinya melalui serangkaian pengujian JUnit. The WARdanLIB keduanya memiliki pengujian unitnya sendiri.

Hasil dari semua ini adalah integrasi dan cakupan pengujian unit dipisahkan dan dapat dibedakan di 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 dan TEST pom.xmlakan mewarisi eksekusi plugin 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>

Saya juga menemukan posting blog Petri Kainulainens 'Membuat Laporan Cakupan Kode untuk Tes Unit dan Integrasi Dengan Plugin JaCoCo Maven' menjadi berharga untuk sisi pengaturan JaCoCo.

markdsievers
sumber
Saya perlu memperbarui posting ini pada tahap tertentu karena sebenarnya sedikit kurang optimal. agent-for-ithanya diperlukan saat menjalankan pengujian dalam TESTmodul tetapi konfigurasi saat ini menjalankannya untuk setiap modul lainnya, yang tidak memiliki nilai. Perbaikan akan agent-for-utberjalan di semua modul lain dan agent-for-ithanya berjalan di TEST.
markdsievers
8

Ada cara untuk mencapai ini. Keajaibannya adalah membuat file jacoco.exec gabungan. Dan dengan maven 3.3.1 ada cara mudah untuk mendapatkannya. Berikut profil saya:

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

Jika Anda menambahkan profil ini ke pom dan panggilan orang tua Anda mvn clean install sonar:sonar -DrunSonar Anda mendapatkan cakupan lengkap.

Keajaiban di sini maven.multiModuleProjectDirectory. Folder ini selalu merupakan folder tempat Anda memulai pembuatan maven.

Sven Oppermann
sumber
Ini berhasil untuk saya, setelah melalui berbagai solusi lain.
Jimson Kannanthara James
Satu-satunya masalah adalah, saya harus menjalankan sonar dengan perintah, mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.0.905:sonar -DrunSonarkarena A required class was missing while executing org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar: org/sonar/batch/bootstrapper/IssueListenerkesalahan.
Jimson Kannanthara James
1
Jangan gunakan sihir ini. Properti yang diberikan adalah detail implementasi dan tidak boleh diandalkan. - Tim Pengembang Maven
Michael-O
6

Konfigurasi yang saya gunakan di pom level induk tempat saya memiliki fase pengujian unit dan integrasi yang terpisah.

Saya mengkonfigurasi properti berikut di Properti POM induk

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

Saya menempatkan definisi plugin di bawah manajemen plugin.

Perhatikan bahwa saya mendefinisikan properti untuk argumen surefire (surefireArgLine) dan failafe (failafeArgLine) untuk memungkinkan jacoco mengkonfigurasi javaagent agar berjalan dengan setiap pengujian.

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

Dan di bagian build

 <build>
     <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
        </plugin>

        <plugin>
            <!-- for unit test execution -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
        </plugin>
        <plugin>
            <!-- For integration test separation -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
        </plugin>
        <plugin>
            <!-- For code coverage -->
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
        </plugin>
        ....

Dan di bagian pelaporan

    <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
sumber
1
Saya melihat Anda memiliki <append>true</append>konfigurasi di bawah prepare-agentbagian ...
Stewart
Tekanan. Baca komentar saya untuk jawaban lain. Itu adalah bahan penting yang hilang bagi saya, tidak ditemukan di dokumen lain.
Stewart
apakah Anda memiliki tautan github untuk ini? Saya ingin melakukan konfigurasi yang persis sama
Rohit Kasat
@Rhit - tidak, saya tidak, setidaknya tidak di repositori publik.
sweetfa
Ini bekerja sangat baik dengan Sonar Qube Versi 6.5 (build 27846) ...: D Cakupan Kode akan ditampilkan dengan benar.
udoline
4

Saya menemukan solusi lain untuk versi Sonar baru di mana format laporan biner JaCoCo (* .exec) tidak digunakan lagi dan format yang disukai adalah XML (SonarJava 5.12 dan lebih tinggi). Solusinya sangat sederhana dan mirip dengan solusi sebelumnya dengan laporan * .exec di direktori induk dari topik ini: https://stackoverflow.com/a/15535970/4448263 .

Dengan asumsi bahwa struktur proyek kami adalah:

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

Anda perlu mengikuti konfigurasi plugin build maven di pom proyek agregat:

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

Kemudian bangun proyek dengan maven:

mvn clean verify

Dan untuk Sonar Anda harus mengatur properti di GUI administrasi:

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

atau menggunakan baris perintah:

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

Deskripsi

Hal ini menciptakan laporan biner untuk setiap modul di direktori default: target/jacoco.exec. Kemudian menciptakan laporan XML untuk setiap modul di direktori default: target/site/jacoco/jacoco.xml. Kemudian membuat laporan agregat untuk setiap modul dalam direktori kustom ${project.basedir}/../target/site/jacoco-aggregate/yang berhubungan dengan direktori induk untuk setiap modul. Untuk moduleA dan moduleB ini akan menjadi jalur umum moduleC/target/site/jacoco-aggregate/.

Karena moduleB bergantung pada moduleA, moduleB akan dibuat terakhir dan laporannya akan digunakan sebagai laporan cakupan gabungan di Sonar untuk kedua modul A dan B.

Selain laporan gabungan, kami memerlukan laporan modul normal karena laporan gabungan JaCoCo berisi data cakupan hanya untuk dependensi.

Bersama-sama, kedua jenis laporan ini menyediakan data cakupan penuh untuk Sonar.

Ada satu batasan kecil: Anda harus dapat menulis laporan di direktori induk proyek (harus memiliki izin). Atau Anda dapat menyetel properti jacoco.skip=truedi pom.xml (moduleC) proyek root dan jacoco.skip=falsedi modul dengan kelas dan pengujian (moduleA dan moduleB).

keddok
sumber
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
sumber
2

Sebagai Sonar sonar.jacoco.reportPath, sonar.jacoco.itReportPathdan sonar.jacoco.reportPathssemuanya sudah usang , Anda harus menggunakan sonar.coverage.jacoco.xmlReportPathssekarang. Ini juga berdampak jika Anda ingin mengonfigurasi proyek maven multi modul dengan Sonar dan Jacoco.

Seperti yang @Lonzak tunjukkan , sejak Sonar 0.7.7, Anda dapat menggunakan tujuan aggragasi laporan Sonar. Masukkan saja Anda orang tua pom ketergantungan berikut:

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

Karena versi terbaru dari jacoco-maven-plugin kompatibel dengan xml-reports, ini akan membuat untuk setiap modul di folder targetnya sendiri folder situs / jacoco-aggregate yang berisi jacoco.xmlfile.

Untuk membiarkan Sonar menggabungkan semua modul, gunakan perintah berikut:

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

Untuk menjaga jawaban saya singkat dan tepat, saya tidak menyebutkan dependensi maven-surefire-plugindan maven-failsafe-plugin. Anda bisa menambahkannya tanpa konfigurasi lain:

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

Anda dapat memanggil tugas semut yang disebut merge on maven, untuk menempatkan semua file cakupan (* .exec) bersama-sama dalam file yang sama.

Jika Anda menjalankan pengujian unit, gunakan fase persiapan-paket , jika Anda menjalankan pengujian integrasi, gunakan uji pasca-integrasi .

Situs ini memiliki contoh bagaimana memanggil tugas semut jacoco di proyek maven

Anda dapat menggunakan file gabungan ini di sonar.

Andre Piantino
sumber
0

untuk melakukan pengujian unit DAN pengujian integrasi, Anda dapat menggunakan maven-surefire-plugin dan maven-failafe-plugin dengan penyertaan / pengecualian terbatas. Saya bermain dengan CDI saat berhubungan dengan sonar / jacoco, jadi saya berakhir di proyek ini:

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

Mungkin itu sedikit membantu Anda. di pom.xml saya, saya menggunakan "-javaagent" secara implisit dengan mengatur opsi-argLine di bagian-konfigurasi dari plugin-pengujian yang ditentukan. Secara eksplisit menggunakan ANT dalam proyek MAVEN adalah sesuatu yang tidak akan saya coba, bagi saya itu terlalu banyak mencampurkan dua dunia.

Saya hanya memiliki proyek maven modul tunggal, tetapi mungkin ini membantu Anda menyesuaikan milik Anda untuk bekerja.

catatan: mungkin tidak semua maven-plugin up2date, mungkin beberapa masalah diperbaiki di versi yang lebih baru

FibreFoX
sumber
Terima kasih untuk ini; Saya akan memeriksanya dan memberi tahu Anda cara kerjanya. Mungkin tidak minggu ini :)
Stewart
0

Sampel ini bekerja dengan sangat baik untuk saya:

<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
sumber
Mohon berikan penjelasan untuk jawaban Anda
mishsx
@mishsx Artikel yang bagus untuk penjelasan: natritmeyer.com/howto/…
SerhatTopkaya