偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

vivo 基于 JaCoCo 的測試覆蓋率設(shè)計與實踐

開發(fā)
本文主要介紹vivo內(nèi)部研發(fā)平臺使用JaCoCo實現(xiàn)測試覆蓋率的實踐,包括JaCoCo原理介紹以及在實踐過程中遇到的新增代碼覆蓋率統(tǒng)計問題和頻繁發(fā)布導(dǎo)致覆蓋率丟失問題的解決辦法。

作者|vivo 互聯(lián)網(wǎng)服務(wù)器團隊- Xu Shen

本文主要介紹vivo內(nèi)部研發(fā)平臺使用JaCoCo實現(xiàn)測試覆蓋率的實踐,包括JaCoCo原理介紹以及在實踐過程中遇到的新增代碼覆蓋率統(tǒng)計問題和頻繁發(fā)布導(dǎo)致覆蓋率丟失問題的解決辦法。

一、為什么需要測試覆蓋率

1.1 在日常研發(fā)過程中,經(jīng)常發(fā)現(xiàn)一些問題

  • 測試案例的設(shè)計憑經(jīng)驗,當研發(fā)一個新功能時,經(jīng)常對測試場景估計不足,到上線后發(fā)現(xiàn)bug;
  • 開發(fā)經(jīng)常做一些需求之外的代碼變更(代碼小范圍內(nèi)重構(gòu)或在開發(fā)過程中發(fā)現(xiàn)小缺陷隨手改掉),導(dǎo)致測試任務(wù)無法測試到對應(yīng)的場景,引起線上問題;

  • 對測試效果無法量化考核,導(dǎo)致測試工作的質(zhì)量無法進一步提升。

1.2. 有沒有技術(shù)手段能夠盡可能的避免上面的問題呢?

在業(yè)內(nèi)已經(jīng)在普遍使用代碼覆蓋率來提升測試質(zhì)量,那什么是代碼覆蓋率?

代碼覆蓋率是軟件測試中的一種度量,描述程序中源代碼被測試的比例和程度,所得比例稱為代碼覆蓋率 。

代碼覆蓋率指標通常包含下面幾類:

  • 函數(shù)/方法覆蓋率:函數(shù)/方法中有多少被調(diào)用到
  • 分支覆蓋率:有多少控制結(jié)構(gòu)的分支(例如if語句)被執(zhí)行
  • 條件覆蓋率:有多少布爾子表達式被測試為真值和假值
  • 行覆蓋率:有多少行的源代碼被測試過

1.3 在使用測試覆蓋率的過程中,經(jīng)常發(fā)現(xiàn)的場景

  • if/else語句中,if{}內(nèi)的代碼被覆蓋到,else{}內(nèi)的代碼沒有被覆蓋到,可以得出部分分支場景沒有測試到;
  • try/catch語句中,try{}內(nèi)的代碼被覆蓋到,catch{}內(nèi)的代碼沒有被覆蓋到,可以得出異常場景沒有測試到;
  • if (條件1 || 條件2 || 條件3)語句中,條件1被覆蓋到,條件2和條件3沒有被覆蓋到,可以得出部分條件場景沒有測試到;

 測試人員對代碼覆蓋率的指標正確使用,能有效提升測試的質(zhì)量,進而提升版本的上線質(zhì)量。

二、JaCoCo在測試覆蓋率場景中的使用

2.1  JaCoCo介紹

當前主流的代碼覆蓋率工具:   

  • C/C++→Gcov ,Java→JaCoCo,JavaScript→ Istanbul。
  • 考慮到服務(wù)器端主要是Java語言,所以CICD平臺優(yōu)先使用JaCoCo來支持 Java 語言的代碼覆蓋率統(tǒng)計能力。
  • 通過JaCoCo官網(wǎng),我們可以看到JaCoCo的使命是為Java VM 的環(huán)境中的代碼覆蓋分析提供標準技術(shù)。重點是提供一個輕量級、靈活且有據(jù)可查的庫,用于與各種構(gòu)建和開發(fā)工具集成。

2.2 JaCoCo優(yōu)點

  • JaCoCo支持指令(C0)、分支(C1)、行、方法、類和圈復(fù)雜度等多維度的覆蓋分析;
  • 基于 Java 字節(jié)碼,也可以在沒有源文件的情況下工作;
  • 性能良好,運行時開銷很小,尤其是對于大型項目;
  • 比較完整的API,很方便與其他工具進行集成;
  • 遠程協(xié)議和 JMX 控制可在任何時間點從代理請求執(zhí)行數(shù)據(jù)下載。

2.3 JaCoCo原理

主要來自于JaCoCo官方網(wǎng)站

JaCoCo支持幾種不同的方法來收集覆蓋信息,對于每種方法,由不同技術(shù)實現(xiàn)的,下圖橙色路徑部分是JaCoCo 推薦使用的方式,即通過On-The-Fly方式收集覆蓋率信息:

圖片

通過上圖我們知道,JaCoCo 是通過對Java字節(jié)碼(Byte Code)插入探針的方式來收集覆蓋率信息的,探針是可以插入現(xiàn)有指令之間的附加指令。它們不會改變方法的行為,但會記錄它們已被執(zhí)行的事實。

下面以一段簡單的  程序為例進行說明:

圖片

這段代碼經(jīng)過Java編譯以后轉(zhuǎn)化為以下字節(jié)碼:

圖片

因為Java 字節(jié)碼指令的線性序列,控制流是通過條件或無條件指令實現(xiàn)跳轉(zhuǎn)的,跳轉(zhuǎn)目標在技術(shù)上是相對于目標指令的偏移量。這個跟大學(xué)學(xué)習(xí)的匯編指令的跳轉(zhuǎn)方式類似,為了更好的可讀性,使用符號標簽 (L1,L2 ) 代替實際的指令地址。

圖片

上圖中橙色的部分為插入的探針,理論上我們可以在控制流圖的每個邊緣插入一個探針,由于探針實現(xiàn)本身需要一些字節(jié)碼指令,這將會使類文件的大小增加數(shù)倍;幸運的是,這不是必需的,實際上我們只需要根據(jù)方法的控制流為每個方法插入幾個探針。例如,沒有任何分支的方法只需要一個探針。

如果已經(jīng)執(zhí)行了探測,我們就知道相應(yīng)的邊已經(jīng)被訪問過。從這條邊我們可以得出結(jié)論到其他前面的節(jié)點和邊:

  • 如果一條邊被訪問過,我們就知道這條邊的源節(jié)點已經(jīng)被執(zhí)行了;

  • 如果一個節(jié)點已經(jīng)被執(zhí)行并且該節(jié)點是只有一條邊的目標,我們知道這條邊已經(jīng)被訪問過。

如果我們在正確的位置有探針,遞歸地應(yīng)用這些規(guī)則可以確定方法的所有指令的執(zhí)行狀態(tài),探針只是需要在控制流邊緣插入的一小段附加指令。

三、CICD平臺關(guān)于測試覆蓋率的解決方案

通過上面對JaCoCo原理的介紹,結(jié)合我們公司內(nèi)部的研發(fā)流程,在CICD平臺對代碼覆蓋率功能的設(shè)計如下:

圖片

從上面 CICD 平臺對測試覆蓋率的設(shè)計圖,大概可以看出來,整個過程包含三個階段

3.1 測試前

測試前由測試人員(開發(fā)人員/運維人員)在流水線上開啟測試覆蓋率功能,在流水線執(zhí)行發(fā)布時,會在測試環(huán)境上下載JaCoCo Agent包,并在Java進程啟動時配置JavaAgent參數(shù);

在進程啟動過程或啟動之后,有class文件被加載時被Agent攔截,對class文件進行插樁處理,在必要的路徑下插入探針(插入探針的原理在上一節(jié)已經(jīng)介紹)。

3.2 測試中

在測試過程中,測試人員在測試環(huán)境執(zhí)行測試案例(手動執(zhí)行或自動化腳本),被調(diào)用到的代碼會被探針記錄下來,探針數(shù)據(jù)保存在Java進程的內(nèi)存中。

3.3  測試后

測試人員可以多次發(fā)布測試環(huán)境,針對同一個分支的代碼,可以合并多次測試的結(jié)果數(shù)據(jù),形成全量的覆蓋率數(shù)據(jù);

在測試結(jié)束后,CICD平臺通過JaCoCo的API,手動/自動下載(dump)覆蓋率數(shù)據(jù),合并(merge)歷史覆蓋率數(shù)據(jù),生成測試覆蓋率報告;

測試人員根據(jù)測試覆蓋率報告的結(jié)果,查看測試遺漏的場景,進行補充測試,事后總結(jié)遺漏的原因,提高測試效率。

四、在實踐過程中遇到的問題及解決辦法

測試覆蓋率在上線運行一段時間后,在實踐過程中發(fā)現(xiàn)了一些問題,總結(jié)為以下幾點:

4.1 在不同機器編譯會導(dǎo)致classid不一致的問題

在實踐過程中,經(jīng)常遇到這樣一個問題,用戶反饋并確認案例已經(jīng)正常執(zhí)行,但是生成的報告顯示未覆蓋,經(jīng)過調(diào)查發(fā)現(xiàn)在測試環(huán)境中的class和生成報告時的class不一致導(dǎo)致的。

在 JaCoCo內(nèi)部,覆蓋率數(shù)據(jù)是以classid作為key來存儲的,classid是根據(jù)class的字節(jié)碼hash算法得出來的,看JaCoCo源碼中關(guān)于classid的算法如下:

圖片

出現(xiàn)不一致的情況包括:

  • 發(fā)布時編譯的機器和生成報告的機器環(huán)境上有差異,比如操作系統(tǒng)版本、JDK版本等,導(dǎo)致編譯的class不一致;
  • 發(fā)布時編譯的代碼版本與生成報告時的代碼版本有差異,導(dǎo)致編譯的class不一致。

要解決上面環(huán)境的問題,需要保持在測試覆蓋率過程中編譯的機器環(huán)境保持一致,或者做到只編譯一次,使用同一份class文件,考慮到存儲空間的問題,vivo采用保持環(huán)境一致的辦法來解決。

對于第二種情況,常見于采用敏捷研發(fā)的團隊,在一個版本中按功能點轉(zhuǎn)測,經(jīng)常導(dǎo)致測試在測試過程中,源代碼已經(jīng)發(fā)生了修改,生成報告時代碼版本和發(fā)布時的代碼版本已經(jīng)不一致,這種情況比較復(fù)雜,我們在下面會介紹。

4.2 在研發(fā)過程中更加關(guān)注增量代碼的覆蓋率

在我們?nèi)粘5难邪l(fā)活動中,對于全量代碼更多使用自動化腳本來回歸,而新研發(fā)的功能主要表現(xiàn)為增量代碼,對于增量代碼的覆蓋率情況更加關(guān)注, JaCoCo本身不支持增量代碼的覆蓋率。

對于這個問題網(wǎng)上也有不少解決方案,基本都是基于git的版本差異,在生成報告時過濾掉沒有差異的類,形成兩份覆蓋率報告,一份是全量代碼覆蓋率報告,一份是增量代碼覆蓋率報告,而我們更希望在一份覆蓋率報告中呈現(xiàn)增量代碼和全量代碼的覆蓋情況,結(jié)合代碼在全量報告中的覆蓋路徑分析遺漏的場景,同時能在報告中標注增量代碼和增量代碼的覆蓋情況,期望的效果如下圖所示:

圖片

圖片

為了達到上述效果,需要幾個改造步驟:

  • 計算出當前代碼分支的變動情況,需要精確到代碼行
  • 改造JaCoCo計算邏輯,針對增量代碼單獨統(tǒng)計覆蓋率指標值
  • 改造JaCoCo報告格式,在報告中兼容全量代碼和增量代碼的覆蓋情況

對于計算代碼分支的變動情況,放棄 GitLab 提供的代碼比對功能來獲取不同版本之前的差異信息,如果版本之間差異太多的話,經(jīng)常發(fā)生GitLab 的API接口調(diào)用超時;

并且GitLab 的比對功能無法滿足定制場景,比如一行代碼僅僅因為格式化被識別為變更代碼等等,采用借助Linux自帶的diff命令,實現(xiàn)代碼差異比對的能力:

圖片

對于改造 JaCoCo計算邏輯,增加針對增量代碼的覆蓋率指標統(tǒng)計,在CoverageNodeImpl類中增加新的Counter,用于統(tǒng)計新增類、方法、行、指令覆蓋率指標;在SourceNodeImple類中increment方法中增加新增代碼行的統(tǒng)計邏輯。

圖片

圖片

4.3 重談關(guān)于classid的問題

在上面已經(jīng)談到關(guān)于classid的問題,如果是環(huán)境問題是比較好解決,但是現(xiàn)在互聯(lián)網(wǎng)團隊基本都使用敏捷模式,基本不太可能等開發(fā)工作全部完成再轉(zhuǎn)測,這樣必然會導(dǎo)致最新的覆蓋率報告,會出現(xiàn)以類為單元的覆蓋率數(shù)據(jù)丟失,需要測試人員來回重復(fù)的執(zhí)行測試案例,否則測試覆蓋率數(shù)據(jù)不會很好看。

既然知道問題所在,那有沒有辦法解決呢?是不是可以直接找到以前的classid,把以前的classid對應(yīng)的探針數(shù)據(jù)復(fù)制到當前的classid下就可以?當然是不行的,因為源代碼發(fā)生變動,導(dǎo)致探針的數(shù)量發(fā)生變化,會出現(xiàn)下面的情況:

圖片

或者這樣

圖片

出現(xiàn)這樣的情況,會無法判斷具體哪些探針是新增的或者刪除的;即使出現(xiàn)前后探針一致的情況,也有可能因為代碼修改,探針位置發(fā)生變化:

圖片

那么這個問題是否就無解了呢?這里給出一個大概思路,現(xiàn)在的覆蓋率數(shù)據(jù)是以類為單位存儲的,我們可以修改存儲的粒度,細化到方法級別,這樣可以保留一個類的大部分探針數(shù)據(jù),這樣如果只是修改一個方法的話,那么其他方法的測試數(shù)據(jù)可以繼續(xù)保留,只需要重新測試這個方法就行,這樣可以有效的降低測試人員對整個類的所有方案重復(fù)測試的情況。

五、總結(jié)

對于測試覆蓋率功能,有沒有給測試的質(zhì)量帶來提升,答案是顯而易見的。

當然也因為上面提到的問題,給測試人員帶了些麻煩,為了提升測試覆蓋率數(shù)據(jù),導(dǎo)致測試人員對同一個功能重復(fù)多次測試;同時也給測試人員帶來了好處,很多測試人員在面對測試覆蓋率指標嚴格要求下,被迫去看代碼的實現(xiàn)邏輯,提升了自己業(yè)務(wù)水平和閱讀代碼的水平,甚至出現(xiàn)測試人員和開發(fā)人員當面對質(zhì),關(guān)于代碼邏輯是否合理的場景。

最后,測試覆蓋率不是衡量測試質(zhì)量的唯一標準,要合理利用測試覆蓋率來提升測試質(zhì)量。

責(zé)任編輯:未麗燕 來源: vivo互聯(lián)網(wǎng)技術(shù)
相關(guān)推薦

2022-05-31 09:01:18

SwiftApp 項目

2023-10-27 08:49:00

JCovOpenJDK

2012-04-11 11:21:57

ibmdw

2019-09-25 09:20:41

谷歌代碼開發(fā)者

2023-04-06 08:03:43

Spock插件Surefire

2022-07-22 07:38:31

監(jiān)控系統(tǒng)

2011-04-25 09:49:20

代碼測試

2021-10-15 13:47:19

覆蓋率檢測 istanbul 總代碼的比例

2015-11-09 17:56:57

WebPHP函數(shù)覆蓋

2016-01-13 10:14:15

WebPHP函數(shù)覆蓋

2022-03-29 11:32:32

單元測試覆蓋率框架

2011-11-01 10:10:48

ScriptCover

2017-08-14 15:27:23

安卓單元測試代碼測試

2022-10-21 15:29:32

5G網(wǎng)絡(luò)

2021-12-25 22:30:27

Chrome DevTJavaScript調(diào)試工具

2024-11-01 15:05:12

2023-03-09 09:31:58

架構(gòu)設(shè)計vivo

2022-02-18 11:13:53

監(jiān)控架構(gòu)系統(tǒng)

2023-02-09 08:08:01

vivoJenkins服務(wù)器

2019-09-30 10:27:52

變異測試評估
點贊
收藏

51CTO技術(shù)棧公眾號