背景
埋點對電商類app的業務發展一直有著重要的指導作用,但是其複雜的資料組成使得它的穩定性難以得到保障,往往業務邏輯的一些重構就會導致一些埋點屬性甚至是整個埋點的丟失。
也正是由於埋點具有多個資料來源,常規的自動化驗證只能驗證埋點是否存在,無法跟業務場景匹配。而對於人工排查來說,雖然能解決和場景匹配的問題,但是像不同埋點的屬性之間的關聯或者屬性和介面欄位的關聯這類複雜的校驗做起來也非常的困難。
本文將介紹我們是如何通過teslaLab+埋點驗證平臺實現了埋點的自動迴歸以及多維度的埋點校驗,並在最近三個版本中累積發現了數十個埋點問題。
安卓
IOS
痛點
一個埋點中的資料主要由三個部分組成:
- 介面下發資料
- 使用者行為
- 本地執行的程式碼
要想驗證一個埋點是否符合預期的設計,關鍵的難點就在於如何固定住這三個資料來源,使其每次生成的結果都保持一致或者符合我們預定的規則。因此我們分別採用了以下方案來實現埋點生成時資料來源的固定
- 介面資料:對介面mock實現了對介面資料的錄製&回放
- 使用者行為資料:通過谷歌的uiautomator來實現使用者行為的錄製&回放
- 原生程式碼:和ab平臺打通,通過動態調整ab配置下發介面來最大限度上固定客戶端ab實驗相關的程式碼。
概覽
名詞解釋
- teslaLab: 是一款無線測試工具(MAC/WIN應用),提供開箱即用的無線效能 /體驗 /UI自動化 等專項測試工具。
- ubt-verification:安卓側實現埋點資料錄製和介面Mock功能的SDK。
- 測試場景:即校驗規則組,對應著一個測試用例,包含了這個case的所有埋點校驗規則
- mock記錄:包含了一個case在執行過程中請求的所有介面的資料,用於自動化迴歸時進行介面mock。
- 測試記錄:自動化迴歸的產物,即錄製到的所有埋點資料。
- 驗證報告:即測試記錄和測試場景的結合產物,包含了所有異常埋點的具體異常資訊。
- 任務組:來自teslaLab的概念,即測試記錄的集合,一般用於聚合各業務線的測試記錄。
- 通過率:指一個測試記錄中沒有任何埋點異常的埋點(去重)佔埋點總數(去重)的百分比。
- 任務組通過率:指任務組中所有測試記錄中沒有異常的埋點總數之和(去重)佔所有埋點總數之和(去重)的百分比。
系統架構圖
整個埋點自動化驗證平臺主要由三部分組成,分別是:
- 自動化工具:teslaLab
- 移動端SDK:安卓的ubt-verification和ios的kylin
- 驗證平臺:無線研發平臺的埋點驗證模組
流程圖
下圖為單個測試用例的首次驗證流程:
主要可分為三個階段:
- 準備階段
<!---->
- 用teslaLab錄製或者編寫自動化指令碼
- 在指令碼編輯頁手動執行指令碼並選擇錄製Mock功能,錄製介面資料並建立Mock記錄
- 新建執行任務並選中前面新建的指令碼和Mock記錄,執行任務之後得到一組埋點資料(即測試記錄)。
- 根據需要驗證的埋點的數量自行選擇手動配置(不推薦,太麻煩)或者從上一步得到的測試記錄中自動生成(推薦)相應基礎規則(即測試場景)。
- 至此,埋點自動化驗證的三要素(自動化指令碼,Mock記錄,測試場景)已集齊。
<!---->
- 執行階段
<!---->
- 可以手動執行或者通過配置Cron表示式實現定時執行在準備階段新建的自動化任務,產出一份測試記錄和一份驗證報告。
<!---->
- 驗收階段
<!---->
根據預定策略和測試記錄自動生成的驗證規則可能無法滿足預期,因此產出的驗證報告中的問題需要人工核查是否有效。
- 如果無效則可以通過報告詳情頁中的修復按鈕快速訂正規則,或者前往測試場景詳情頁手動訂正規則。
- 如果有效則可以選中有效的埋點並提交報障至埋點管理平臺,提交成功後會飛書通知至最後一位負責該埋點的研發和測試,當問題修復並被測試驗收之後即可驗收報障。
- 至此,一個測試用例的完整驗證流程結束。
詳情
接下來將按照驗證流程的順序逐一介紹這三個模組的詳細流程
自動化模組
埋點自動化依賴 「Tesla-lab 」 的自動化模組,其中資料Mock 記錄的錄製和UI自動化 指令碼的錄製依賴 「Tesla-lab」 本地編輯器,任務和任務組的定時執行依賴 「Tesla-lab」 任務排程模組,任務的實際執行依賴 「Tesla-lab」 任務執行器。
「Tesla-lab 」自動化流程圖
「Tesla-lab 」自動化整體架構實現
實現上分三個模組:
- 端
<!---->
- 編輯器端,負責指令碼編輯和資料錄製
- TeslaLab 客戶端負責本地指令碼/ 任務的除錯/執行,定時任務的部署
<!---->
- Core-local java agent
<!---->
- 本地核心服務,封裝了基於Quartz 的任務 / 任務組
- 本地裝置管理
<!---->
- iOS 基於 tidevice / wda
- Android基於 uiautomator2
<!---->
- 自動化任務實際執行者
<!---->
- 基於pytest 的指令碼執行器
<!---->
- TeslaLab 服務
<!---->
- 提供指令碼管理
- 任務/任務組管理
- 裝置遠端管理和同步
「Tesla-lab 」自動化錄製編輯器
編輯器/錄製器(客戶端內嵌Web)
- 錄製指令碼
<!---->
- 支援手動編寫或者通過點選頁面生成對應程式碼,支援執行/暫停來除錯指令碼
- 資料錄製,通過和移動端SDK進行本地的socket通訊,觸發SDK的介面/埋點的錄製/回放流程
<!---->
- Mock介面資料錄製
「Tesla-lab 」自動化任務執行器
- 回放任務建立
回放任務的建立會通過 本地socket xxxx 埠新建一個本地任務,同時會建立一份遠端任務。這樣可以通過Lab的安裝自動同步任務到本地,TeslaLab的核心本地任務和資料都是通過agent 模組和服務端進行互動。
- 回放任務執行
任務支援立即執行或者通過配置Cron表示式來實現定時執行,任務具有保護機制,在遇到應用crash或者anr(指令碼停滯超過一定時間)時會嘗試重新開始任務,並且單個任務執行總耗時超過一定時間則會提前呼叫結束錄製的api來跳過該任務。
- 回放任務結果
執行完畢後可通過在任務配置中開啟飛書通知來獲取任務組或者任務的執行結果,包含任務的執行詳情。也可以直接在任務列表頁點選展開檢視該任務的歷史執行記錄,記錄中包括執行期間的截圖和logcat日誌。
- 「最佳實踐一」一個任務關聯一個指令碼。每個指令碼關聯一條Mock記錄和一個測試場景。
關聯mock記錄和校驗規則,支援模糊搜尋
- 「最佳實踐二」合理利用任務組,任務組可以按照產品線或者業務線進行建立。
- 實現通過 TeslaLabEngine 單例模式實現API的收口。同時,TeslaLabEngine 可以做為獨立的Jar 包介面和前端介面進行解除耦合,可以單獨使用。
- 「最佳實踐三」合理利用飛書通知,進行任務/任務組的排錯。
報告示例:
- 「最佳實踐四」利用Cron表示式實現每日凌晨定時執行任務組,用於持續關注自動化執行的穩定性。目前一個應用的所有任務均在同一個任務組中,每天凌晨0點定時執行,其任務組的通過率即為當日的通過率指標,用於監測自動化執行的穩定性。
「Tesla-lab 」演進方向
在未來,依託雲真機平臺實現本地除錯,雲端部署和執行能力,實現更加自動化/智慧化的方式,再結合客戶端豐富的異常採集策略將埋點缺陷,客戶端缺陷儘早,儘快發現。
資料採集SDK
移動端的資料採集SDK均由teslaLab通過socket通訊調起,無互動介面。
安卓側為獨立sdk:ubt-verification,ios測則是依賴於線下效能測試工具Kylin實現。
整體架構圖
流程圖
移動端SDK的功能主要有錄製Mock資料和錄製埋點資料兩個流程:
準備階段
- 在端上通過三方工具nanoHttpPd啟動服務,收到teslaLab呼叫之後開啟mock錄製流程
- 在本地生成記錄id等引數,和teslalab傳參一併快取至本地,隨後重啟應用
錄製Mock資料
- 重啟後開始執行自動化指令碼,同時將通過攔截器獲得的所有的網路請求request&response詳情上報至後端
- 指令碼執行完畢後teslaLab將呼叫相關介面停止端上的錄製流程,同時SDK呼叫mock記錄建立介面
錄製埋點資料(即自動化回放)
- 重啟後開始執行自動化指令碼,所有的網路請求將在收到response之後呼叫後端介面獲取與其request匹配的mock資料並替換。
- 所有監聽到的埋點資料將被非同步存入本地資料庫,同時會有一個定時迴圈執行的任務從資料庫中分批讀取埋點資料並整合上報至後端。
- 指令碼執行完畢後teslaLab將呼叫相關介面停止端上的錄製流程,同時SDK呼叫測試記錄建立介面
埋點資料採集模組
安卓實現
主要通過反射對神策sdk實現靜態代理,在代理中實現埋點上報時的回撥,並在回撥中將埋點資料通過eventBus抄送至負責埋點上報的管理例項中,進而儲存至sqlite。後續在埋點上報階段將分批從sqlite中取出埋點資料並通過介面上報至後端。
IOS實現
神策sdk埋點記錄時有對外的通知,iOS監聽神策埋點通知即可獲得埋點資料。
介面Mock模組
安卓實現
通過對okhttpClientBuilder類的build方法進行插樁,並使用addInterceptor方法加入自定義攔截器,用於實現介面資料的錄製和介面的Mock。這裡我們是通過是否包含業務自定義的攔截器來判斷當前的okhttpClient是否為我們需要插樁的目標client。
在攔截器中即可對介面資料進行錄製或者是mock。
IOS實現
通過NSURProtocol對網路進行攔截,有請求發起時,請求mock服務介面判斷是否有mock資料,請求到mock資料就構建響應返回mock資料,沒有請求到就正常發起請求。
socket通訊模組
安卓實現
通過引入三方工具nanoHttpPd,在移動端開啟服務,mac客戶端端即可直接通過IP+埠的方式呼叫到在移動端實現的get/post介面,從而實現和自動化工具teslaLab的互動。
IOS實現
通過引入三方工具GCDAsync,在iOS客戶端開啟服務,互動邏輯同Android。
穩定性監控模組
- 本地記錄埋點錄製的總量,mock是否成功開啟,包的md5值/包id等資訊,跟隨埋點上傳至後端,用於監控自動化迴歸的執行穩定性以及發現問題後的排查。
遇到的挑戰
在穩定執行了一個版本之後,安卓側突然出現了大規模指令碼執行失敗問題,經排查執行截圖定位到是商詳介面的response發生資料結構的變更,導致使用前期錄製的介面資料進行Mock時無法完成資料解析,自動降級切換到CDN資料,從而導致頁面元素無法被指令碼識別。
我們在早期有規劃到這種情況,所以實現了對介面資料結構變更的自動檢測以及修復提醒,但是這裡的商詳介面卻並沒有觸發任何提醒,最後經排查發現我們錄製到的Mock資料是風控sdk加密後的response:
初期我們是為了錄製到完整的request和response資料,所以將攔截器放在了攔截器列表中最後一位。但是實際執行中應用層並不需要這些攔截器新增的額外引數,因此我們將攔截器前移到第一位,並且重新錄製這些涉及商詳介面的Mock記錄。最終修復後指令碼執行恢復正常。
平臺
整體架構圖
無線研發平臺:
- 測試場景模組
- Mock記錄模組
- 測試記錄模組
- 驗證報告模組
埋點管理平臺
- 埋點報障模組
流程圖
埋點驗證&驗收流程
- 通常一個測試用例中的埋點都有幾十個,因此推薦在構建場景時直接從測試記錄生成預設規則。
- 通過生成的規則產出的驗證報告的通過率一般在50~70%,這是因為部分埋點屬性的必傳屬性不是固定的,通常在不同的場景會有著不同的表現。但是生成此規則的時候是根據埋點管理平臺返回的埋點資訊生成的,因此需要將這部分規則進行訂正,可以在驗證報告詳情頁中通過快捷鍵直接一鍵修復,或者手動進行調整。
- 訂正之後重新進行校驗,產出的報告通過率通常會提升至75%左右,剩下的異常部分通常由一些隨機因素導致(例如時間戳,頁面瀏覽時長)。此時剩餘問題較少,可以直接人工嘗試復現,經確認後即可選擇埋點並提交報障至埋點管理平臺。
- 埋點管理平臺將傳送飛書通知至最近負責過此埋點的研發,研發修復問題之後會飛書通知最近負責過的測試,經測試和報障發起人驗收之後報障流程結束。如果問題在修復或者驗收階段停留超過一定時間將上升並飛書通知負責人leader。
最佳實踐
根據最近幾個版本的使用者反饋和總結,目前的最佳實踐為:
- 從測試記錄自動生成基礎規則,並用於產出驗證報告。
- 根據報告結果,在報告詳情中使用快捷鍵對必傳規則進行快速修正,並再次觸發驗證,得到報告。
- 直接嘗試人工復現報告中剩餘的問題,確認後直接提交報障至埋點管理平臺。
測試場景模組
為了從多方面對埋點實現充分的精準校驗,我們根據埋點的內容將用於驗證的規則劃分為埋點維度和屬性維度:
- 埋點維度
<!---->
- 埋點的數量
- 埋點之間的時序關係
- 是否重複上報(1s內上報多次)
<!---->
- 屬性維度
<!---->
- 是否必傳
- 是否可空
- 取值範圍
<!---->
- 列舉型別
- 多層巢狀JSON陣列
- 數字區間
<!---->
- 屬性值之間的對映(例如tabId和tabName)
- 正則校驗
- 和mock記錄中介面資料的對映(例如金剛位的埋點有部分屬性的值來源於介面下發)
並且每一個規則都可選強/弱校驗,區別只在於弱校驗不會影響到最終的通過率指標
遇到的挑戰
- 一個執行時長1分鐘的測試用例,假設能夠錄製到100個左右的埋點,去重後大約40個,每個埋點需要驗證的屬性平均約7個,這意味著每一個case都需要手動點選4073*3=2520次才能完成基礎規則的配置,這顯然是不可接受的,所以我們實現了從錄製的埋點資料中按照預定策略自動生成預設規則,這樣只需要保證錄製的埋點資料正常,即可完成最基本規則(包括埋點數量,是否必傳,是否可空和取值範圍規則)的構建。
- 對於首頁的一些的曝光埋點來說,大部分case都會上報,並且其規則基本一致,所以為了避免重複配置浪費人力,我們實現了全域性場景,並按照配置的優先順序和普通規則進行整合,目前已用於首頁曝光埋點的介面對映規則配置。
- 部分埋點屬性的值是直接將演算法下發的資料和介面資料合併的結果,這類資料一般為巢狀層級較深的JSON陣列,由於陣列中元素是無序的,因此列舉型別不能滿足其取值範圍的校驗。為此我們通過遞迴將問題簡化為JSON物件之間的對比來尋找差異,實現了針對這類複雜層級JSON陣列的規則提取,規則校驗和規則修復。
- 埋點的詳情資料均來自埋點管理系統,自動生成的規則也是根據埋點管理平臺中埋點屬性是否必傳的標註來生成,但是大部分埋點屬性是否必傳並非絕對情況,在不同的應用場景下可能必傳也可能不必傳,這導致我們產出的驗證報告中一直有大量噪聲。為此我們實現了在報告中對規則快速修復以及介面對映規則,在迅速消除噪聲的同時也建立起埋點資料和介面資料的對映關係,從根源上對埋點資料進行校驗。雖然在修復上線後由於商詳介面的問題整體的驗證報告通過率並未大幅度提升,但是在修復後的單個版本就發現了數十個埋點問題。
Mock記錄模組
- mock記錄由埋點資料採集sdk建立,在建立時檢查必傳介面(ab配置下發介面,首頁的一些介面)是否錄製來進行卡口,避免後續產出的報告為髒資料。
- 為了靈活控制mock的實際資料,每一個網路請求都會被錄製,並且支援開關。對於get請求還支援根據requestParams來自動匹配對應的response。
- 為了協助自動化工具解決彈窗的問題,我們還實現了全域性Mock,統一將紅包彈窗的介面mock並返回空結果。
- 介面資料作為埋點資料的重要組成部分,往往決定著自動化迴歸的穩定性,因此我們還實現了對介面變更的自動檢測,通過比對介面真實資料和mock資料的key值,尋找資料結構上的差異,生成變更的記錄和修改建議。
並且支援變更的應用和撤回。
遇到的挑戰
- 在錄製mock資料初期,我們遇到過部分帶有搜尋商品操作的指令碼會執行失敗,經排查發現是端上的實驗組程式碼已經調整,而ab配置下發的介面由於mock已經被固定,這導致原先錄製的指令碼無法適配新的實驗組的程式碼。為此我們引入了事件變更監聽,並過濾出所有來自ab管理系統的變更事件,再依據事件詳情中的ab實驗id去ab管理系統獲取最新的配置資訊,來自動生成用於批量更新mock資料的推薦修改結果。
測試記錄
- 測試記錄列表頁
測試記錄由移動端資料採集sdk建立,會根據端上上傳的監控資訊進行比對,如果有異常會飛書報警。
其中紅色背景表示記錄異常,完全不可信:
- mock未開啟:即獲取mock資料的介面發生過非200的情況,說明mock未開啟或者失效。
- 埋點數量不一致:後端通過埋點上報介面統計到的埋點數量和端上在神策sdk的回撥處統計的數量不一致,說明sdk存在漏報或者上報介面異常問題。
淡黃色背景表示記錄可能有異常,需要排查:
- 即測試記錄中的埋點數量和錄製的時長比例異常,正常比例約大於1:1,如果出現埋點數量小於錄製時長秒數,一般為指令碼異常,需要人工排查。
- 測試記錄詳情頁
驗證報告模組
- 報告的概覽會展示報告的基礎資訊:
- 報告的詳情按照埋點聚合,展示了每一個埋點的異常資訊及其原始資料。
- 在報告中經人工復現改埋點異常之後即可選擇異常的埋點並提交報障至埋點管理平臺,報障的流程與線上報障一致,支援問題打回,測試複測,建立人驗收等功能,並且在超時後會自動上升併傳送飛書通知至leader。
總結
埋點驗證平臺在每個階段遇到的痛點其實都是“埋點資料如何固定”這個問題的一個縮影。業務的快速迭代使得埋點驗證過程中積累的mock記錄和驗證規則這些沉澱產物十分脆弱,即使我們通過多種手段實現了這些資料的手動或自動更新,它們最終也難免會徹底失效。因此我們後續在提取長期有效沉澱的同時,也將致力於提升驗證規則和mock資料構建的自動化程度,來壓縮失效後資料重建的人力成本。
文/ZHOUXIAOFENG
關注得物技術,做最潮技術人!