《2-沈柯-移動端代碼質量觀測實踐.pdf》由會員分享,可在線閱讀,更多相關《2-沈柯-移動端代碼質量觀測實踐.pdf(41頁珍藏版)》請在三個皮匠報告上搜索。
1、移動端代碼質量觀測實踐沈柯嗶哩嗶哩 質量保障中心 資深開發工程師沈柯負責C端社區&基礎架構業務質量保障、質量提效、團隊技術架構、測試技術創新等工作,參與團隊質量保障體系優化,推進業務灰度、質量分級、移動端穩定性建設等,十余年移動端相關測試經驗,有豐富的移動端自動化測試、專項測試、持續集成、穩定性治理經驗,畢業后曾就職于搜狗、阿里巴巴,參與著作阿里測試之道。嗶哩嗶哩 質量保障中心 資深開發工程師目錄CONTENTS移動端質量01 移動端代碼測試的挑戰02 移動端靜態代碼質量觀測03 移動端動態代碼質量觀測04 業務落地實踐05 01移動端質量常見移動端質量評估體系質量驗證方案UI 自動化測試智能
2、遍歷測試適配測試啟動耗時測試頁面兼容性測試性能測試弱網測試顯性質量從使用者角度查看應用是否有缺陷、是否穩定、是否有性能問題,比如頁面加載是否快速、信息流滑動是否順暢、頁面交互是否卡頓等常見技術方案:Xcode Instrument、PerfDog、錄屏分幀、Monkey 等隱性質量軟件系統內部的質量狀態,代碼質量、模塊架構、代碼效率、代碼可讀性、代碼可擴展性,可統稱為代碼質量,大量低質量代碼容易積累過多的技術債常見技術方案:code review、結對編程、靜態代碼檢查(SonarQube)、動態代碼檢查問題1:代碼隱性質量缺少有效檢查工具質量內建自動化測試:單元測試、組件測試、端到端測試,部
3、署流水線,每次提交應用程序代碼、配置或環境以及運行時所需要軟件發生變化時,都要執行這些測試手工測試:需求評審、需求驗證、演示、可用性測試、探索性測試、測試用例管理關于移動端自動化測試性能測試-FPS、內存、CPU埋點自動化測試問題2:移動端 Android、iOS 打包時間+自動化測試時間超過 30 分鐘,測試效率低下02移動端代碼測試的挑戰移動端代碼測試標準方案AndroidLocal Tests:JVM 可直接執行的測試用例,不依賴真實或者虛擬設備Instrumented Tests:在真實或虛擬設備上運行的測試,此類測試包括集成測試、端到端測試,以及僅靠 JVM 無法完成應用功能驗證的其
4、他測試iOSUnit Tests:基于 XCTest 框架,測試代碼編譯通過后直接在 Mac 本地執行UI Tests:在真實或虛擬設備上運行的測試,此類測試包括集成測試,需要執行整包編譯流程移動端測試環境配置復雜性Xcode、CocoaPods、Android Studio、Gradle、Maven 等工種工具花式編譯報錯,排查成本高移動端代碼測試挑戰 代碼量價值標準成本代碼量(行)Java+Kotlin 百萬級OC+Swift百萬級存量代碼客戶端早期注重功能迭代,忽視單元測試、可測性,歷史包袱重單元測試構建時間無限期往后推遲,可測改造存量代碼風險高客戶端代碼迭代周期快,代碼倉日均更新代碼量
5、級大重度依賴集成測試,代碼變更影響范圍評估能力有限UI 渲染邏輯與業務邏輯耦合,程序狀態控制困難;缺少單測最佳實踐業務交替頻繁,文檔化不足,新接手開發/測試同學不熟悉代碼邏輯增量代碼業務邏輯日均改動代碼行數增加/刪除近萬行增加/刪除近萬行周均需求數量幾十個需求幾十個需求如何大規模降低白盒測試成本?如何編寫有效的白盒測試用例?如何體現白盒測試帶來的價值?如何有效設計函數邏輯的斷言?行業內缺少移動端白盒測試最佳實踐方案,目前還沒有看到移動端大規模執行白盒測試 CI/CD 成功的案例移動端代碼測試挑戰 可測性程序有一個 Google IO 大會活動詳情頁,點擊“+”按鈕用戶可以將會話添加到他們的日歷
6、中,如果他們已將會話添加到他們的日歷中,則該加號按鈕將變為“簽到”按鈕。如果他們再次點擊“簽到”按鈕,會話將從他們的日歷中刪除移動端代碼測試挑戰 可測性UI 自動化-Android Instrumented TestsActivityTestRule:此規則提供單個 Activity 的功能測試-帶有 Test 函數會被執行-帶有 Before 注釋的所有方法運行之前啟動測試完成并-帶有 After 注釋的所有方法結束后終止操作步驟:腳本點擊+文本,點擊以后斷言按鈕狀態是否成功切換成 check 狀態單元測試:Arrange Act and AssertPost-Act-State Asser
7、t:-檢查函數返回值-檢查被測類的函數-檢測注入對象的狀態移動端代碼測試挑戰 可測性代碼測試常用三步驟:Arrange、Act、Assert 困難,由于 Android 代碼充斥著大量系統回調無法 arrange,構造參數復雜,即被測試代碼引用了無法主動創建的實例,則該段代碼存在不可測的風險。示例 onStop()函數:無返回值、無法通過入參控制內部邏輯、無法獲取內部狀態問題3:移動端代碼可測性差,應用架構復雜,存在大量系統創建的類以及系統回調,無法通過測試代碼有效初始化并控制代碼執行流程官方示例架構業內實際架構移動端應用的系統框架設計使得代碼測試更加復雜,Google 編寫 AndroidS
8、DK 的方式以及 Google 鼓勵我們構建應用程序的方式使測試變得困難,在某些情況下甚至是不可能的內存對象關聯03移動端靜態代碼質量觀測靜態代碼分析代碼質量:代碼的效率、結構、可讀性、可擴展性、可靠性和可維護性等,靜態代碼分析作為第一個切入點;問題修復價值感弱,距離實際業務問題太遠不可 Mock 環路復雜度(Non-Mockable TotalRecursive Cyclomatic Complexity):環路復雜度(Cyclomatic Complexity)用于衡量代碼中有多少種不同的執行路徑,通過計算 if、while 和 case 作為分支基礎單位進行計算全局可變變量:計算被測類全
9、局可訪問且可變的字段數,可變的全局狀態使測試變得困難,因為測試是不可隔離的,需要在測試之間設置和清除全局狀態得墨忒耳法則:調用從外部模塊獲得的對象的方法會引入復雜度,外部函數應該自我調用。調用外部對象的函數會使得測試變得更加困難,因為 mock 時需要將函數內部狀態透傳給外部的調用靜態代碼插樁+運行時信息攔截實現原理:開發可插拔代碼套件,通過 AOP 能力將代碼注入到被測試應用;基于注入的套件代碼對函數狀態進行攔截、修改、存儲,結合各類斷言能力持續管控業務代碼邏輯正確性、可測性語言代碼插樁代碼回放JavaASM+gradle反射KotlinASM+gradle-Objective-CClang
10、 插件NSExpressionSwiftSwiftSyntax-靜態代碼插樁插件代碼 Clang 插件iOS 端基于 Clang 插件提供的一系列 API,可以按需對源碼進行結構化重寫;Android 端基于 gradle+ASM框架注入字節碼Objective-C 插樁效果Java 字節碼插樁效果靜態代碼插樁-運行參數校驗攔截函數入參、返回值,將內存對象序列化成 JSON 字符串,通過腳本斷言、數據 diff 校驗運行時信息靜態代碼插樁業務場景代碼特征基礎層大部分代碼跟 UI 類解耦,弱依賴系統類有定義良好的接口提供給上層業務調用代碼內部邏輯緊湊、閉環弱依賴其他模塊核心層部分代碼跟 UI、系
11、統類耦合部分邏輯依賴網絡、設備硬件等外部狀態函數邏輯校驗跟設備狀態耦合業務層大部分代碼跟 UI 狀態耦合代碼邏輯通過 UI 組件進行展現大量代碼通過系統回調、異步回調進行處理通過 Java 反射、Objective-C NSExpression Eval 能力可以對簡單函數進行代碼回放,但是無法高效處理復雜函數移動端系統對象序列化生成的數據復雜度遠超預期,生成 JSON 數據過于龐雜,甄別有意義字段難度極大靜態代碼插樁會遇到眾多技術挑戰,如要適配不同語言的解析器、編譯過程,需要處理不同的函數語言以及參數類型,是一項非常細致且有技術挑戰的工作,執行成本居高不下;同時 Android、iOS 雙端
12、技術方案割裂,維護成本極高移動端代碼測試難題從下往上:函數調用鏈、模塊依賴關系等,定位容易但距離問題較遠,從代碼底層向上摸索質量維度,周期長、依賴高該方向會遇到眾多技術挑戰,如要適配不同語言的解析器、編譯過程、語法糖,是一項非常精細且有技術挑戰的工作從上往下:基于 UI 操作,結合測試工具采集采集、度量數據,如頁面加載速度、穩定性測試等,距離問題近,但是定位相對困難常見測試方案:PerfDog、adb monkey,跨進程測試,程序內部狀態不可見自動化測試金字塔模型一些常見的質量問題:白屏、網絡出錯、黑屏、圖片不顯示、ANR、發熱、主線程卡頓、流量偷跑、http(s)檢測、主線程 IO、主線程
13、網絡請求,這些真實存在的質量問題似乎無法落檔到 UI 測試、集成測試、單元測試范疇移動端代碼測試難題問題1:代碼隱性質量缺少有效檢查工具問題2:移動端 Android、iOS 打包時間+自動化測試時間超過 30 分鐘,測試效率低下問題3:移動端代碼可測性差,應用架構復雜,存在大量系統創建的類以及系統回調,無法通過測試代碼有效初始化并控制代碼執行流程問題4:移動端顯性質量問題定位困難,問題現象跟問題代碼之間無法建立有效連接,且問題形式存在不確定性方案目標:探索是否存在一個中間層,向上可以進行宏觀層面操作、向下可以精準定位問題代碼,同時支持:快速驗證(秒級)、代碼級校驗、函數 hook、組件擴展能
14、力04移動端動態代碼質量觀測移動端動態化/Patch方案的啟發ReactNative:一個由 Facebook 于 2015 年 9 月發布的一款 開 源 的JavaScript 框 架,它 可 以 讓 開 發 者 使 用JavaScript 和 React 來開發跨平臺的移動應用JSPatch:一個開源項目,只需要在項目里引入極小的引擎文件,就可以使用 JavaScript 調用任何 Objective-C 的原生接口,替換任意 Objective-C 原生方法通過 JavaScript 訪問/創建原生代碼應用進程移動端動態測試框架在應用進程內置 JavaScript 引擎,動態加載 JS
15、代碼并橋接調用原生代碼JavaScript 腳本JavaScript 引擎原生代碼系統代碼對比序列化數據驗證跟原生代碼測試,JavaScript 動態代碼測試在技術門檻跟可編程性上做到較好平衡移動端動態測試框架-HookInline HookPLT Hook維度PLT HookInline Hook精準度(中)函數級(高)匯編/指令級范圍(?。┏霈F在 PLT 表中的動態鏈接函數(大)目標 so 內全部可執行代碼靈活性(差)批量(好)單次或批量技術難度(中)涉及內存地址計算和修改等(高)涉及寄存器計算、手寫匯編、指令修復等動態代碼 hook 框架是實現質量觀測的核心前提移動端動態質量觀測實踐 p
16、thread OOM根因:進程虛擬內存地址空間耗盡,導致創建線程過程中發生 OOMAndroid 應用常見的線上內存問題:pthread_create那什么時候會虛擬內存地址空間不足呢?創建 Socket文件句柄過多打開文件創建 HandlerThread創建 NIO Channel棧內存溢出線程過多線程數超限CPU Profiler 查看所有線程列表adb shell ps-T p pidadb shell dumpsys meminfo pacakgenamecat/proc/pid/status是否有更加體系化的觀測方式?移動端動態質量觀測實踐 pthread OOM監聽線程創建監聽文件
17、創建Hook 代碼監聽 Thread、File 等關鍵函數創建java.lang.Threadjava.io.F.S.Socket移動端動態質量觀測實踐 UI 自動化dump 頁面元素實現基礎 UI 操作UI 自動化腳本Monkey 隨機點擊測試移動端動態質量觀測框架依托腳本引擎,抹平雙端環境差異,統一測試能力,支持業務自定義迭代05業務落地實踐移動端測試代碼生成支持實時在線編輯、調試腳本代碼,單次代碼調試耗時維持在秒級,對比原生代碼測試,技術門檻大大降低,運行耗時下降90%以上支持代碼運行時檢查,hook 返回值,手動選擇需要校驗的字段并生成測試代碼,可按需二次編輯測試代碼底層通用腳本移動端分層測試能力聚合15 行代碼實現 Monkey 測試能力,可按需拓展測試條件提升覆蓋率配合圖片治理、高危權限訪問、主線程檢測腳本實現質量專項域檢查嗶哩嗶哩技術公眾號感謝聆聽關注QECon公眾號