Làm cách nào để định cấu hình đa mô-đun Maven + Sonar + JaCoCo để đưa ra báo cáo bảo hiểm hợp nhất?


127

Tôi đã tìm kiếm trên internet cho cái này. Có rất nhiều câu trả lời ngoài kia, liên quan đến các thuộc tính Maven như ${sonar.jacoco.reportPath}, org.jacoco:jacoco-maven-plugin:prepare-agenthoặc cài đặt maven-surefire-plugin argLinevới -javaagent.

Một số cách, không có câu trả lời nào, một mình, hoặc kết hợp, đang tạo ra những gì tôi theo sau: Một báo cáo bảo hiểm cho thấy một lớp được bảo hiểm nếu nó được sử dụng trong các bài kiểm tra cao hơn, như các thực thể được sử dụng bởi DAO, mặc dù nó không được bao phủ hoàn toàn bởi các thử nghiệm trong mô-đun riêng của nó.

Có một cấu hình dứt khoát ở đâu đó, để đạt được điều này, xin vui lòng?

Câu trả lời:


163

Tôi cũng ở trong hoàn cảnh giống như bạn, một nửa câu trả lời rải rác trên Internet khá khó chịu, vì dường như nhiều người có cùng một vấn đề, nhưng không ai có thể bận tâm giải thích đầy đủ cách họ giải quyết nó.

Các tài liệu Sonar đề cập đến một dự án GitHub với các ví dụ hữu ích. Những gì tôi đã làm để giải quyết vấn đề này là áp dụng logic kiểm thử tích hợp vào các bài kiểm tra đơn vị thông thường (mặc dù các bài kiểm tra đơn vị phù hợp phải là mô đun cụ thể, nhưng điều này không phải luôn luôn như vậy).

Trong tệp cha mẹ, thêm các thuộc tính sau:

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

Điều này sẽ làm cho Sonar nhận các báo cáo thử nghiệm đơn vị cho tất cả các mô hình con ở cùng một nơi (một thư mục đích trong dự án mẹ). Nó cũng nói với Sonar sử dụng lại các báo cáo được chạy thủ công thay vì tự cuộn. Chúng ta chỉ cần làm cho jacoco-maven-plugin chạy cho tất cả các mô hình con bằng cách đặt cái này trong pom cha, bên trong build / 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>

destFileđặt tệp báo cáo vào nơi Sonar sẽ tìm kiếm nó và appendlàm cho nó gắn vào tệp chứ không phải ghi đè lên nó. Điều này sẽ kết hợp tất cả các báo cáo JaCoCo cho tất cả các mô hình con trong cùng một tệp.

Sonar sẽ xem xét tệp đó cho từng mô hình con, vì đó là những gì chúng tôi đã chỉ cho anh ta ở trên, cho chúng tôi kết quả thử nghiệm đơn vị kết hợp cho các tệp đa mô-đun trong Sonar.


Thật kỳ diệu! Điều này đã làm việc. Cuối cùng! Tôi nghĩ rằng phép thuật thiếu câu thần chú quan trọng mà tôi đã mất là <append> true </ append>
Stewart

Nó hoạt động! Tôi đã phải làm một cái mới mvn packagetrước khi chạy mvn sonar:sonarđể có được đường dẫn báo cáo mới được tạo.
thomasa88

2
Theo ví dụ, thuộc tính "sonar.jacoco.itReportPath" nên được sử dụng để có được kết quả hợp nhất vào "phạm vi bảo hiểm mã tổng thể". Hãy cập nhật câu trả lời.
Yves Martin

4
"sonar.dynamicAnalysis" cũng không được dùng nữa: docs.sonarqube.org/display/SONAR/Release+4.3+Upgrad+Notes
Yves Martin

3
Liên kết được cập nhật: docs.sonarqube.org/display/SONARQUBE53/ Kẻ
Lonzak

23

Câu hỏi thường gặp

Những câu hỏi từ đỉnh đầu của tôi kể từ lúc đó tôi phát điên với jacoco.

Máy chủ ứng dụng của tôi (jBoss, Glassfish ..) ở Iraq, Syria, bất cứ điều gì .. Có thể có được phạm vi bảo hiểm đa mô-đun khi chạy thử nghiệm tích hợp trên nó không? Jenkins và Sonar cũng ở trên các máy chủ khác nhau.

Đúng. Bạn phải sử dụng đại lý jacoco chạy trong chế độ output=tcpserver, jacoco ant lib. Về cơ bản hai jars. Điều này sẽ mang lại cho bạn thành công 99%.

Đại lý jacoco hoạt động như thế nào?

Bạn nối một chuỗi

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

đến máy chủ ứng dụng của bạn JAVA_OPTS và khởi động lại nó. Trong chuỗi này chỉ [your_path]phải được thay thế bằng đường dẫn đến jacocoagent.jar, được lưu trữ (lưu trữ nó!) Trên máy ảo của bạn nơi máy chủ ứng dụng chạy. Kể từ thời điểm bạn khởi động máy chủ ứng dụng, tất cả các ứng dụng được triển khai sẽ được theo dõi động và hoạt động của chúng (có nghĩa là sử dụng mã) sẽ sẵn sàng để bạn có được định dạng jacocos .exec theo yêu cầu tcl.

Tôi có thể đặt lại đại lý jacoco để bắt đầu thu thập dữ liệu thực hiện kể từ khi thử nghiệm bắt đầu không?

Có, với mục đích đó, bạn cần jacocoant.jar và tập lệnh xây dựng kiến ​​nằm trong không gian làm việc của jenkins.

Vì vậy, về cơ bản những gì tôi cần từ http://www.eclemma.org/jacoco/ là jacocoant.jar nằm trong không gian làm việc jenkins của tôi và jacocoagent.jar nằm trên máy chủ ứng dụng VM của tôi?

Đúng rồi.

Tôi không muốn sử dụng kiến, tôi đã nghe nói rằng plugin jacoco maven cũng có thể làm tất cả mọi thứ.

Điều đó không đúng, plugin jacoco maven có thể thu thập dữ liệu thử nghiệm đơn vị và một số dữ liệu thử nghiệm tích hợp (xem Arquillian Jacoco ), nhưng nếu bạn yên tâm thử nghiệm như một bản dựng riêng biệt trong jenkins và muốn hiển thị phạm vi đa mô-đun, tôi có thể Tôi không thấy plugin maven có thể giúp bạn như thế nào.

Chính xác thì đại lý jacoco sản xuất những gì?

Chỉ có dữ liệu bảo hiểm ở .execđịnh dạng. Sonar sau đó có thể đọc nó.

Có phải jacoco cần biết các lớp java của tôi nằm ở đâu không?

Không, sonar nào, nhưng không phải jacoco. Khi bạn làm mvn sonar:sonarđường dẫn đến lớp học đi vào chơi.

Vậy còn đoạn script ant thì sao?

Nó phải được trình bày trong không gian làm việc của jenkins. Kịch bản ant của tôi, tôi gọi nó là jacoco.xmlnhư thế:

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

Hai thông số bắt buộc bạn phải vượt qua khi gọi tập lệnh này -Dworkspace=$WORKSPACE sử dụng nó để trỏ đến không gian làm việc và -Djacoco.host=yourappserver.commáy chủ jenkins của bạn mà không cầnhttp://

Cũng lưu ý rằng tôi đặt jacocoant.jar$ {workspace} /tools/jacoco/jacocoant.jar

Tôi nên làm gì tiếp theo?

Bạn đã khởi động máy chủ ứng dụng của mình với jacocoagent.jar chưa?

Bạn đã đặt ant script và jacocoant.jar trong không gian làm việc của jenkins chưa?

Nếu có, bước cuối cùng là cấu hình một bản dựng jenkins. Đây là chiến lược:

  1. Gọi mục tiêu kiến jacocoResetđể thiết lập lại tất cả dữ liệu được thu thập trước đó.
  2. Chạy thử nghiệm của bạn
  3. Gọi mục tiêu kiến jacocoReportđể nhận báo cáo

Nếu mọi thứ đều đúng, bạn sẽ thấy it-jacoco.exectrong không gian làm việc xây dựng của mình.

Nhìn vào ảnh chụp màn hình, tôi cũng đã antcài đặt trong không gian làm việc của mình trong $WORKSPACE/tools/antthư mục, nhưng bạn có thể sử dụng một ảnh được cài đặt trong jenkins của bạn.

nhập mô tả hình ảnh ở đây

Làm thế nào để đẩy báo cáo này trong sonar?

Maven sonar:sonarsẽ thực hiện công việc (đừng quên cấu hình nó), trỏ nó vào pom.xml chính để nó sẽ chạy qua tất cả các mô-đun. Sử dụng sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.exectham số để báo cho sonar nơi báo cáo kiểm tra tích hợp của bạn được đặt. Mỗi lần nó sẽ phân tích các lớp mô-đun mới, nó sẽ tìm kiếm thông tin về phạm vi bảo hiểm it-jacoco.exec.

Tôi đã có jacoco.exec trong thư mục `target` của tôi,` mvn sonar: sonar` bỏ qua / xóa nó

Theo mặc định mvn sonar:sonarlàm cleanvà xóa thư mục mục tiêu của bạn, sử dụng sonar.dynamicAnalysis=reuseReportsđể tránh nó.


20

PHIÊN BẢN CÁCH MẠNG MỚI 0,7,7

Vì Phiên bản 0.7.7, có một cách mới để tạo báo cáo tổng hợp:

Bạn tạo một dự án 'báo cáo riêng biệt thu thập tất cả các báo cáo cần thiết (Bất kỳ mục tiêu nào trong dự án tổng hợp được thực hiện trước các mô-đun của nó do đó không thể sử dụng nó).

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

Các pom gốc trông như thế này (đừng quên thêm mô-đun báo cáo mới trong các mô-đun):

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

Các poms từ mỗi mô-đun phụ hoàn toàn không cần phải thay đổi. Pom từ mô-đun báo cáo trông như thế này:

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

Một exmple đầy đủ có thể được tìm thấy ở đây .


3
Những công việc này. Báo cáo tổng hợp cho thấy phạm vi bảo hiểm mã tích lũy cho tất cả các mô-đun. Bạn đã bao giờ thử xem báo cáo tích lũy này trong Sonar chưa? Tôi đã sử dụng sonar-qube để đọc jacoco.exec cho các báo cáo riêng lẻ, nhưng với tổng hợp báo cáo này, tôi không thấy một jacoco.exec tổng hợp trong mô-đun báo cáo.
Swetha V

@SwethaV Có thành công nào trong việc này không? Chúng tôi đang ở cùng một vị trí và cần tìm cách tạo ra người thực thi tổng hợp :)
Vinky

Chúng tôi sử dụng sonar qube phiên bản 6.X có trang bảo hiểm thử nghiệm riêng do đó tôi không cần jacoco ở đó. Đối với phiên bản cũ hơn, chúng tôi đã cài đặt plugin cobertura cũng cung cấp chức năng này ...
Lonzak

11

Tôi sẽ đăng giải pháp của mình vì nó khác biệt một cách tinh tế so với những người khác và cũng khiến tôi mất một ngày để làm đúng, với sự hỗ trợ của các câu trả lời hiện có.

Đối với dự án Maven đa mô-đun:

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

Trong đó WARdự án là ứng dụng web chính, LIB1 và 2 là các mô-đun bổ sung WARphụ thuộc vào và TESTlà nơi thử nghiệm tích hợp sống. TESTtạo ra một cá thể Tomcat nhúng (không thông qua plugin Tomcat) và chạy WARdự án và kiểm tra chúng thông qua một bộ các bài kiểm tra JUnit. Các WARLIBcác dự án đều có đơn vị xét nghiệm riêng của họ.

Kết quả của tất cả điều này là phạm vi kiểm thử tích hợp và đơn vị được tách ra và có thể được phân biệt trong 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.xmlsẽ kế thừa các plugin thực hiện 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>

Tôi cũng thấy bài đăng trên blog của Petri Kainulainens 'Tạo báo cáo bảo hiểm mã cho các bài kiểm tra đơn vị và tích hợp với Plugin JaCoCo Maven' có giá trị cho mặt thiết lập JaCoCo.


Tôi cần cập nhật bài viết này ở một số giai đoạn vì nó thực sự hơi tối ưu. agent-for-itchỉ cần thiết khi chạy các kiểm tra trong TESTmô-đun nhưng cấu hình hiện tại có nó chạy cho mọi mô-đun khác, nơi nó không có giá trị. Sự cải thiện sẽ là agent-for-utchạy trong tất cả các mô-đun khác và agent-for-itchỉ chạy trong TEST.
markdsievers

6

Cấu hình tôi sử dụng trong pom cấp cha mẹ của tôi, nơi tôi có các giai đoạn kiểm tra đơn vị và tích hợp riêng biệt.

Tôi cấu hình các thuộc tính sau trong Thuộc tính POM gốc

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

Tôi đặt các định nghĩa plugin dưới sự quản lý plugin.

Lưu ý rằng tôi xác định một thuộc tính cho các đối số Surefire (SurefireArgLine) và failafe (failafeArgLine) để cho phép jacoco định cấu hình javaagent chạy với mỗi thử nghiệm.

Theo pluginQuản lý

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

Và trong phần xây dựng

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

Và trong phần báo cáo

    <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
Tôi thấy bạn có <append>true</append>cấu hình dưới các prepare-agentphần ...
Stewart

Nhấn mạnh. Đọc bình luận của tôi để trả lời khác. Đó là thành phần quan trọng còn thiếu đối với tôi, không được tìm thấy trong các tài liệu khác.
Stewart

Bạn có một liên kết github cho điều này? Tôi muốn thực hiện các cấu hình chính xác tương tự
Rohit Kasat

@Rhit - không tôi không, ít nhất là không có trong kho lưu trữ công cộng.
sweetfa

Điều này hoạt động rất tốt với Sonar Qube Phiên bản 6.5 (bản dựng 27846) ...: D Bảo hiểm mã sẽ được hiển thị chính xác.
udoline

6

Có một cách để thực hiện điều này. Điều kỳ diệu là tạo một tệp jacoco.exec kết hợp. Và với maven 3.3.1, có một cách dễ dàng để có được điều này. Đây là hồ sơ của tôi:

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

Nếu bạn thêm hồ sơ này vào cha mẹ của bạn và gọi mvn clean install sonar:sonar -DrunSonarbạn sẽ nhận được bảo hiểm đầy đủ.

Điều kỳ diệu ở đây là maven.multiModuleProjectDirectory. Thư mục này luôn là thư mục nơi bạn bắt đầu xây dựng maven.


Điều này làm việc cho tôi, sau khi trải qua nhiều giải pháp khác.
Jimson Kannanthara James

Vấn đề duy nhất là, tôi đã phải chạy sonar bằng lệnh, mvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.0.905:sonar -DrunSonardo A required class was missing while executing org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar: org/sonar/batch/bootstrapper/IssueListenerlỗi.
Jimson Kannanthara James

1
Đừng sử dụng phép thuật này. Các tài sản nhất định là một chi tiết thực hiện và sẽ không được dựa vào. - Nhóm phát triển Maven
Michael-O

4

Tôi đã tìm thấy một giải pháp khác cho các phiên bản Sonar mới trong đó định dạng báo cáo nhị phân của JaCoCo (* .exec) không được dùng nữa và định dạng ưa thích là XML (SonarJava 5.12 trở lên). Giải pháp này rất đơn giản và tương tự như giải pháp trước đây với các báo cáo * .exec trong thư mục mẹ từ chủ đề này: https://stackoverflow.com/a/15535970/4448263 .

Giả sử rằng cấu trúc dự án của chúng tôi là:

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

Bạn cần theo dõi cấu hình plugin xây dựng maven trong pom tổng hợp của dự án:

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

Sau đó, xây dựng dự án với maven:

mvn clean verify

Và đối với Sonar, bạn nên đặt thuộc tính trong GUI quản trị:

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

hoặc sử dụng dòng lệnh:

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

Sự miêu tả

Điều này tạo ra các báo cáo nhị phân cho mỗi mô-đun trong các thư mục mặc định : target/jacoco.exec. Sau đó tạo báo cáo XML cho mỗi mô-đun trong các thư mục mặc định : target/site/jacoco/jacoco.xml. Sau đó tạo một báo cáo tổng hợp cho từng mô-đun trong thư mục tùy chỉnh ${project.basedir}/../target/site/jacoco-aggregate/có liên quan đến thư mục mẹ cho mỗi mô-đun. Đối với moduleA và moduleB đây sẽ là đường dẫn chung moduleC/target/site/jacoco-aggregate/.

Vì moduleB phụ thuộc vào moduleA, moduleB sẽ được xây dựng sau cùng và báo cáo của nó sẽ được sử dụng làm báo cáo bảo hiểm tổng hợp trong Sonar cho cả hai mô-đun A và B.

Ngoài báo cáo tổng hợp, chúng tôi cần báo cáo mô-đun thông thường vì báo cáo tổng hợp JaCoCo chỉ chứa dữ liệu bảo hiểm cho các phụ thuộc.

Cùng với nhau, hai loại báo cáo này cung cấp dữ liệu bảo hiểm đầy đủ cho Sonar.

Có một hạn chế nhỏ: bạn sẽ có thể viết báo cáo trong thư mục mẹ của dự án (nên có sự cho phép). Hoặc bạn có thể đặt jacoco.skip=truethuộc tính trong pom.xml (moduleC) của dự án gốc và jacoco.skip=falsetrong các mô-đun với các lớp và kiểm tra (moduleA và 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

Là Sonar sonar.jacoco.reportPath, sonar.jacoco.itReportPathsonar.jacoco.reportPathstất cả đã bị phản đối , bạn nên sử dụng sonar.coverage.jacoco.xmlReportPathsngay bây giờ. Điều này cũng có một số tác động nếu bạn muốn cấu hình một dự án maven đa mô-đun với Sonar và Jacoco.

Như @Lonzak đã chỉ ra , kể từ Sonar 0.7.7, bạn có thể sử dụng mục tiêu báo cáo của Sonars. Chỉ cần đặt vào bạn cha mẹ pom phụ thuộc sau:

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

Vì các phiên bản hiện tại của jacoco-maven-plugin tương thích với các báo cáo xml, điều này sẽ tạo cho mọi mô-đun trong thư mục đích riêng của nó một thư mục trang web / jacoco-tổng hợp chứa một jacoco.xmltệp.

Để cho Sonar kết hợp tất cả các mô-đun, sử dụng lệnh sau:

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

Để giữ cho câu trả lời của tôi ngắn gọn và chính xác, tôi đã không đề cập đến maven-surefire-plugin maven-failsafe-pluginphụ thuộc. Bạn chỉ có thể thêm chúng mà không cần bất kỳ cấu hình nào khác:

<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

Bạn có thể gọi một tác vụ ant được gọi là merge trên maven, để đặt tất cả các tệp bảo hiểm (* .exec) trong cùng một tệp.

Nếu bạn đang chạy thử nghiệm đơn vị, hãy sử dụng gói chuẩn bị pha , nếu bạn chạy thử nghiệm tích hợp thì hãy sử dụng thử nghiệm sau tích hợp .

Trang web này có một ví dụ về cách gọi nhiệm vụ ant jacoco trong dự án maven

Bạn có thể sử dụng tập tin hợp nhất này trên sonar.


0

để kiểm tra đơn vị VÀ kiểm thử tích hợp, bạn có thể sử dụng maven-Surefire-plugin và maven-failafe-plugin với các bao gồm / loại trừ bị hạn chế. Tôi đã chơi với CDI trong khi liên lạc với sonar / jacoco, vì vậy tôi đã kết thúc dự án này:

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

Có lẽ nó giúp bạn một chút. trong tệp pom.xml của tôi, tôi sử dụng ẩn "-javaagent" bằng cách đặt tùy chọn argLine trong phần cấu hình của các trình cắm thử nghiệm được chỉ định. Rõ ràng sử dụng ANT trong các dự án MAVEN là điều mà tôi sẽ không thử, đối với tôi, nó có nhiều sự pha trộn giữa hai thế giới.

Tôi chỉ có một dự án maven mô-đun đơn, nhưng có lẽ nó giúp bạn điều chỉnh của bạn để làm việc.

lưu ý: có thể không phải tất cả các plugin maven đều là up2date, có thể một số vấn đề đã được khắc phục trong các phiên bản sau


Cảm ơn vì điều đó; Tôi sẽ xem và cho bạn biết làm thế nào nó hoạt động ra. Có thể không phải là tuần này :)
Stewart

0

Mẫu này hoạt động rất tốt đối với tôi:

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

Vui lòng cung cấp một số lời giải thích cho câu trả lời của bạn
mishsx

@mishsx Một bài viết hay để giải thích: natritmeyer.com/howto/ Kẻ
SerhatTopkaya
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.