基于?Jenkins?+?JaCoCo?實(shí)現(xiàn)功能測(cè)試代碼覆蓋率統(tǒng)計(jì)

基于 Jenkins + JaCoCo 實(shí)現(xiàn)功能測(cè)試代碼覆蓋率統(tǒng)計(jì)

本文對(duì) JaCoCo 進(jìn)行簡(jiǎn)要介紹,并借助 Jenkins 實(shí)現(xiàn)功能測(cè)試代碼覆蓋率統(tǒng)計(jì)



使用 JaCoCo 統(tǒng)計(jì)功能測(cè)試代碼覆蓋率?

對(duì)于 JaCoCo,有所了解但又不是很熟悉。 “有所了解”指的是在 CI 實(shí)踐中已經(jīng)使用 JaCoCo 對(duì)單元測(cè)試代碼覆蓋率統(tǒng)計(jì): 當(dāng)代碼 push 到代碼倉(cāng)庫(kù)后,用 JaCoCo 進(jìn)行單元測(cè)試代碼覆蓋率統(tǒng)計(jì),并將相應(yīng)數(shù)據(jù)推送到 SonarQube。 “不是很熟”指的是應(yīng)用場(chǎng)景也僅限于此,并未進(jìn)行過(guò)多研究與實(shí)踐。


前不久,有測(cè)試同事提出,想要在實(shí)際測(cè)試時(shí),用 JaCoCo 統(tǒng)計(jì)功能測(cè)試代碼覆蓋率。 其主要目的是在經(jīng)過(guò)功能測(cè)試后,通過(guò)查看代碼覆蓋率統(tǒng)計(jì)的相關(guān)指標(biāo),增強(qiáng)對(duì)軟件質(zhì)量的信心。 經(jīng)查閱資料,證明這是可行的。


由于對(duì) JaCoCo 不甚了解,于是查閱官網(wǎng)資料對(duì) JaCoCo 進(jìn)一步了解。


進(jìn)一步了解 JaCoCo

JaCoCo,即 Java Code Coverage,是一款開(kāi)源的 Java 代碼覆蓋率統(tǒng)計(jì)工具。 它由 EclEmma 團(tuán)隊(duì)根據(jù)多年來(lái)使用和集成現(xiàn)有庫(kù)的經(jīng)驗(yàn)教訓(xùn)而創(chuàng)建。


JaCoCo 愿景

JaCoCo 應(yīng)該為基于 Java VM 的環(huán)境中的代碼覆蓋率分析提供標(biāo)準(zhǔn)技術(shù)。 重點(diǎn)是提供一個(gè)輕量級(jí)的、靈活的、文檔良好的庫(kù),以便與各種構(gòu)建和開(kāi)發(fā)工具集成。


JaCoCo 產(chǎn)品功能

指令(C0)、分支(C1)、行、方法、類(lèi)型和圈復(fù)雜度的覆蓋率分析。

基于 Java 字節(jié)碼,因此也可以在沒(méi)有源文件的情況下工作。

通過(guò)基于 Java agent 的實(shí)時(shí)檢測(cè)進(jìn)行簡(jiǎn)單集成。其他集成場(chǎng)景(如自定義類(lèi)加載器)也可以通過(guò) API 實(shí)現(xiàn)。

框架無(wú)關(guān)性:平穩(wěn)地與基于 Java VM 的應(yīng)用程序集成,比如普通 Java 程序、OSGi 框架、web 容器或 EJB 服務(wù)器。

兼容所有已發(fā)布的 Java 類(lèi)文件版本。

支持不同的 JVM 語(yǔ)言。

支持幾種報(bào)告格式( HTML、XML、CSV )。

遠(yuǎn)程協(xié)議和 JMX 控件,以便在任何時(shí)間點(diǎn)從覆蓋率 agent 請(qǐng)求執(zhí)行數(shù)據(jù) dump 。

Ant 任務(wù),用于收集和管理執(zhí)行數(shù)據(jù)并創(chuàng)建結(jié)構(gòu)化覆蓋報(bào)告。

Maven 插件,用于收集覆蓋信息并在Maven構(gòu)建中創(chuàng)建報(bào)告。

非功能特性

使用簡(jiǎn)單和與現(xiàn)有構(gòu)建腳本和工具集成。

良好的性能和最小的運(yùn)行時(shí)開(kāi)銷(xiāo),特別是對(duì)大型項(xiàng)目。

輕量級(jí)實(shí)現(xiàn),對(duì)外部庫(kù)和系統(tǒng)資源的依賴(lài)性最小。

全面的文檔。

完整文檔化的 API ( JavaDoc ) 和用于與其他工具集成的示例。

回歸測(cè)試基于 JUnit 測(cè)試用例,具有完整的功能測(cè)試覆蓋率。

對(duì) JaCoCo 可以與現(xiàn)有構(gòu)建腳本和工具進(jìn)行集成這里做進(jìn)一步說(shuō)明: 官方提供了 Java API、Java Agent 、CLI、Ant 、Maven、Eclipse 這幾種集成方式; 第三方提供了諸如與 Gradle、IDEA、Jenkins 等其它工具的集成方式。


拋開(kāi)理論,開(kāi)始實(shí)踐

JaCoCo 不僅支持統(tǒng)計(jì)本地服務(wù)的代碼覆蓋率,也支持統(tǒng)計(jì)遠(yuǎn)程服務(wù)的代碼覆蓋率。 單元測(cè)試覆蓋率統(tǒng)計(jì)就是統(tǒng)計(jì)本地服務(wù)的代碼覆蓋率,代碼和運(yùn)行的服務(wù)在一臺(tái)機(jī)器上,筆者這里通過(guò)使用 JaCoCo Maven 插件完成的。 而功能測(cè)試代碼覆蓋率統(tǒng)計(jì)則是統(tǒng)計(jì)遠(yuǎn)程服務(wù)的代碼覆蓋率,代碼和運(yùn)行的服務(wù)一般不在一臺(tái)機(jī)器上,這里需要借助 JaCoCo Java agent 實(shí)現(xiàn)。 > 備注:實(shí)際上,JaCoCo Maven 插件也使用了 JaCoCo Java agent,不過(guò)用戶(hù)不需要直接關(guān)系 Java agent 及其選項(xiàng),Maven 插件都透明地處理了。


1、下載 JaCoCo 分發(fā)包

可以從 JaCoCo 官網(wǎng)下載分發(fā)包,也可以從 Maven 倉(cāng)庫(kù)(中央倉(cāng)庫(kù)或私服)下載。 分發(fā)包的 lib 目錄下,包括以下庫(kù):


2、Java 應(yīng)用啟動(dòng)腳本添加 jacocoagent 相關(guān) JVM 參數(shù)

需要將 jacocoagent.jar 推送到部署應(yīng)用的服務(wù)器上,筆者這里用 Ansible 進(jìn)行了批量推送。 Java 應(yīng)用啟動(dòng)腳本需要加入類(lèi)似下面的 JVM 參數(shù):


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

這樣在應(yīng)用成功啟動(dòng)后,會(huì)暴露一個(gè) TCP 服務(wù),客戶(hù)端可以連接到這個(gè)服務(wù)并獲取執(zhí)行數(shù)據(jù)文件。


相關(guān)屬性說(shuō)明如下: - append:其中 append=false 表示 dump 每次會(huì)生成一個(gè)新的執(zhí)行數(shù)據(jù)文件,如果 append=true,dump 時(shí)則會(huì)將數(shù)據(jù)追加到已存在的執(zhí)行數(shù)據(jù)文件。 其中 output=tcpserver 表示 agent 監(jiān)聽(tīng)來(lái)自被 adrress 和 port 屬性指定的TCP 端口的連接,執(zhí)行數(shù)據(jù)被寫(xiě)到這個(gè)連接; - output:如果 output=tcpclient 則表示在啟動(dòng)時(shí),agent 連接到被 adrress 和 port 屬性指定的TCP 端口,執(zhí)行數(shù)據(jù)被寫(xiě)到這個(gè)連接; 如果 output=file 則表示在 JVM 終止時(shí),執(zhí)行數(shù)據(jù)被寫(xiě)到被 destfile 屬性指定的文件。output 默認(rèn)值為 file 。 - address:當(dāng) output 為 tcpserver 時(shí)綁定到的 IP 地址或主機(jī)名,或者當(dāng) output 為 tcpclient 時(shí)連接到的 IP 地址或主機(jī)名。 在 tcpserver 模式下,值為“*”導(dǎo)致代理只接受本機(jī)地址上的連接。address 默認(rèn)值為 127.0.0.1 。 - port:當(dāng) output 方式為 tcpserver 時(shí)綁定到該端口,或者當(dāng) output 方式為 tcpclient 時(shí)連接到該端口。 在 tcpserver 模式下,端口必須可用,這意味著如果多個(gè) JaCoCo agent 在同一臺(tái)機(jī)器上運(yùn)行,則必須指定不同的端口。port 默認(rèn)值為 6300 。


3、創(chuàng)建及配置 Jenkins Pipeline 任務(wù)

Jenkins 任務(wù)大致有幾個(gè)步驟:拉取代碼,構(gòu)建,dump 應(yīng)用執(zhí)行數(shù)據(jù)( jacoco.exec ),解析 JaCoCo 產(chǎn)生的 jacoco.exec 文件,然后生成覆蓋率報(bào)告(HTML 格式)。 拉取代碼這里無(wú)需多說(shuō),配置下從代碼倉(cāng)庫(kù)(SVN/Git)和分支地址就可以了,比較簡(jiǎn)單。 構(gòu)建這里用了 Jenkins Pipeline Maven Integration Plugin ,筆者這里所用的 Maven 命令是 mvn clean package -Dmaven.test.skip=true 。 dump 應(yīng)用執(zhí)行數(shù)據(jù)這里有多種方式:Ant、CLI、Maven,因?yàn)镴ava 應(yīng)用是用 Maven 構(gòu)建的,這里選擇了 Maven Jacoco Plugin。 解析 JaCoCo 產(chǎn)生的 jacoco.exec 文件,然后生成覆蓋率報(bào)告(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 覆蓋率報(bào)告,部分截圖如下:




總結(jié)

筆者所實(shí)現(xiàn)的方式并未覆蓋任何場(chǎng)景,但是大同小異,相關(guān)工具的使用詳情可以查看官網(wǎng)文檔,因?yàn)樗亲钊娴摹?筆者希望這個(gè)實(shí)踐能給有類(lèi)似訴求的同行一些參考,當(dāng)然筆者也希望能夠和大家互相交流。 同時(shí)筆者的 JaCoCo 實(shí)踐之路并未結(jié)束,可能在使用的過(guò)程中會(huì)有一些問(wèn)題需要解決, 后續(xù)也將考慮使用 Jenkins API 為需要統(tǒng)計(jì)功能測(cè)試代碼覆蓋率的 Java 應(yīng)用實(shí)例自動(dòng)生成一個(gè)對(duì)應(yīng)的 Jenkins 任務(wù), 并在 Java 應(yīng)用實(shí)例銷(xiāo)毀后,對(duì)相應(yīng)的 Jenkins 任務(wù)進(jìn)行清理等其它功能。


參考

https://www.eclemma.org/jacoco/index.html

https://www.jacoco.org/jacoco/trunk/doc/integrations.html

https://www.jacoco.org/jacoco/trunk/doc/agent.html

https://www.jacoco.org/jacoco/trunk/doc/counters.html

https://www.eclemma.org/jacoco/trunk/doc/mission.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容