วิธีกำหนดค่า Maven + Sonar + JaCoCo แบบหลายโมดูลเพื่อให้รายงานความครอบคลุมแบบผสาน


128

ฉันค้นหาข้อมูลนี้ขึ้นและลงทางอินเทอร์เน็ต มีจำนวนมากครึ่งคำตอบออกมีจะทำอย่างไรกับ Maven คุณสมบัติเช่นเป็น${sonar.jacoco.reportPath}หรือorg.jacoco:jacoco-maven-plugin:prepare-agentหรือการตั้งค่าด้วยmaven-surefire-plugin argLine-javaagent

บางวิธีที่ไม่มีคำตอบเหล่านี้ไม่ว่าจะเป็นของตัวเองหรือแบบรวมกันกำลังสร้างสิ่งที่ฉันต้องการ: รายงานความครอบคลุมซึ่งแสดงคลาสที่ครอบคลุมหากใช้ในการทดสอบที่สูงขึ้นในสแต็กเช่นเอนทิตีที่ใช้ โดย DAO แม้ว่าจะไม่ครอบคลุมทั้งหมดโดยการทดสอบในโมดูลของตัวเอง

มีการกำหนดค่าที่ชัดเจนอยู่ที่ไหนสักแห่งเพื่อให้บรรลุสิ่งนี้โปรด?

คำตอบ:


165

ฉันตกอยู่ในสถานการณ์เดียวกับคุณคำตอบครึ่งหนึ่งที่กระจัดกระจายไปทั่วอินเทอร์เน็ตนั้นค่อนข้างน่ารำคาญเนื่องจากดูเหมือนว่ามีหลายคนที่มีปัญหาเดียวกัน แต่ไม่มีใครสามารถอธิบายได้อย่างเต็มที่ว่าพวกเขาแก้ไขอย่างไร

เอกสาร Sonarอ้างถึง โครงการ 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 ใช้รายงานซ้ำที่รันด้วยตนเองแทนที่จะกลิ้งของตัวเอง เราเพียงแค่ต้องทำให้ jacoco-maven-plugin ทำงานสำหรับโมดูลย่อยทั้งหมดโดยวางสิ่งนี้ใน pom หลักภายใน 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>

destFileวางไฟล์รายงานไว้ในตำแหน่งที่ Sonar จะค้นหาและappendทำให้ไฟล์นั้นต่อท้ายไฟล์แทนที่จะเขียนทับ ซึ่งจะรวมรายงาน JaCoCo สำหรับโมดูลย่อยทั้งหมดไว้ในไฟล์เดียวกัน

Sonar จะดูไฟล์นั้นสำหรับแต่ละโมดูลย่อยเนื่องจากนั่นคือสิ่งที่เราชี้ให้เขาเห็นด้านบนทำให้เรามีผลการทดสอบหน่วยรวมสำหรับไฟล์หลายโมดูลใน Sonar


มหัศจรรย์! สิ่งนี้ได้ผล ที่สุด! ฉันคิดว่าเวทมนตร์ที่ขาดหายไปในคาถาสำคัญที่ฉันขาดหายไปนั้น <append> จริง </append>
Stewart

มันได้ผล! ฉันต้องทำใหม่mvn packageก่อนที่จะเรียกใช้mvn sonar:sonarเพื่อรับเส้นทางรายงานใหม่ที่สร้างขึ้น
thomasa88

2
ตามตัวอย่างควรใช้พร็อพเพอร์ตี้ "sonar.jacoco.itReportPath" เพื่อให้ได้ผลลัพธ์ที่รวมเป็น "การครอบคลุมโค้ดโดยรวม" โปรดอัปเดตคำตอบ
Yves Martin

4
"sonar.dynamicAnalysis" เลิกใช้แล้วเช่นกัน: docs.sonarqube.org/display/SONAR/Release+4.3+Upgrade+Notes
Yves Martin

3
อัปเดตลิงค์: docs.sonarqube.org/display/SONARQUBE53/…
Lonzak

23

คำถามที่พบบ่อย

คำถามจากหัวของฉันตั้งแต่ตอนนั้นฉันก็คลั่งไคล้จาโคโค่

แอปพลิเคชันเซิร์ฟเวอร์ของฉัน (jBoss, Glassfish .. ) ตั้งอยู่ในอิรักซีเรียอะไรก็ได้ .. เป็นไปได้ไหมที่จะได้รับการครอบคลุมหลายโมดูลเมื่อทำการทดสอบการรวมกับมัน? Jenkins และ Sonar อยู่บนเซิร์ฟเวอร์ที่แตกต่างกัน

ใช่. คุณต้องใช้ตัวแทน jacocoที่ทำงานในโหมดoutput=tcpserverjacoco ant lib โดยทั่วไปสองjarวินาที สิ่งนี้จะทำให้คุณประสบความสำเร็จ 99%

ตัวแทนจาโคโคทำงานอย่างไร?

คุณต่อท้ายสตริง

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

ไปยังแอ็พพลิเคชันเซิร์ฟเวอร์ JAVA_OPTS ของคุณแล้วรีสตาร์ท ในสตริงนี้[your_path]จะต้องถูกแทนที่ด้วยพา ธ ไปยัง jacocoagent.jar ที่จัดเก็บ (เก็บไว้!) บน VM ของคุณที่เซิร์ฟเวอร์แอปทำงาน ตั้งแต่เวลานั้นคุณเริ่มเซิร์ฟเวอร์แอปแอปพลิเคชันทั้งหมดที่ปรับใช้จะได้รับการตรวจสอบแบบไดนามิกและกิจกรรม (หมายถึงการใช้รหัส) จะพร้อมให้คุณรับในรูปแบบ jacocos .exec ตามคำขอ tcl

ฉันสามารถรีเซ็ต jacoco agent เพื่อเริ่มรวบรวมข้อมูลการดำเนินการนับตั้งแต่เวลาเริ่มการทดสอบได้หรือไม่

ใช่เพื่อจุดประสงค์นั้นคุณต้องใช้ jacocoant.jar และสคริปต์สร้างมดที่อยู่ในพื้นที่ทำงานเจนกินส์ของคุณ

โดยพื้นฐานแล้วสิ่งที่ฉันต้องการจาก http://www.eclemma.org/jacoco/ คือ jacocoant.jar ที่อยู่ในพื้นที่ทำงานเจนกินส์ของฉันและ jacocoagent.jar ที่อยู่บน VM เซิร์ฟเวอร์แอปของฉัน

ถูกตัอง.

ฉันไม่ต้องการใช้มดฉันได้ยินมาว่าปลั๊กอิน jacoco maven สามารถทำทุกอย่างได้เช่นกัน

ไม่ถูกต้องปลั๊กอิน jacoco maven สามารถรวบรวมข้อมูลการทดสอบหน่วยและข้อมูลการทดสอบการรวมบางอย่าง (ดูArquillian Jacoco ) แต่ถ้าคุณมีตัวอย่างเช่นโปรดมั่นใจว่าการทดสอบเป็นโครงสร้างแยกต่างหากในเจนกินส์และต้องการแสดงการครอบคลุมหลายโมดูลฉันทำได้ ไม่เห็นว่าปลั๊กอิน maven สามารถช่วยคุณได้อย่างไร

ตัวแทนจาโคโคผลิตอะไรกันแน่?

ครอบคลุมเฉพาะข้อมูลใน.execรูปแบบ Sonar ก็สามารถอ่านได้

จาโคโคจำเป็นต้องรู้หรือไม่ว่าชั้นเรียนจาวาของฉันอยู่ที่ไหน?

ไม่โซนาร์ทำ แต่ไม่ใช่จาโคโค่ เมื่อคุณทำmvn sonar:sonarเส้นทางสู่ชั้นเรียนเข้ามามีบทบาท

แล้วบทมดล่ะ?

จะต้องถูกนำเสนอในพื้นที่ทำงานของเจนกินส์ ฉันเรียกมันว่าสคริปต์มดฉันเรียกมันjacoco.xmlว่า:

<project name="Jacoco library to collect code coverage remotely" xmlns:jacoco="antlib:org.jacoco.ant">
    <property name="jacoco.port" value="6300"/>
    <property name="jacocoReportFile" location="${workspace}/it-jacoco.exec"/>

    <taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
        <classpath path="${workspace}/tools/jacoco/jacocoant.jar"/>
    </taskdef>

    <target name="jacocoReport">
            <jacoco:dump address="${jacoco.host}" port="${jacoco.port}" dump="true" reset="true" destfile="${jacocoReportFile}" append="false"/>
    </target>

    <target name="jacocoReset">
            <jacoco:dump address="${jacoco.host}" port="${jacoco.port}" reset="true" destfile="${jacocoReportFile}" append="false"/>
        <delete file="${jacocoReportFile}"/>
    </target>
</project>

พารามิเตอร์บังคับสองตัวที่คุณควรส่งผ่านเมื่อเรียกใช้สคริปต์นี้ -Dworkspace=$WORKSPACE ใช้เพื่อชี้ไปที่พื้นที่ทำงานเจนกินส์และ-Djacoco.host=yourappserver.comโฮสต์ที่ไม่มีhttp://

โปรดสังเกตด้วยว่าฉันใส่ไว้jacocoant.jarที่ $ {workspace} /tools/jacoco/jacocoant.jar

ควรทำอย่างไรต่อไป

คุณเริ่มเซิร์ฟเวอร์แอปด้วย jacocoagent.jar หรือไม่

คุณใส่ ant script และ jacocoant.jar ไว้ในพื้นที่ทำงานของเจนกินส์หรือไม่?

ถ้าใช่ขั้นตอนสุดท้ายคือกำหนดค่าการสร้างเจนกินส์ นี่คือกลยุทธ์:

  1. เรียกใช้เป้าหมายมดjacocoResetเพื่อรีเซ็ตข้อมูลที่รวบรวมไว้ก่อนหน้านี้ทั้งหมด
  2. ทำการทดสอบของคุณ
  3. เรียกใช้เป้าหมายมดjacocoReportเพื่อรับรายงาน

หากทุกอย่างถูกต้องคุณจะเห็นit-jacoco.execในพื้นที่ทำงานบิลด์ของคุณ

ดูภาพหน้าจอฉันได้antติดตั้งในพื้นที่ทำงานของฉันใน$WORKSPACE/tools/antdir แล้ว แต่คุณสามารถใช้ภาพที่ติดตั้งในเจนกินส์ของคุณได้

ใส่คำอธิบายภาพที่นี่

จะส่งรายงานนี้ในโซนาร์ได้อย่างไร?

Maven sonar:sonarจะทำงาน (อย่าลืมกำหนดค่า) ชี้ไปที่ pom.xml หลักเพื่อให้ทำงานผ่านโมดูลทั้งหมด ใช้sonar.jacoco.itReportPath=$WORKSPACE/it-jacoco.execพารามิเตอร์เพื่อบอกโซนาร์ว่ารายงานการทดสอบการรวมของคุณอยู่ที่ใด it-jacoco.execทุกครั้งที่มันจะวิเคราะห์ชั้นเรียนโมดูลใหม่ก็จะหาข้อมูลเกี่ยวกับความคุ้มครองใน

ฉันมี jacoco.exec อยู่แล้วใน "target" dir ของฉันโซนาร์ `mvn: sonar` ละเว้น / ลบออก

โดยค่าเริ่มต้นmvn sonar:sonarจะทำcleanและลบ dir เป้าหมายของคุณให้ใช้sonar.dynamicAnalysis=reuseReportsเพื่อหลีกเลี่ยง


20

วิธีใหม่ตั้งแต่รุ่น 0.7.7

เนื่องจากเวอร์ชัน 0.7.7 มีวิธีใหม่ในการสร้างรายงานรวม:

คุณสร้างโครงการ 'รายงาน' แยกต่างหากซึ่งรวบรวมรายงานที่จำเป็นทั้งหมด (เป้าหมายใด ๆ ในโปรเจ็กต์ตัวรวบรวมจะถูกดำเนินการก่อนโมดูลจึงไม่สามารถใช้งานได้)

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

ราก pomลักษณะเช่นนี้ (อย่าลืมที่จะเพิ่มโมดูลรายงานใหม่ภายใต้โมดูล):

<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 จากโมดูลรายงานมีลักษณะดังนี้:

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

exmple เต็มสามารถพบได้ที่นี่


3
นี้ได้ผล รายงานรวมจะแสดงความครอบคลุมของรหัสสะสมสำหรับโมดูลทั้งหมด คุณเคยลองดูรายงานสะสมนี้ใน Sonar หรือไม่? ฉันใช้ sonar-qube เพื่ออ่าน jacoco.exec สำหรับแต่ละรายงาน แต่ด้วยการรวมรายงานนี้ฉันไม่เห็น jacoco.exec แบบรวมในโมดูลรายงาน
Swetha V

@SwethaV ประสบความสำเร็จในเรื่องนี้หรือไม่? เราอยู่ในตำแหน่งเดียวกันและต้องหาวิธีสร้างผู้บริหารแบบรวม :)
Vinky

เราใช้ sonar qube เวอร์ชัน 6.X ซึ่งมีหน้าครอบคลุมการทดสอบของตัวเองดังนั้นฉันไม่ต้องการ jacoco ในนั้น สำหรับเวอร์ชันเก่าเราได้ติดตั้งปลั๊กอิน cobertura ซึ่งมีฟังก์ชันนี้ด้วย ...
Lonzak

12

ฉันจะโพสต์วิธีแก้ปัญหาของฉันเนื่องจากมันแตกต่างจากที่อื่นอย่างละเอียดและยังต้องใช้เวลาหนึ่งวันในการทำให้ถูกต้องด้วยความช่วยเหลือของคำตอบที่มีอยู่

สำหรับโครงการ Maven แบบหลายโมดูล:

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

โดยที่WARโปรเจ็กต์เป็นเว็บแอปหลักLIB1 และ 2 เป็นโมดูลเพิ่มเติมWARขึ้นอยู่กับและTESTเป็นที่ที่การทดสอบการรวมอยู่ TESTหมุนอินสแตนซ์ Tomcat แบบฝัง (ไม่ใช่ผ่านปลั๊กอิน Tomcat) และรันWARโปรเจ็กต์และทดสอบผ่านชุดการทดสอบ JUnit WARและLIBโครงการทั้งสองมีการทดสอบหน่วยของตัวเอง

ผลลัพธ์ของทั้งหมดนี้คือการรวมและความครอบคลุมการทดสอบหน่วยที่แยกออกจากกันและสามารถแยกแยะได้ใน 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 และTEST pom.xmlจะได้รับมรดกดำเนินการที่ JaCoCo ปลั๊กอิน

TEST pom.xml

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.19.1</version>
    <executions>
        <execution>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
            <configuration>
                <skipTests>${skip.tests}</skipTests>
                <argLine>${argLine} -Duser.timezone=UTC -Xms256m -Xmx256m</argLine>
                <includes>
                    <includes>**/*Test*</includes>
                </includes>
            </configuration>
        </execution>
    </executions>
</plugin>

ฉันยังพบว่าบล็อกโพสต์ของ Petri Kainulainens 'การสร้างรายงานการครอบคลุมรหัสสำหรับหน่วยและการทดสอบการรวมระบบด้วยปลั๊กอิน JaCoCo Maven'มีประโยชน์สำหรับด้านการตั้งค่า JaCoCo ของสิ่งต่างๆ


ฉันต้องการอัปเดตโพสต์นี้ในบางขั้นตอนเนื่องจากเป็นเรื่องที่ไม่เหมาะสมเล็กน้อย agent-for-itมีความจำเป็นเฉพาะเมื่อรันการทดสอบในTESTโมดูล แต่การกำหนดค่าปัจจุบันทำงานสำหรับโมดูลอื่น ๆ ทั้งหมดโดยที่ไม่มีค่า การปรับปรุงจะต้องagent-for-utทำงานในโมดูลอื่น ๆ ทั้งหมดและagent-for-itทำงานในTESTเท่านั้น
markdsievers

8

มีวิธีที่จะทำให้สำเร็จได้ ความมหัศจรรย์คือการสร้างไฟล์ 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>

หากคุณเพิ่มโปรไฟล์นี้ในพ่อแม่ของคุณและโทรหาmvn clean install sonar:sonar -DrunSonarคุณจะได้รับความคุ้มครองที่สมบูรณ์

maven.multiModuleProjectDirectoryความมหัศจรรย์ที่นี่คือ โฟลเดอร์นี้เป็นโฟลเดอร์ที่คุณเริ่มสร้าง maven เสมอ


สิ่งนี้ใช้ได้ผลสำหรับฉันหลังจากผ่านวิธีแก้ปัญหาอื่น ๆ อีกมากมาย
Jimson Kannanthara James

ปัญหาเดียวคือฉันต้องเรียกใช้โซนาร์ด้วยคำสั่งmvn org.sonarsource.scanner.maven:sonar-maven-plugin:3.4.0.905:sonar -DrunSonarเนื่องจากA required class was missing while executing org.sonarsource.scanner.maven:sonar-maven-plugin:3.0.1:sonar: org/sonar/batch/bootstrapper/IssueListenerข้อผิดพลาด
Jimson Kannanthara James

1
อย่าใช้เวทมนตร์นี้ คุณสมบัติที่ระบุเป็นรายละเอียดการดำเนินการและจะไม่ต้องพึ่งพา - The Maven Developer Team
Michael-O

6

การกำหนดค่าที่ฉันใช้ใน pom ระดับแม่ของฉันซึ่งฉันมีขั้นตอนการทดสอบหน่วยและการรวมแยกกัน

ฉันกำหนดค่าคุณสมบัติต่อไปนี้ในคุณสมบัติ POM หลัก

    <maven.surefire.report.plugin>2.19.1</maven.surefire.report.plugin>
    <jacoco.plugin.version>0.7.6.201602180812</jacoco.plugin.version>
    <jacoco.check.lineRatio>0.52</jacoco.check.lineRatio>
    <jacoco.check.branchRatio>0.40</jacoco.check.branchRatio>
    <jacoco.check.complexityMax>15</jacoco.check.complexityMax>
    <jacoco.skip>false</jacoco.skip>
    <jacoco.excludePattern/>
    <jacoco.destfile>${project.basedir}/../target/coverage-reports/jacoco.exec</jacoco.destfile>

    <sonar.language>java</sonar.language>
    <sonar.exclusions>**/generated-sources/**/*</sonar.exclusions>
    <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
    <sonar.coverage.exclusions>${jacoco.excludePattern}</sonar.coverage.exclusions>
    <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
    <sonar.jacoco.reportPath>${project.basedir}/../target/coverage-reports</sonar.jacoco.reportPath>

    <skip.surefire.tests>${skipTests}</skip.surefire.tests>
    <skip.failsafe.tests>${skipTests}</skip.failsafe.tests>

ฉันวางคำจำกัดความของปลั๊กอินไว้ภายใต้การจัดการปลั๊กอิน

โปรดทราบว่าฉันกำหนดคุณสมบัติสำหรับอาร์กิวเมนต์ surefire (surefireArgLine) และ failafe (failafeArgLine) เพื่ออนุญาตให้ jacoco กำหนดค่า javaagent ให้ทำงานกับการทดสอบแต่ละครั้ง

ภายใต้ pluginManagement

  <build>
     <pluginManagment>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <fork>true</fork>
                    <meminitial>1024m</meminitial>
                    <maxmem>1024m</maxmem>
                    <compilerArgument>-g</compilerArgument>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.19.1</version>
                <configuration>
                    <forkCount>4</forkCount>
                    <reuseForks>false</reuseForks>
                    <argLine>-Xmx2048m ${surefireArgLine}</argLine>
                    <includes>
                        <include>**/*Test.java</include>
                    </includes>
                    <excludes>
                        <exclude>**/*IT.java</exclude>
                    </excludes>
                    <skip>${skip.surefire.tests}</skip>
                </configuration>
            </plugin>
            <plugin>
                <!-- For integration test separation -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.19.1</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.surefire</groupId>
                        <artifactId>surefire-junit47</artifactId>
                        <version>2.19.1</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <forkCount>4</forkCount>
                    <reuseForks>false</reuseForks>
                    <argLine>${failsafeArgLine}</argLine>
                    <includes>
                        <include>**/*IT.java</include>
                    </includes>
                    <skip>${skip.failsafe.tests}</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>integration-test</id>
                        <goals>
                            <goal>integration-test</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>verify</id>
                        <goals>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <!-- Code Coverage -->
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>${jacoco.plugin.version}</version>
                <configuration>
                    <haltOnFailure>true</haltOnFailure>
                    <excludes>
                        <exclude>**/*.mar</exclude>
                        <exclude>${jacoco.excludePattern}</exclude>
                    </excludes>
                    <rules>
                        <rule>
                            <element>BUNDLE</element>
                            <limits>
                                <limit>
                                    <counter>LINE</counter>
                                    <value>COVEREDRATIO</value>
                                    <minimum>${jacoco.check.lineRatio}</minimum>
                                </limit>
                                <limit>
                                    <counter>BRANCH</counter>
                                    <value>COVEREDRATIO</value>
                                    <minimum>${jacoco.check.branchRatio}</minimum>
                                </limit>
                            </limits>
                        </rule>
                        <rule>
                            <element>METHOD</element>
                            <limits>
                                <limit>
                                    <counter>COMPLEXITY</counter>
                                    <value>TOTALCOUNT</value>
                                    <maximum>${jacoco.check.complexityMax}</maximum>
                                </limit>
                            </limits>
                        </rule>
                    </rules>
                </configuration>
                <executions>
                    <execution>
                        <id>pre-unit-test</id>
                        <goals>
                            <goal>prepare-agent</goal>
                        </goals>
                        <configuration>
                            <destFile>${jacoco.destfile}</destFile>
                            <append>true</append>
                            <propertyName>surefireArgLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>post-unit-test</id>
                        <phase>test</phase>
                        <goals>
                            <goal>report</goal>
                        </goals>
                        <configuration>
                            <dataFile>${jacoco.destfile}</dataFile>
                            <outputDirectory>${sonar.jacoco.reportPath}</outputDirectory>
                            <skip>${skip.surefire.tests}</skip>
                        </configuration>
                    </execution>
                    <execution>
                        <id>pre-integration-test</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>prepare-agent-integration</goal>
                        </goals>
                        <configuration>
                            <destFile>${jacoco.destfile}</destFile>
                            <append>true</append>
                            <propertyName>failsafeArgLine</propertyName>
                        </configuration>
                    </execution>
                    <execution>
                        <id>post-integration-test</id>
                        <phase>post-integration-test</phase>
                        <goals>
                            <goal>report-integration</goal>
                        </goals>
                        <configuration>
                            <dataFile>${jacoco.destfile}</dataFile>
                            <outputDirectory>${sonar.jacoco.reportPath}</outputDirectory>
                            <skip>${skip.failsafe.tests}</skip>
                        </configuration>
                    </execution>
                    <!-- Disabled until such time as code quality stops this tripping
                    <execution>
                        <id>default-check</id>
                        <goals>
                            <goal>check</goal>
                        </goals>
                        <configuration>
                            <dataFile>${jacoco.destfile}</dataFile>
                        </configuration>
                    </execution>
                    -->
                </executions>
            </plugin>
            ...

และในส่วนการสร้าง

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

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

และในส่วนการรายงาน

    <reporting>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-report-plugin</artifactId>
            <version>${maven.surefire.report.plugin}</version>
            <configuration>
                <showSuccess>false</showSuccess>
                <alwaysGenerateFailsafeReport>true</alwaysGenerateFailsafeReport>
                <alwaysGenerateSurefireReport>true</alwaysGenerateSurefireReport>
                <aggregate>true</aggregate>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco.plugin.version}</version>
            <configuration>
                <excludes>
                    <exclude>**/*.mar</exclude>
                    <exclude>${jacoco.excludePattern}</exclude>
                </excludes>
            </configuration>
        </plugin>
     </plugins>
  </reporting>

1
ฉันเห็นว่าคุณมีการกำหนดค่า<append>true</append>ภายใต้prepare-agentส่วน ...
สจ๊วต

ความสำคัญ อ่านความคิดเห็นของฉันเพื่อหาคำตอบอื่น มันเป็นส่วนประกอบสำคัญที่ขาดหายไปสำหรับฉันไม่พบในเอกสารอื่น ๆ
Stewart

คุณมีลิงค์ github สำหรับสิ่งนี้หรือไม่? ฉันต้องการทำคอนฟิกที่คล้ายกัน
Rohit Kasat

@Rhit - ไม่ฉันไม่ทำอย่างน้อยก็ไม่ได้อยู่ในที่เก็บสาธารณะ
sweetfa

สิ่งนี้ใช้ได้ดีกับ Sonar Qube เวอร์ชัน 6.5 (build 27846) ... : D การครอบคลุมโค้ดจะแสดงอย่างถูกต้อง
udoline

4

ฉันพบโซลูชันอื่นสำหรับ Sonar เวอร์ชันใหม่ที่เลิกใช้รูปแบบรายงานไบนารีของ JaCoCo (* .exec) และรูปแบบที่ต้องการคือ XML (SonarJava 5.12 ขึ้นไป) การแก้ปัญหาคือง่ายมากและคล้ายกับวิธีการแก้ปัญหาก่อนหน้านี้มีรายงาน .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

คุณต้องติดตามการกำหนดค่าปลั๊กอินสร้าง maven ใน pom ของโครงการรวม:

<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 โมดูล B จะถูกสร้างขึ้นเป็นลำดับสุดท้ายและรายงานจะถูกใช้เป็นรายงานความครอบคลุมรวมในโซนาร์สำหรับทั้งโมดูล A และ B

นอกเหนือจากรายงานรวมแล้วเรายังต้องการรายงานโมดูลปกติเนื่องจากรายงานรวม JaCoCo มีข้อมูลความครอบคลุมสำหรับการอ้างอิงเท่านั้น

รายงานทั้งสองประเภทนี้จะให้ข้อมูลครอบคลุมทั้งหมดสำหรับ Sonar

มีข้อ จำกัด เล็กน้อย: คุณควรจะเขียนรายงานในไดเร็กทอรีหลักของโปรเจ็กต์ได้ (ควรได้รับอนุญาต) หรือคุณสามารถตั้งค่าคุณสมบัติjacoco.skip=trueใน pom.xml (moduleC) ของโปรเจ็กต์และjacoco.skip=falseในโมดูลที่มีคลาสและการทดสอบ (moduleA และ moduleB)


3

ในฐานะที่เป็น sonars sonar.jacoco.reportPath, sonar.jacoco.itReportPathและsonar.jacoco.reportPathsได้รับการเลิกคุณควรใช้sonar.coverage.jacoco.xmlReportPathsในขณะนี้ นอกจากนี้ยังมีผลกระทบบางอย่างหากคุณต้องการกำหนดค่าโครงการ maven หลายโมดูลด้วย Sonar และ Jacoco

ดังที่ @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 สิ่งนี้จะสร้างขึ้นสำหรับทุกโมดูลในโฟลเดอร์เป้าหมายของตัวเองซึ่งเป็นโฟลเดอร์ site / jacoco-aggregate ที่มีjacoco.xmlไฟล์

ในการให้ 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>

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>             

1

คุณสามารถเรียกงานมดที่เรียกว่าmerge on maven เพื่อรวมไฟล์ความครอบคลุมทั้งหมด (* .exec) เข้าด้วยกันในไฟล์เดียวกัน

หากคุณกำลังเรียกใช้การทดสอบหน่วยใช้ขั้นตอนการเตรียมความพร้อมแพคเกจถ้าคุณเรียกใช้การทดสอบบูรณาการเพื่อให้การใช้งานโพสต์บูรณาการการทดสอบ

ไซต์นี้มีตัวอย่างวิธีการเรียกงาน jacoco ant ในโครงการ maven

คุณสามารถใช้ไฟล์ที่ผสานนี้บนโซนาร์


1

เพื่อให้มีการทดสอบหน่วยและการทดสอบการรวมคุณสามารถใช้ maven-surefire-plugin และ maven-failafe-plugin ที่มีการรวม / ไม่รวมที่ จำกัด ฉันเล่นกับ CDI ในขณะที่ติดต่อกับ sonar / jacoco ดังนั้นฉันจึงลงเอยในโครงการนี้:

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

บางทีมันอาจช่วยคุณได้เล็กน้อย ใน pom.xml ของฉันฉันใช้ "-javaagent" โดยปริยายโดยการตั้งค่าตัวเลือก argLine ในส่วนการกำหนดค่าของปลั๊กอินการทดสอบที่ระบุ การใช้ ANT อย่างชัดเจนในโครงการ MAVEN เป็นสิ่งที่ฉันจะไม่ลองสำหรับฉันมันเป็นการผสมผสานระหว่างสองโลก

ฉันมีเพียงโครงการ 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.