唯品會iOS程式碼覆蓋率的應用實踐
調研中發現,iOS程式碼覆蓋率如要大規模應用到功能/迴歸測試,需解決如下三個痛點:
蘋果開發工具Xcode僅支援單元測試的程式碼覆蓋率,而且只能在本地連線除錯。而實際的測試裝置多達20+,把裝置連線電腦再收集覆蓋率是不可行的,我們必須做到收集自動化,而且對使用者無感知。
App的功能分支測試周期大約有4天,此期間可能存在多次的開發程式碼提交、缺陷修復,以哪一個版本作為覆蓋率統計是值得思考的。我們嘗試約定在某個穩定版本做全面的功能測試,但效果並不好,因為前期已測過的功能沒必要重測一遍,時間也不允許。因此,我們需要支援行覆蓋率的多版本合併。
鑑於app的執行模式僅支援離線插樁,我們需要處理大量手機使用者,不同時間節點的覆蓋率資料。
首先,程式碼覆蓋率要考慮插樁,插樁方式有3種:1)原始碼插樁;2)中間程式碼插樁;3)可執行檔案的二進位制插樁。iOS使用clang作為前端編譯器,負責生成AST語法樹,並將程式碼編譯成LLVM bitcode;而LLVM作為後端編譯器負責生成平臺相關的機器語言。其編譯插樁過程屬於中間程式碼插樁,簡化的過程可參考圖1。LLVM脫胎於GCC,也可使用gcda/gcno記錄程式碼覆蓋率。其中:
gcno是notes file,插樁編譯後生成;
gcda是data file,與gcno對應,由程式執行時記錄;
LCOV作為GCC Code Coverage的開源前端工具,支援行/函式/分支覆蓋的報告輸出。因此,我們使用LCOV作為iOS程式碼覆蓋率生成工具。
圖1: 插樁編譯原理
圖2: 系統架構
前端UI接入公司的覆蓋率平臺,支援覆蓋率的收集、生成報告、郵件通知;
排程層負責分發訊息至具體執行的機器Analyser,Analyser由jenkins封裝,節點的機器必須為Mac系統,物理機或虛擬機器均可;
分析器支援覆蓋率檔案的合併、差異以及報告的輸出。另外分析器負責接收終端上報覆蓋率資料;
檔案系統管理覆蓋率檔案的中間資料以及版本構建資訊。
我們設計出一整套解決方案,請看圖3
圖3:iOS程式碼覆蓋率實現時序圖
具體處理時序如下:
1) Xcode打包伺服器在CI中自動插樁,並根據commit id,上傳與之對應的標籤檔案gcno;
2) 使用者透過OTA方式安裝app,在測試過程中只需把app置於後臺,覆蓋率資料即可從快取刷入硬碟,並透過http介面上傳至檔案伺服器;
3) 覆蓋率平臺可通手工觸發方式,收集指定分支、commit id的覆蓋率檔案info;
4) 待預處理完畢後,覆蓋率平臺可生成合並的或差異的覆蓋率報告;
接下來我們從如下三方面剖析技術實現:
Xcode插樁
Pod上傳伺服器
覆蓋率檔案的合併/差異處理
(一) Xcode插樁
在BuildSettings分別設定Instrument Program Flow、Generate Legacy Test Coverage File為True,即可開啟插樁。
圖4: Xcode 插樁設定
(二) Pod上傳伺服器
透過Pod的外掛方式,我們使用C++混編,呼叫外部的__gcov_flush方法把覆蓋率gcda從記憶體刷到硬碟。為了方便交叉編譯,GCC設計了兩個與生成路徑相關的變數GCOV_PREFIX,GCOV_PREFIX_STRIP,如下圖。
圖5: Pod的外掛實現
在生成GCDA後就要考慮上傳到檔案伺服器了,我們採用AFNETWORKING庫,把多個GCDA檔案整合在一個介面上傳,檔案大小約7M Bytes
(三) 覆蓋率檔案預處理,支援差異/多版本合併
我們使用開源LCOV來處理檔案,gcda+gcno+原始碼可生成中間檔案info,info檔案包含了最終呈現報告的所有資訊,包括原始碼路徑、函式名、函式執行次數、函式總數、函式在原始檔的位置、行號、行執行次數、行總數。為支援行差異覆蓋率,我們自定義了新欄位CA/CF/CH,請見圖6。
圖6: 中間檔案info資料結構
對於兩個不同版本的合併,使用平移。原則是把舊版本程式碼裡的未變更的行覆蓋平移到新版本。請見圖7。
圖7: 新舊版本git diff對比
具體流程如下,舊程式碼的覆蓋率與git diff 比較,先判斷是否塊內程式碼,如不是塊內程式碼則平移行號至新版本;若是塊內程式碼,則再判斷是否為已刪除的行號,若是,則跳過不做平移;若不是已刪除的行,則平移行號,請見圖8。或許讀者有疑問,兩個版本的上下文都變了,平移行覆蓋率後的可信度高麼?筆者想強調的是,覆蓋率報告好比一份健康檢查報告,只關心異常點,沒有覆蓋的行就是異常點。在使用平移演算法後那些依然沒有覆蓋的行就是沒經探索的荒地,將是重點關注的物件。
圖8: 兩個版本的行覆蓋率合併流程
我們再擴充套件至n個版本的合併,可沿用以上的平移演算法,只需把最後一個版本作為平移的基準版本即可,可參考下圖。
圖9: 多版本的行覆蓋率合併流程
至此,iOS覆蓋率整套實現方案描述完畢。
iOS覆蓋率工具已接入至覆蓋率平臺,可透過伺服器管理指定待收集的系統平臺,分支;平臺支援多分支同時收集。功能測試分支的覆蓋率收集時間可控制在20分鐘內。覆蓋率收集完成後,平臺可設定行差異覆蓋率的對比基線,可設定一個分支內合併的多個版本,效果請見圖10、11、12。
圖10: 移動測試列表伺服器管理
圖11: 生成覆蓋率報告頁面
圖12: iOS覆蓋率報告的目錄結構
最後,我們看看該工具的應用情況,特賣會App當前每兩週發一個版本,在功能測試階段,各條業務線(包括特賣/基礎/使用者/創新)已開始使用iOS覆蓋率檢測工具,從使用的經驗看,功能測試階段的程式碼行差異覆蓋率達到90%,未覆蓋的行主要包括三項,風險可控:
異常捕捉
非空指標的保護
冗餘預留程式碼
結合iOS覆蓋率工具,我們總結出目前適合特賣會app的精準測試策略,請見圖13。在測試分析階段,我們注重需求差異,技術差異的分析,結合用例地圖得出測試策略,並指導我們進行冒煙/功能測試,每個測試階段的Code Review著重點有所不同,在冒煙測試階段,CR著重檢查開關、介面名、介面引數、model欄位;在功能測試階段,CR重點關注介面異常/跳轉、行為;迴歸階段則優先檢查Bug Fix的程式碼改動。測試階段均透過行差異覆蓋率檢查測試遺漏,並反饋更新測試策略。
圖13: 特賣會App精準測試策略
目前使用的人工分析+工具輔助的方式進行精準測試,在這條探索的道路上我們還有很長的路要走。人工分析受制於技術,需求背景,能力和經驗,我們很難保證質量。如何把已有的覆蓋率資料轉化為事前分析的參考,並結合整理的用例-模組(檔案、函式、分支)對映庫實行自助分析、測試用例集推薦,將是我們下一步研究的重點。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69900365/viewspace-2636946/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- iOS 覆蓋率檢測原理與增量程式碼測試覆蓋率工具實現iOS
- ReactNative 多端程式碼覆蓋率調研及實踐React
- 聊聊Go程式碼覆蓋率技術與最佳實踐Go
- 長文解讀:Flink在唯品會的實踐應用!
- 程式碼覆蓋率與測試覆蓋率比較
- pHp程式碼覆蓋率PHP
- Flink在唯品會的實踐
- Apache Flink在唯品會的實踐Apache
- 什麼是程式碼覆蓋率
- go 程式碼覆蓋率測試Go
- 在做服務端程式碼覆蓋率或者準備做程式碼覆蓋率的兄弟們,來聊聊???服務端
- 圖資料庫 Nebula Graph 的程式碼變更測試覆蓋率實踐資料庫
- JaCoCo計算程式碼覆蓋率原理
- 唯品會 JIT模式 應用探討模式
- 【Lua】實現程式碼執行覆蓋率統計工具
- 單元測試必備:Asp.Net Core程式碼覆蓋率實戰,打造可靠應用 !ASP.NET
- Java 程式碼覆蓋率調研報告Java
- 【譯】Visual Studio Enterprise 中的程式碼覆蓋率特性
- [lua][openresty]程式碼覆蓋率檢測的解決方式REST
- 自動化會提高測試覆蓋率,那測試覆蓋率是什麼?
- 使用 coverlet 檢視.NET Core應用的測試覆蓋率
- vivo 基於 JaCoCo 的測試覆蓋率設計與實踐
- 進化的覆蓋率-程式碼實時染色系統 - 周為 / 翟帥
- 【唯實踐】容器環境應用一鍵拉起實踐
- 使用Jacoco統計服務端程式碼覆蓋情況實踐服務端
- 數倉服務平臺在唯品會的建設實踐
- 構建與定製:唯品會PaaS基於Kubernetes的實踐
- 基於Jacoco的單元測試程式碼覆蓋率統計
- C++語言的單元測試與程式碼覆蓋率C++
- James Shore:不要使用單元測試的程式碼覆蓋率
- 開源專案核心程式碼單元測試 100% 覆蓋率實戰
- idea2022.1 檢視單測覆蓋率展示分支覆蓋率Idea
- 測試覆蓋率二改實現
- 前端質量提升利器-馬可程式碼覆蓋率平臺前端
- Jenkins+Cobertura程式碼覆蓋率(學習筆記三十七)Jenkins筆記
- 關於程式碼覆蓋率,你不可不知的兩大陷阱!
- iOS程式碼瘦身實踐:刪除無用的類iOS
- 唯品會的“成年煩心事”