
編者按:本文源自阿裡雲雲效團隊出品的《阿裡巴巴DevOps實踐指南》,掃描上方二維碼或前往:
https://developer.aliyun.com/topic/devops,下載下傳完整版電子書,了解阿裡十年DevOps實踐經驗。
在任何業務發展的過程中都會不可避免的面臨服務的膨脹,應用複雜度的增加,可持續測試的難度不斷增加。一方面,用例集會不斷的膨脹,一次 CI 驗證要數十分鐘,用例的維護成本越來越高,開發效率開始降低。另一方面,我們花了精力寫了很多自動化用例,希望能夠提高投入産出比,也就是測試的有效性。
提升測試速度
分布式測試
分布式測試的核心思想是通過增加計算資源,并發的對 case 進行執行,并在執行後對測試産生的結構化結果進行解析合并,進而提升單次測試的執行速度。
整個測試的執行過程可以劃分為以下三個階段:
- 測試用例解析與分發
- 分組用例的執行
- 分組測試結果合并
以阿裡雲某雲産品核心團隊的某工程為例,該工程擁有 1 萬多個單元測試用例,在沒有采用分布式測試方案之前,一次 CI 的驗證時長超過 4 小時,導緻問題發現、修複時長拉長,影響了日常的疊代速度。該團隊後采取了分布式測試的方式進行,平均的執行時長被優化到了半小時以内。
分布式測試的本質就是用執行資源的堆疊,去換取更快的執行速度。理論上我們把每一個測試用例拆分到一個容器内執行,可以獲得極緻的回報速度。但是并不是所有場景下都适合采用分布式測試,例如用例之間存在依賴,這些用例不能無差别的分布在不同的執行分組。
精準測試
分布式測試很大程度上解決了測試執行的速度問題。但是如果在任何情況下都無差别的執行全量的用例,會存在一些問題:
- 對計算資源的浪費
- 引入了大量的無效執行
- 用例本身穩定性問題導緻排查時間浪費
- 在探索測試有效性的過程中,我們引入了精準測試的方案
什麼是精準測試?
通過建立測試用例與業務方法的關聯關系,在代碼發生變化時,精準的推薦出需要運作的用例,進行測試執行與結果回報。通過精準的圈定測試範圍,可以帶來效率和速度的雙重收益。
精準測試的基本要素
- 測試用例(Case)與應用代碼方法(CodeMethod)關聯關系的建立。這種關聯關系,我們定義為基線。
- 代碼發生變更,根據基線中用例與應用代碼方法的關聯關系,準确推薦出變化的方法、關聯的測試用例和變化的測試用例,并進行運作。
如何建立測試基線
- 基線的建立方式有多種,在阿裡巴巴内部使用過以下兩種方法去建立用例與代碼的關聯。
- 通過位元組碼注入的方式,埋入 trace 調用,并在調用中傳入用例與業務方法的簽名。通過采集 trace 的日志,拿到所有的測試用例與方法調用鍊路,建立起用例與方法的關聯關系。
- 通過 AST 解析的方式。
如何進行用例推薦
在代碼發生變更後,會基于代碼變更解析出變化的測試用例與變化的業務方法。方法的變化通常是新增、删除、更新。
用例的代碼變更情況比較簡單,所有新增和更新的用例都會納入到回歸範圍。
被測應用代碼變更,要分情況考慮:
- 新增的方法:比對不到任何用例,針對此次變更,開發或測試可能補充了測試用例,也可能未補充,需要進行提示。
- 更新的方法:更新的方法分兩種情況,第一種,更新的方法有關聯的用例,需要推薦出來;第二種,更新的方法原本就沒有關聯任何用例,需要提示使用者補充測試用例進行覆寫。
- 删除的方法:删除的方法也分兩種情況,第一種,該方法本身就不關聯任何測試用例,不做任何提示;第二種,該方法關聯了一些測試用例,那麼考慮到方法有可能隻是重構或者更名的情況,這部分關聯的測試用例在沒有被删除的情況下,也是需要進行回歸的。
阿裡雲某核心雲産品,通過使用精準測試的方案,一個疊代了一周左右的代碼變更,從原先每次 CI 需要全量執行 3700+用例,到每次 CI 可以精準的執行變更影響的用例範圍。速度提升了近一倍,測試範圍縮小到不到原先的 1/6。
提升測試有效性
我們希望編寫和運作的測試用例能夠有效的覆寫代碼的邏輯,其中重要的一個着手點是測試覆寫率,通過測試覆寫率來暴露問題,并促進問題的解決。
測試覆寫率
測試覆寫率,在本文中,指的是代碼的覆寫率。即行覆寫率,分支覆寫率等。
此外,本文中所有涉及覆寫率采集的示例都以 Java 為例。
如何收集完整的覆寫率
一個應用下通常存在多種不同類型的自動化測試集
- 單元測試
- 手工測試
- API 測試
- WebUI 測試
- 其他
為了能夠準确的反映一個應用的完整覆寫率,需要對上述多種自動化測試的結果進行聚合。在阿裡,每一個測試的運作都會關聯到相應的應用,進而可以對測試結果進行聚合。
為了能夠收集所有類型的測試覆寫率,我們做了以下事情:
對于單元測試來說,覆寫率資料産生在單測執行的機器上,我們會根據執行機上的原始代碼資訊,編譯後的 class 資訊,單測執行後産生的覆寫率資料原始檔案,以及變更的代碼資訊,計算出單元測試的覆寫率報告。
手工/自動化測試
我們實作了一個覆寫率采集用戶端,和一個覆寫率采集/報告計算解析的覆寫率平台。通過運維平台将覆寫率采集用戶端部署到應用的內建環境,在應用啟動時會挂載一個 javaagent 程序。當我們在任意測試平台觸發任意類型的自動化測試時,會通知覆寫率平台與覆寫率采集用戶端進行互動,完成覆寫率計算原始資料的采集與解析。
另外,在進行釋出卡點時,我們會合并相應的單測覆寫率形成完整的覆寫率報告。
測試覆寫率能給研發過程帶來哪些價值
- 分析未覆寫部分的代碼,進而反推在前期測試設計是否充分,沒有覆寫到的代碼是否是測試設計的盲點,為什麼沒有考慮到?需求/設計不夠清晰,測試設計的了解有誤,工程方法應用後的造成的政策性放棄等等,之後逐漸補充測試用例。
- 代碼覆寫率高不能說明代碼品質高,但是反過來看,代碼覆寫率低,代碼品質不會高到哪裡去,可以作為測試自我審視的重要工具之一。
- 分析變更代碼的覆寫情況,進而保證對變更的測試充分,增強釋出成功率與信心。
除了上述的“測試覆寫率”,還可以使用相同的技術來統計“線上業務對代碼的覆寫情況”。也就是統計出來有哪些代碼是被真正的線上業務所用到的,哪些是從來沒有被調用到的。進而檢測出程式中的廢代碼,可以逆向反推在代碼設計中思維混亂點,提醒設計/開發人員理清代碼邏輯關系,提升代碼品質。
增量覆寫率
有了完整的測試覆寫率資料之後,就可以讓它發揮作用了。但脫離了具體的場景,單獨追求一個較高的測試覆寫率數值是沒有意義的。如果一味的追求較高的覆寫率的數值,往往帶來的的是用例的過度設計。如何健康有效的讓項目的測試覆寫率穩步的提升,在阿裡巴巴内部,我們更多的是采用關注增量覆寫率的方式來提升整體的測試覆寫率。
什麼是增量覆寫率
增量覆寫率是指,某一次測試過程中,變化的代碼的測試覆寫情況。
變化的代碼=被測分支的代碼與目标對比分支的 diff(通常目标對比分支是我們最終會合入的分支)。
增量覆寫率=變化的被覆寫的代碼行/變化的代碼行。
增量覆寫率的價值
- 釋出之前是否存在漏測
- 針對漏測完善用例集
- 增強變更釋出的成功率與釋出信心
- 通過追求增量覆寫率進而提高被測應用的整體測試充分度
增量覆寫率的應用
在單元測試的時候,會有單元測試的增量覆寫率,在測試/預發等環境進行各種接口自動化/UI 自動化/流量回放/手工測試時,也會有增量覆寫率産生。當增量覆寫率與持續傳遞流水線進行結合時,能夠有效的保障項目品質是在往好的趨勢發展。
在阿裡巴巴内部的實踐中,我們通常會在 CICD 流水線中的關鍵階段設定各類卡點,保障在多人協作的場景下,每個開發同學送出進入內建的代碼經過充分的自測。在上線前的內建階段,進入的代碼在內建環境中被充分驗證後,才會被允許釋出上線。
通過增量覆寫率的回報,開發/測試同學可以針對性的去補充各類測試用例,盡可能的保障在各階段不存在測試遺漏。同時,在不斷的完善測試集的情況下,項目的整體測試覆寫率也會得到健康有效的提升。
線上覆寫率
覆寫率的采集我們通常不會應用到線上環境中,但是如果将覆寫率采集放到線上環境,又能演化出應用瘦身的場景,幫助我們從另外一個角度提升效率。
通常線上業務的服務都會部署多個副本,為了減少風險,我們會在其中的少量副本上進行覆寫率采集。經過一個較長的采集周期後,會生成線上覆寫率報告。在這個時候可以認為被覆寫到的代碼都是有效代碼,而剩下的那些長時間沒有流量覆寫的代碼,需要謹慎的考慮删除/重構。通過這樣的方式去精簡我們的代碼,進而降低維護成本。
在阿裡巴巴内部,當我們決定對某些維護困難或者腐化明顯的應用進行重構時,都會進行一段時間的線上覆寫率采集,并根據報告去指導我們進行代碼重構,代碼瘦身。
小結
分布式測試為測試速度插上了翅膀,精準測試有效的識别出了測試的範圍,增量覆寫率又為測試的不斷完備提供了有利的指引,線上覆寫率幫助我們有效的進行應用瘦身。充分利用好這些技術手段進行測試提效,可以讓持續傳遞的過程更加的順暢。
免費下載下傳《阿裡巴巴DevOps實踐指南》
阿裡巴巴合夥人和業界多位大佬力薦、何勉、陳鑫等17位阿裡資深技術專家聯袂出品、阿裡十年DevOps經驗沉澱總結、阿裡巴巴DevOps落地實踐一本通。
前往:
,下載下傳完整版電子書。