測試覆蓋率工具之--02 Jacoco使用
Jacoco 統計的是全量程式碼覆蓋率。它不僅支援生成單元測試的覆蓋率,也支援監控生成介面測試,功能測試的覆蓋率。
一. 單元測試覆蓋率(maven 配置)
單元測試覆蓋率是在專案編譯過程中生成的。這裡以 maven 為例,有兩種實現方式
1.1 mvn命令增加引數
在執行mvn命令時,加上“org.jacoco:jacoco-maven-plugin:prepare-agent”引數即可。 示例:
mvn clean test org.jacoco:jacoco-maven-plugin:0.7.3.201502191951:prepare-agent install -Dmaven.test.failure.ignore=true
其中,jacoco-maven-plugin後面跟的是jacoco的版本; 【-Dmaven.test.failure.ignore=true】建議加上,否則如果單元測試失敗,就會直接中斷,不會產生.exec檔案
1.2 在pom檔案中新增jacoco外掛
具體的配置方法如下,也可參考:
<!-- jacoco plugin --> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.6.4.201312101107</version> <executions> <execution> <!-- 在maven的initialize階段,將Jacoco的runtime agent作為VM的一個引數 傳給被測程式,用於監控JVM中的呼叫。 --> <id>default-prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> <configuration> <destFile> ${project.build.directory}/coverage-reports/jacoco.exec </destFile> <propertyName>surefireArgLine</propertyName> </configuration> </execution> <!-- 在程式的verify階段,執行report測試的程式。 檔案的輸入為perpare-agent階段中設定或者預設的jacoco.exec. 引數 includes和excludes可用來選定report中過濾的類。 --> <execution> <id>default-report</id> <phase>test</phase> <goals> <goal>report</goal> </goals> <configuration> <dataFile>${project.build.directory}/coverage-reports/jacoco.exec</dataFile> <outputDirectory>${project.reporting.outputDirectory}/jacoco</outputDirectory> </configuration> </execution> </executions> </plugin> <!-- 使用 maven-surefire-plugin來執行單元測試。 將surefireArgLine賦值給argLine引數,以保證在測試執行時Jacoco agent處於執行狀態。 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.16</version> <configuration> <argLine>${surefireArgLine}</argLine> </configuration> </plugin> </plugins>
在執行mvn test時,即可得到對應的覆蓋率報告。
二. 動態監測 Web 專案全量覆蓋率
先來看一下 Jacoco 工作原理,如下圖所示:
來看下具體配置
2.1. 服務端設定 JacocoAgent 並使用
1. java -jar 方式啟動的專案(如springBoot)
java -javaagent:/data/webapp/jacoco/jacocoagent.jar=includes=*,output=tcpserver,append=false,address=*,port=6200 -jar xxxxxxxxxx.jar
請注意 java -jar 命令的使用方式:在jar包前面傳進去的引數是給 jvm 啟動用的,在jar包之後跟的引數是給main方法的。
具體參見
2. tomcat
我們常用的命令存在於:$CATALINA_HOME\bin下,有startup.sh和shutdown.sh,,其實這兩個只是封裝之後的指令碼,底層呼叫的都是$CATALINA_HOME\bin\catalina.sh
set JAVA_OPTS=-server -Xms1024m -Xmx1024m -XX:PermSize=512M -XX:MaxNewSize=512m -XX:MaxPermSize=512m -Djava.awt.headless=true -javaagent:D:\AutoTest\jacoco\lib\jacocoagent.jar=includes=com.hundsun.*,output=tcpserver,port=8229,address=127.0.0.1 -Xverify:none
3. weblogic
在~/bin/startWebLogic.sh下配置jacoco環境資訊
JAVA_OPTIONS="${JAVA_OPTIONS} -javaagent:/home/weblogic/Oracle/Middleware/Oracle_Home/user_projects/domains/base_domain/bin/jacoco-0.8.3/lib/jacocoagent.jar=includes=*,output=tcpserver,address=192.168.10.26,port=6200 -Xverify:none"
4. Apache Ant方式
參見 http://eclemma.org/jacoco/trunk/doc/ant.html
build.xml中,有特定的 compile 階段。請務必保證,有 debug="true" 這個配置,否則 jacoco 是無法注入的。有的時候ant專案生成的覆蓋率資料大小為0,就可以去排查下這裡。
5. Apache Maven方式(外掛啟動)
參見 http://www.eclemma.org/jacoco/trunk/doc/maven.html
注意:Export MAVEN_OPTS引數時,後續的所有mvn命令,都會帶上此引數,因此相當於每次執行mvn命令,都會嘗試啟動代理,因此可能會出現address bind already in use之類的異常丟擲。因此,我們只有在mvn tomcat7:run啟動伺服器時才需要啟動代理,其他如mvn的編譯、install命令都不需要,所以在啟動之後,把MAVEN_OPTS引數置空,或者重啟一個terminal來執行命令
2.2 啟動後執行測試(介面測試、功能測試等)
這時可以對服務端進行測試,所有調服務端介面的操作都會記錄作為程式碼覆蓋率依據。
2.3 抓取資訊並生成報告
- 在專案根目錄下新建一個build.xml檔案,檔案內容如下:
<?xml version="1.0" ?>
<project name="wftestReport" xmlns:jacoco="antlib:org.jacoco.ant" default="jacoco">
<property name="server_ip" value="10.16.55.95"/>
<property name="server_port" value="6200"/>
<!--Jacoco的安裝路徑-->
<property name="jacocoantPath" value="/data/jenkins/jacoco-0.8.4/lib/jacocoant.jar"/>
<!--最終生成.exec檔案的路徑,Jacoco就是根據這個檔案生成最終的報告的-->
<property name="jacocoexecPath" value="./jacoco/mergetest.exec"/>
<!--合併報告路徑-->
<property name="mergePath" value="./jacoco/all" />
<!--生成覆蓋率報告的路徑-->
<property name="reportfolderPath" value="./jacoco/report"/>
<!--跑的是class,標註的是原始碼?-->
<!--原始碼路徑-->
<!--可以配置多個原始碼-->
<property name="express_src" value="/data/jenkins/.jenkins/workspace/TEST_ISTP_95/svn/src/main/java/com/isoftstone"/>
<!--.class檔案路徑-->
<property name="express_class" value="/data/jenkins/.jenkins/workspace/TEST_ISTP_95/svn/target/classes/com/isoftstone"/>
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath path="${jacocoantPath}" />
</taskdef>
<!-- 1 dump任務:獲取覆蓋率exec檔案 -->
<target name="dump">
<jacoco:dump address="${server_ip}" reset="false" destfile="${jacocoexecPath}" port="${server_port}" append="true"/>
</target>
<!-- 2 合併exec檔案 -->
<!-- 獲取指定目錄下的所有 exec 檔案並將資料合併為一個exec -->
<target name="merge">
<jacoco:merge destfile="./jacoco/merged.exec">
<fileset dir="${mergePath}" includes="*.exec" />
</jacoco:merge>
</target>
<!-- 3 生成覆蓋率報告
根據前面配置的原始碼路徑和.class檔案路徑,
根據dump後,生成的.exec檔案,生成最終的html覆蓋率報告。-->
<target name="report">
<!--暫時不刪除,一旦刪除,其他兩個的報告也沒了-->
<delete dir="${reportfolderPath}" />
<mkdir dir="${reportfolderPath}" />
<jacoco:report>
<executiondata>
<file file="${jacocoexecPath}" />
</executiondata>
<structure name="JaCoCo Report">
<group name="Core">
<classfiles>
<fileset dir="${express_class}" />
</classfiles>
<sourcefiles encoding="utf-8">
<fileset dir="${express_src}" />
</sourcefiles>
</group>
</structure>
<html destdir="${reportfolderPath}" encoding="utf-8" />
<csv destfile="D:\AutoTest\JRES\codeCoverage\report.csv" />
</jacoco:report>
</target>
</project>
-
接著在build.xml檔案目錄下執行ant dump命令,在當前目錄下出現一個.exec字尾名結尾的檔案,出現如下圖所示的代表執行成功
-
生成report
【補充】JacocoAgent 說明
代理 jacocoagent.jar 是JaCoCo發行版的一部分,包含所有必需的依賴關係。可以使用以下JVM選項啟用Java代理:
-javaagent:[yourpath/]jacocoagent.jar=[option1]=[value1],[option2]=[value2]
JaCoCo代理支援的選項如下:
選項 | 描述 | 預設 |
---|---|---|
destfile | 執行資料的輸出檔案的路徑。 | jacoco.exec |
append | 如果設定為true並且執行資料檔案已經存在,則將覆蓋資料附加到現有檔案。如果設定為 false,則將替換現有的執行資料檔案。 | true |
includes | 執行分析中應包含的類名列表。列表條目以冒號(:)分隔,可以使用萬用字元(*和?)。除了效能優化或技術角落案例,通常不需要此選項。 | * (所有類) |
excludes | 應從執行分析中排除的類名稱列表。列表條目以冒號(:)分隔,可以使用萬用字元(*和?)。除了效能優化或技術角落案例,通常不需要此選項。 | 空(不排除類) |
exclclassloader | 應從執行分析中排除的類載入器名稱的列表。列表條目以冒號(:)分隔,可以使用萬用字元(*和 ?)。如果特殊框架與JaCoCo程式碼工具發生衝突,特別是無法訪問Java執行時類的類載入器,則可能需要此選項。 | sun.reflect.DelegatingClassLoader |
inclbootstrapclasses | 指定是否還應該檢測引導類載入器的類。謹慎使用此功能,需要大量包括/不包括調整。 | false |
inclnolocationclasses | 指定是否還應該檢測沒有源位置的類。通常這樣的類是在執行時產生的,例如通過模擬框架,因此在預設情況下被排除。 | false |
sessionid | 與執行資料一起寫入的會話識別符號。沒有這個引數,代理就會建立一個隨機的識別符號。 | 自動生成 |
dumponexit | 如果設定為true覆蓋資料,將在VM關閉時寫入。如果file指定了轉儲,或者輸出為tcpserver/ tcpclient 並且在虛擬機器終止時連線處於開啟狀態,則只能寫入轉儲。 | true |
output | 用於寫入覆蓋率資料的輸出方法。有效的選項是: file:在虛擬機器終止執行資料寫入destfile屬性中指定的檔案。 tcpserver:代理偵聽由address和port屬性指定的TCP埠上的傳入連線。執行資料被寫入到這個TCP連線。 tcpclient:啟動時,代理將連線到由address和port屬性指定的TCP埠。執行資料被寫入到這個TCP連線。 none:不要產生任何輸出。 請參閱下面的安全考慮。 |
file |
address | 當輸出方法為tcpserver或連線到 輸出方法時要繫結的IP地址或主機名 tcpclient。在tcpserver模式中,值“ *”使代理接受任何本地地址上的連線。 | 迴環介面 |
port | 當輸出方法是繫結的埠,tcpserver或者當輸出方法是連線的埠tcpclient。在 tcpserver模式下,埠必須可用,這意味著如果多個JaCoCo代理應該在同一臺機器上執行,則必須指定不同的埠。 | 6300 |
classdumpdir | agent所呼叫到的所有class檔案的目錄。這可以用於除錯目的,或者在動態建立類的情況下,例如當使用指令碼引擎時。 | 沒有轉儲 |
jmx | 如果設定為true代理通過名稱下的JMX 公開 功能org.jacoco:type=Runtime。請參閱下面的安全考慮。 | false |