測試覆蓋率工具之--02 Jacoco使用


Jacoco 統計的是全量代碼覆蓋率。它不僅支持生成單元測試的覆蓋率,也支持監控生成接口測試,功能測試的覆蓋率。

一. 工作原理

1.1. Jacoco 工作原理

  先來看一下 Jacoco 工作原理,如下圖所示:
Jacoco 工作原理圖

1.2. 工作步驟

  • 對Java字節碼進行插樁,有on-the-fly和offline兩種方式。
  • 執行測試用例,收集程序執行軌跡信息,支持通過dump將操作記錄從服務端傳輸到本地。
  • 數據處理器結合程序執行軌跡信息和代碼結構信息分析生成代碼覆蓋率報告。
  • 結合源碼和編譯后的文件,可以將代碼覆蓋率報告圖形化展示出來,如html,xml等文件格式。

二. Jacoco使用

2.1. Ant 項目

原文:
    JaCoCo comes with Ant tasks to launch Java programs with execution recording and for creating coverage reports from the recorded data. Execution data can be collected and managed with the tasks coverage, agent, dump and merge. Reports in different formats are created with the report task. For offline instrumentation the task instrument can be used to prepare class files.

翻譯:
  JaCoCo 附帶了Ant任務。它通過啟動帶有記錄執行功能的Java程序,來實現生成覆蓋率報告。其中任務(coverage, agent, dump and merge)用於收集和管理執行信息;任務 report 用於創建不同格式的報告。任務instrument 用於為 offline 模式 instrumentation 准備類文件。詳細說明見
  注意:build.xml中,有特定的 compile 階段。請務必保證,有 debug="true" 這個配置,否則 jacoco 是無法注入的。有的時候ant項目生成的覆蓋率數據大小為0,就可以去排查下這里。
  實例如下:

2.2. Maven 項目

  JaCoCo Maven 插件定義了了如下goals
  1. help
  2. prepare-agent
  3. prepare-agent-integration
  4. merge
  5. report
  6. report-integration
  7. report-aggregate
  8. check
  9. dump
  10. instrument
  11. restore-instrumented-classes
  注意:Export MAVEN_OPTS參數時,后續的所有mvn命令,都會帶上此參數,因此相當於每次執行mvn命令,都會嘗試啟動代理,因此可能會出現address bind already in use之類的異常拋出。因此,我們只有在mvn tomcat7:run啟動服務器時才需要啟動代理,其他如mvn的編譯、install命令都不需要,所以在啟動之后,把MAVEN_OPTS參數置空,或者重啟一個terminal來執行命令

  具體實例如下:

2.3. Java Agent

  Java Agent 只支持 on-the-fly 模式插樁,即所有類文件在加載到JVM期間獨立於應用程序框架進行內存預處理。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

2.4. 命令行界面

  JaCoCo帶有一個命令行接口,可以通過命令行執行基本操作 (jacococli.jar)。對於復雜的用途,尤其是大型項目,請使用 JaCoCo 與各種構建工具的集成。
具體命令如下。每個命令都有可選和必選參數列表。某些參數可以多次指定以提供多個值。

  • dump ------Request execution data from a JaCoCo agent running in 'tcpserver' output mode.
  • instrument------Off-line instrumentation of Java class files and JAR files.
  • merge ------Merges multiple exec files into a new one.
  • report ------Generate reports in different formats by reading exec and Java class files.
  • classinfo ------Print information about Java class files at the provided location.
  • execinfo ------Print exec file content in human readable format.
  • version

三. 動態監測 Web 項目全量覆蓋率

來看下具體配置

3.1. 服務端設置 JacocoAgent 並啟動

  1. 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方法的。

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

3.2. 執行測試(接口測試、功能測試等)

這時可以對服務端進行測試,所有調服務端接口的操作都會記錄作為代碼覆蓋率依據。

3.3. 抓取信息並生成報告

這步可以用jacococli.jar實現,也可以借助ant 或者maven。

3.3.1. 以 jacococli.jar為例

  1. 獲取exec文件
java -jar jacococli.jar dump --address 192.169.110.1 --port 2014 --destfile ./jacoco-demo.exec

使用這個命令會在我們調用方的服務上生成一個exec文件

  1. 生成report
java -jar jacococli.jar report ./jacoco-demo.exec --classfiles /Users/oukotoshuu/IdeaProjects/demo/target/classes/com  --sourcefiles /Users/oukotoshuu/IdeaProjects/demo/src/main/java --html report --xml report.xml

注意這個classfiles和sourcefiles 可以是多個,我們如果是多模塊項目通過指定代碼路徑和編譯文件路徑去分開做統計

3.3.2. 以 ant 為例

  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. 在build.xml文件目錄下運行ant report命令,生成report


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM