1. 程式人生 > 其它 >測試覆蓋率工具之--02 Jacoco使用

測試覆蓋率工具之--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方法的。
  具體參見

http://www.eclemma.org/jacoco/trunk/doc/agent.html

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 抓取資訊並生成報告

  1. 在專案根目錄下新建一個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>
  1. 接著在build.xml檔案目錄下執行ant dump命令,在當前目錄下出現一個.exec字尾名結尾的檔案,出現如下圖所示的代表執行成功

  2. 生成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
【Quality】 Quality is the value to someone who matters。做測試,首先要找到這個someone是誰,以及這個 someone重視的 value是什麼。