1. 程式人生 > >基於 Jenkins + JaCoCo 實現功能測試程式碼覆蓋率統計

基於 Jenkins + JaCoCo 實現功能測試程式碼覆蓋率統計

本文首發於:Jenkins 中文社群

hangzhou

使用 JaCoCo 統計功能測試程式碼覆蓋率?

對於 JaCoCo,有所瞭解但又不是很熟悉。 "有所瞭解"指的是在 CI 實踐中已經使用 JaCoCo 對單元測試程式碼覆蓋率統計: 當代碼 push 到程式碼倉庫後,用 JaCoCo 進行單元測試程式碼覆蓋率統計,並將相應資料推送到 SonarQube。 "不是很熟"指的是應用場景也僅限於此,並未進行過多研究與實踐。

前不久,有測試同事提出,想要在實際測試時,用 JaCoCo 統計功能測試程式碼覆蓋率。 其主要目的是在經過功能測試後,通過檢視程式碼覆蓋率統計的相關指標,增強對軟體質量的信心。 經查閱資料,證明這是可行的。

由於對 JaCoCo 不甚瞭解,於是查閱官網資料對 JaCoCo 進一步瞭解。

進一步瞭解 JaCoCo

JaCoCo,即 Java Code Coverage,是一款開源的 Java 程式碼覆蓋率統計工具。 它由 EclEmma 團隊根據多年來使用和整合現有庫的經驗教訓而建立。

JaCoCo 願景

JaCoCo 應該為基於 Java VM 的環境中的程式碼覆蓋率分析提供標準技術。 重點是提供一個輕量級的、靈活的、文件良好的庫,以便與各種構建和開發工具整合。

JaCoCo 產品功能

  • 指令(C0)、分支(C1)、行、方法、型別和圈複雜度的覆蓋率分析。
  • 基於 Java 位元組碼,因此也可以在沒有原始檔的情況下工作。
  • 通過基於 Java agent 的實時檢測進行簡單整合。其他整合場景(如自定義類載入器)也可以通過 API 實現。
  • 框架無關性:平穩地與基於 Java VM 的應用程式整合,比如普通 Java 程式、OSGi 框架、web 容器或 EJB 伺服器。
  • 相容所有已釋出的 Java 類檔案版本。
  • 支援不同的 JVM 語言。
  • 支援幾種報告格式( HTML、XML、CSV )。
  • 遠端協議和 JMX 控制元件,以便在任何時間點從覆蓋率 agent 請求執行資料 dump 。
  • Ant 任務,用於收集和管理執行資料並建立結構化覆蓋報告。
  • Maven 外掛,用於收集覆蓋資訊並在Maven構建中建立報告。

非功能特性

  • 使用簡單和與現有構建指令碼和工具整合。
  • 良好的效能和最小的執行時開銷,特別是對大型專案。
  • 輕量級實現,對外部庫和系統資源的依賴性最小。
  • 全面的文件。
  • 完整文件化的 API ( JavaDoc ) 和用於與其他工具整合的示例。
  • 迴歸測試基於 JUnit 測試用例,具有完整的功能測試覆蓋率。

對 JaCoCo 可以與現有構建指令碼和工具進行整合這裡做進一步說明: 官方提供了 Java API、Java Agent 、CLI、Ant 、Maven、Eclipse 這幾種整合方式; 第三方提供了諸如與 Gradle、IDEA、Jenkins 等其它工具的整合方式。

拋開理論,開始實踐

JaCoCo 不僅支援統計本地服務的程式碼覆蓋率,也支援統計遠端服務的程式碼覆蓋率。 單元測試覆蓋率統計就是統計本地服務的程式碼覆蓋率,程式碼和執行的服務在一臺機器上,筆者這裡通過使用 JaCoCo Maven 外掛完成的。 而功能測試程式碼覆蓋率統計則是統計遠端服務的程式碼覆蓋率,程式碼和執行的服務一般不在一臺機器上,這裡需要藉助 JaCoCo Java agent 實現。

備註:實際上,JaCoCo Maven 外掛也使用了 JaCoCo Java agent,不過使用者不需要直接關係 Java agent 及其選項,Maven 外掛都透明地處理了。

1、下載 JaCoCo 分發包

可以從 JaCoCo 官網下載分發包,也可以從 Maven 倉庫(中央倉庫或私服)下載。 分發包的 lib 目錄下,包括以下庫:

2、Java 應用啟動指令碼新增 jacocoagent 相關 JVM 引數

需要將 jacocoagent.jar 推送到部署應用的伺服器上,筆者這裡用 Ansible 進行了批量推送。 Java 應用啟動指令碼需要加入類似下面的 JVM 引數:

JAVA_OPTS="$JAVA_OPTS -javaagent:/path/jacocoagent.jar=includes=*,output=tcpserver,append=false,address=$IP,port=$JACOCO_PORT"

這樣在應用成功啟動後,會暴露一個 TCP 服務,客戶端可以連線到這個服務並獲取執行資料檔案。

相關屬性說明如下:

  • append:其中 append=false 表示 dump 每次會生成一個新的執行資料檔案,如果 append=true,dump 時則會將資料追加到已存在的執行資料檔案。 其中 output=tcpserver 表示 agent 監聽來自被 adrress 和 port 屬性指定的TCP 埠的連線,執行資料被寫到這個連線;
  • output:如果 output=tcpclient 則表示在啟動時,agent 連線到被 adrress 和 port 屬性指定的TCP 埠,執行資料被寫到這個連線; 如果 output=file 則表示在 JVM 終止時,執行資料被寫到被 destfile 屬性指定的檔案。output 預設值為 file 。
  • address:當 output 為 tcpserver 時繫結到的 IP 地址或主機名,或者當 output 為 tcpclient 時連線到的 IP 地址或主機名。 在 tcpserver 模式下,值為“*”導致代理只接受本機地址上的連線。address 預設值為 127.0.0.1 。
  • port:當 output 方式為 tcpserver 時繫結到該埠,或者當 output 方式為 tcpclient 時連線到該埠。 在 tcpserver 模式下,埠必須可用,這意味著如果多個 JaCoCo agent 在同一臺機器上執行,則必須指定不同的埠。port 預設值為 6300 。

3、建立及配置 Jenkins Pipeline 任務

Jenkins 任務大致有幾個步驟:拉取程式碼,構建,dump 應用執行資料( jacoco.exec ),解析 JaCoCo 產生的 jacoco.exec 檔案,然後生成覆蓋率報告(HTML 格式)。 拉取程式碼這裡無需多說,配置下從程式碼倉庫(SVN/Git)和分支地址就可以了,比較簡單。 構建這裡用了 Jenkins Pipeline Maven Integration Plugin ,筆者這裡所用的 Maven 命令是 mvn clean package -Dmaven.test.skip=true 。 dump 應用執行資料這裡有多種方式:Ant、CLI、Maven,因為Java 應用是用 Maven 構建的,這裡選擇了 Maven Jacoco Plugin。 解析 JaCoCo 產生的 jacoco.exec 檔案,然後生成覆蓋率報告(HTML 格式)筆者這裡使用了 Jenkins Jacoco Plugin。

Jenkins Pipeline 案例如下:

pipeline {
    agent any
    tools {
        jdk 'JDK1.8'
    }
    stages {
        stage('Checkout'){
            steps{
                git branch: '${GIT_BRANCH}', credentialsId: 'xxx-xxx-xx-xx-xxx', url: '${GIT_URL}'
            }
        }
        stage('Build') {
            steps{
                withMaven(maven: 'maven'){
                      sh "mvn clean package -Dmaven.test.skip=true"
                }
            }
        }
        stage('DumpFromServer'){
            steps {
                withMaven(maven: 'maven'){
                      sh 'mvn org.jacoco:jacoco-maven-plugin:0.8.4:dump -Djacoco.address=${SERVER_IP} -Djacoco.port=${JACOCO_PORT}'
                }
            }
        }
        stage('JacocoPublisher') {
            steps {
                 jacoco()
            }
        }
    }
}

JaCoCo 覆蓋率報告,部分截圖如下:

coverage-summary

總結

筆者所實現的方式並未覆蓋任何場景,但是大同小異,相關工具的使用詳情可以檢視官網文件,因為它是最全面的。 筆者希望這個實踐能給有類似訴求的同行一些參考,當然筆者也希望能夠和大家互相交流。 同時筆者的 JaCoCo 實踐之路並未結束,可能在使用的過程中會有一些問題需要解決, 後續也將考慮使用 Jenkins API 為需要統計功能測試程式碼覆蓋率的 Java 應用例項自動生成一個對應的 Jenkins 任務, 並在 Java 應用例項銷燬後,對相應的 Jenkins 任務進行清理等其它功能。

參考