TARS 系統 —— UI 自動化解決方案

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1. 立項背景"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"業務痛點"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"互聯網 APP 測試在“快速迭代”的開發模式中進行的,每次迭代都會伴隨着各種各樣的測試,其中以功能集成測試爲重要和主要的一個方面,又因版本迭代過程中需要進行的功能特性驗證和已有功能迴歸,要求測試人員既能測試性功能的各種特性,又要保證原有功能不受影響。在頻繁的迭代工程中,APP 的功能和結構越來越複雜,新代碼的影響越來越廣,迴歸範圍越來越多而且 APP 端有各種機型和系統版本,這就造成了潛在的漏測風險和越來越多的重複勞動。以去哪兒網機票業務爲例,冒煙 Case 測試點就有300+,月版迴歸 Case 測試點有1000+,每次月版迴歸相當耗費測試人員精力,測試的質量依賴於測試人員的質量,並且還有可能遺漏,每次月版迴歸都要至少10個 QA 集中測試一天,效率十分低下,並且還經常出現線上 bug 和故障。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了解決其中工作量最大的每次都要進行的迴歸測試工作量問題,提升工作效率,降低潛在的遺漏風險,減少重複的工作,該項目希望能夠通過一種所見即所得的方式完成腳本的錄製,即使測試人員不會編程不懂腳本,也可以通過正常用戶的點擊拖拽等操作,自動完成腳本的錄製,從而大幅度降低企業和項目的自動化維護成本。針對移動廠商跨多端的特點,需要開發一套 UI 自動化測試解決方案。支持 TestCase 的自動重複執行,在多種機型兼容性測試,後端響應數據可控,並對執行結果的請求數據、響應數據以及界面截圖進行驗證,斷言執行結果的正確性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2. 方案選型"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.1 測試分類"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自動化測試是隨軟件開發技術一併發展的一種測試技術。軟件測試包括白盒測試與黑盒測試,而自動化測試最早使用白盒測試中的單元測試。這種測試方式較爲高效,易於實現。黑盒自動化測試興起稍晚,但目前應用也非常廣泛。黑盒自動化測試原理是用程序和腳本模擬用戶的操作行爲,通過智能方式驗證軟件的關鍵檢查點。在桌面軟件和 Web 技術興盛時代,湧現出大量優秀的自動化測試工具如 QTP 和 webdriver,這些工具經過不斷完善已經逐步成熟,能夠較好地滿足傳統應用的自動化測試需求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"APP 的自動化測試包括以下這些:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"1、按測試目的劃分:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"功能測試:對產品和模塊的各個功能進行測試。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"性能測試:對系統的各項性能指標進行測試。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"壓力測試:測試軟件或系統的負載能力,挖掘隱患。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"兼容性測試:對產品和軟硬件之間的兼容性進行測試,比如軟件在各種不同安卓機型上的兼容性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"安全性測試:通過不同方法發現軟件的安全性問題,比如信息泄露、非法使用、惡意破壞等等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其他專項測試:比如弱網絡測試、耗電量測試、流暢度測試等等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2、如果根據軟件開發階段來劃分,每個階段又可以做:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"單元測試:對程序中的獨立模塊進行白盒測試,目的是檢驗軟件基本組成單位的正確性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"集成測試:通過對單元模塊進行組合測試,目的是驗證單元模塊之間的接口是否正確。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統測試:對整個系統進行完整測試,驗證整個系統的正確性與合規性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"迴歸測試:當軟件發生變更的時候,對這次變更可能受影響的功能模塊進行驗證。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"驗收測試:測試的最後一個階段,軟件發佈或者上線前確保軟件質量。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"3、其他常用測試概念:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"冒煙測試:冒煙測試是對軟件最基本的功能進行簡單測試,低成本的判斷軟件是否可測。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"冒煙測試來源於硬件的測試,當電路板做好後,首先會進行一次加電,如果沒有冒煙纔會開始進行接下來的測試,否則說明產品沒有達到最基本的質量要求,需要重新制作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"探索性測試:探索性更多的依賴測試人員的個人經驗或者特長,依靠的是測試人員的主觀能動性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"探索性測試的重要性可以參考遊戲測試領域,千千萬萬的玩家會在各種意想不到的環境下以意想不到的方式來進行遊戲,所以遊戲的測試者不僅要掌握系統的測試方法論、先進的測試工具以外,還要有豐富的遊戲經驗和探索的測試思維。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"功能集成測試、性能、兼容性、界面交互、訪問權限、用戶使用體驗等等,其中琳琅滿目的各種型號、版本的設備數不勝數。其中功能集成測試,在每次版本迭代過程中需要進行的功能特性驗證和已有功能迴歸,要求測試人員既能測試性新功能的各種特性,又要保證原有功能不受影響。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"隨着時間的推移,APP 的功能越來越完備,結構越來越複雜,每次代碼改動的影響範圍越來越廣,而且有些測試條件構造原本就很複雜,相應的迴歸範圍也會隨着越來越多,加上頻繁的迭代,這就使質量保證變爲過多的重複性有意義的勞動,在執行過程中也會一定程度上造成潛在的漏測風險。受限於經濟、人力等因素,想要在一定的時間內完全兼容性測試也十分困難。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"綜上所述:一是功能測試中的變化可能不好執行,二是迴歸頻繁重複,三是兼容性會成倍加劇以上兩種情況,所以爲了解決這些問題,提升工作效率,針對 APP 特點,需要開發一套 APP 自動化解決方案。支持打包之後自動執行測試用例,在多種機型兼容性測試,降低測試人員的重複勞動,提升測試質量,並可對執行結果的判斷是否通過的自動化測試系統。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2.2 UI 自動化發展趨勢"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"智能手機的應用帶來軟件測試技術新的革命,相比於傳統測試,手機測試在硬件上脫離了 PC 的傳統架構,和用戶的交互方式存在很大區別。手機軟件在使用上具有獨特的操作方式,比如用戶的滑動、觸摸和點擊等操作,如何實現手機客戶端上的自動化腳本執行成爲這類測試的難點。又由於 IOS,Android 兩大平臺的市場格局,大部分手機應用都需要支持多個平臺,它們的基礎架構不盡相同,使得手機自動化測試框架對兼容性有了更高要求。移動設備的智能化及普及化,也使越來越多的人享受着科技創新和發展所帶來的便捷生活。尤其是今年以來,全世界的網絡流量第一次歷史性的移動端超過 PC 端,這說明未來的趨勢是移動市場將佔據主導地位,移動設備上應用最廣泛的當屬 APP,因其操作便捷性,友好的交互,以及切實的解決用戶的問題,首當其衝的爲人們所廣泛使用。要做好手機客戶端的自動化測試,首先要解決測試腳本的健壯性和平臺的兼容性問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 APP 的軟件使用過程中,需要儘可能的減少用戶使用過程中遇到的各種問題,避免因 APP 出現的 bug 給用戶帶來使用上的不便,使原本帶來的便捷,變得不那麼“便捷”。所以在開發過程中,就需要把質量作爲重中之重,進行全面深入的質量測試。而互聯網行業瞬息萬變,要滿足日新月異的變化在業務和技術上持續不斷的推陳出新。因此 APP 的開發模式採用了軟件工程中的“快速迭代”模式,以應對快速變化帶來的各種影響,既要保證全面的測試覆蓋,又要用更小的時間成本就成了重點。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"近幾年手機客戶端自動化工具發展較快,出現了不少自動化框架,比如基於 Android 平臺的 UiAutomator 和 Robotium ,IOS 自帶的 Instrument 等,但是這些工具都沒有有效解決平臺兼容性問題,無法用一個統一的框架驅動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不同平臺測試,而且在識別客戶端內容和元素時也存在偏差,測試腳本不夠穩定健壯。目前具有良好兼容性且框架成熟穩定的工具是 Appium。Appium 是一個開源的、跨多平臺多語言的測試框架,相比於其它框架,它編寫測試腳本和運行測試時不需要對源碼重新編譯,在腳本的編寫和實現上也對編程語言沒有太多要求,測試更輕量靈活。此外,Appium 採用了 C\/S 架構 ,提供了一個統一的對外服務接口,使得客戶端或模擬器的交互和控制透明化。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"目前市面上已有一些 APP 的測試框架,有的跨端能力不強,支持 www 網頁測試,有的只支持 Android、IOS 移動端,同時支持 Android、IOS、www、小程序的少之又少,有的解決的功能測試的問題,但是基於快速變化需要維護的成本遠大於使用的成本,都沒有很好的解決痛點。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/b4\/e9\/b426fed442b5dc152620fecefffae9e9.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/90\/33\/9077b5e8c927e59eb45yy42db8c7d033.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TARS 系統通過自研方案,使用人工智能圖像識別技術,OCR 文字識別技術,以及通用 UI 元素查找引擎,可以做到跨端,跨平臺。並且基於 C\/S 框架,通過發 http 請求的方式操控移動設備,可以做到多語言支持。結合 Jenkins 等持續集成工具,搭建一套自研 UI 自動化測試系統沒有任何問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TARS 名稱來源於《星際穿越》這部著名的科幻電影,TARS 是電影中功能強大的智能機器人,輔助主角完成了很多艱鉅的任務。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/87\/89\/8768d87cc88dcbc943a2c3c12aee7289.jpg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3. 框架搭建"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.1 功能梳理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/83\/6e\/830737b59ce3682e58e31a0df3310e6e.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.2 框架結構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"採用 TARS+Jenkins+STF 作爲整體控制調度的系統,整體系統分爲應用層,控制層,設備層。通過設備集羣控制系統,選擇設備集羣,批量跑自動化測試 Case。Case 錄入系統可根據圖片,UI 元素定位識別來確定 Case 的操作步驟。幾乎所有系統採用了代碼量較少、對數據控制更靈活 python 作爲編程語言。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先是準備:控制系統通過設備管理平臺選擇好需要進行測試的設備,安裝好客戶端,配置好測試環境參數,如 AB,MocK。控制系統通修改響應數據,保存響應數據到某個 testcase 中(以備下次 MocK),直接返回服務器響應,還是獲取對應 testcase 的 Mock 數據,可控制 APP 端獲得的各種數據字段。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然後開始執行 testcase:在指定設備中調起客戶端,執行指定 testcase。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後是 diff 斷言階段,對比返回結果,請求參數,樣式圖片之間的差異。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"控制系統,正確的控制調度每一步所要執行何種動作。能夠正確轉發請求並截獲響應。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"Mock 系統能夠按照配置正確或把後端響應數據修改、保存再返給前端,或把 Mock 數據返給前端,並正確保存請求和響應的各個數據,完成 http 轉發代理。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"設備平臺,能根據現有掛載到平臺上的設備,判斷可用情況,提供設備共測試使用。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"Case 錄入,可讓用戶手工操作截圖,UI 元素識別,OCR 文字識別等方式錄入 Case,簡化 Case 錄入方法。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"圖片和數據 diff 系統,把測試數據和截圖準確 diff,排除可能的影響因素(如數據使用 Mock 接口)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/9a\/92\/9a134e971345ed341ea5346c8815c192.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/42\/af\/42d8d8255c2a325a75dd65359f5887af.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/8a\/6a\/8a4532473c178a0ae298d302aa35516a.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.3 元素查找方案"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自動化 Case 編寫需要測試框架層提供對界面元素進行操作的功能支持,其中最重要的就是對元素的查找和操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"編寫 Case 或者錄製 Case,我們需要的一個基礎能力就是如何準確又穩定的獲取到頁面元素。它決定了我們錄製 Case 的成本以及 Case 維護的成本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果查找不夠準確,將直接導致我們的 Case 運行不穩定,影響執行結果的準確性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果頁面結構發生變化,我們查找元素的方式不夠穩定,那每次功能迭代都需要重新對 Case 進行維護,那樣維護 Case 的成本遠大於使用自動化測試節省下來的測試成本,自動化測試也就沒有意義了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一個好的元素查找方式,是需要我們在 UI 自動化測試實踐過程中不斷探索改進的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"目前市面上流行的元素查找方案主要有三大類:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1. 通過 XPath 查找"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們獲取到的 UI 元素基本都是 XML 形式組織的,XPath 是一門在 XML 文檔中查找信息的語言,XPath 可以用來在 XML 文檔中查找元素和屬性。XPath 可以精準定位一個元素,但是它要依賴 XML 文檔結構的上下文,可能會受到佈局改動的影響,且在 iOS 上性能不佳。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2. 通過標識查找"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以通過給元素添加標識(accessibility、testID 等)來直接定位一個元素,或者也可以對文本內容進行匹配查找元素。這樣,即使我們的頁面結構發上了變化,但是需要操作的元素標識沒有變,那麼我們就不需要對代碼進行修改。但是我們需要對特定的元素添加標識,也有一定的工作量和維護成本。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3. 通過圖像識別查找"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"相比於白盒的元素查找方式,圖像識別這種無需關心頁面元素結構,非常自由的元素查找方式好像是自動化測試的未來。只需要通過對想操作的元素進行截圖,就可以根據圖片找到該元素並進行操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是目前這種方式還非常的不成熟,圖像查找的準確度比較差,而且不同的機型上,很可能圖片不能通用,需要針對機型重新截圖。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"embedcomp","attrs":{"type":"table","data":{"content":"
元素查找方式
優點
缺點
XPath定位方式靈活方便依賴上下文,界面佈局改動會影響定位
標識
定位準確穩定,不受佈局變化影響對於列表項等重複元素不好進行區分
圖像標識
更符合人的操作習慣定位不準確,需要適配各種分辨率"}}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在實際使用場景中,我們爲了滿足各種情況,結合使用以上三種元素定位方式。通過 POCO 庫對它們進行了封裝。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"POCO"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"POCO 是一個跨平臺的 UI 自動化開源框架。它底層封裝了各種自動化工具,例如:WDA、UIAutomation 等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"POCO 將其他 UI 自動化工具查找元素的功能進行了統一的封裝,爲 Case 編寫提供了方便靈活又平臺一致的元素操作 api。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"POCO 可以很方便的實現以下功能:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"元素屬性或 id 定位"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"元素相對位置查找"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"元素正則匹配"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"元素交互控制"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"POCO 獲取元素的方法是使用工廠模式來實現的,所以我們也可以很方便的擴展自定義的功能,比如圖像識別或 OCR 文字識別。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於 POCO 是基於 python 實現的,所以我們可以很方便的部署使用,調試腳本也非常容易。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.4 Case 編寫設計模式——Page Object Model"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"僅僅有框架層提供的功能支持還遠不能將 Case 維護的成本降低到一個可接受的範圍。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因爲我們在真正編寫 Case 的時候,需要編寫很多業務邏輯的代碼。我們一般會遇到兩個問題:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"編寫一個 Case 就會涉及比較多的界面操作,只編寫一個 Case 就已經非常耗時了。"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"業務邏輯或元素髮生變化,所有相關的 Case 都要改一遍,如果 Case 越來越多,維護起來將是一種災難。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以我們需要一種合理的設計,能夠儘量重用代碼,並將具體的業務邏輯進行抽象,不必寫很多繁瑣的元素查找操作代碼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Page Object Model (POM) 直譯爲“頁面對象模型”。這種設計模式旨在爲每個待測試的頁面創建一個頁面對象(class),將那些繁瑣的定位操作封裝到這個頁面對象中,只對外提供必要的操作接口。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"POM 將頁面定位和業務操作分開,分離了測試對象和測試腳本,如果 UI 更改頁面,測試腳本不需要更改,只需要更改頁面對象中的某些代碼就可以,提高了可維護性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如說,我們需要測試航班列表頁的搜索結果,可以直接調用首頁對象的功能跳轉到機票首頁,再調用機票首頁對象的選擇城市和日期搜索功能跳轉到航班列表頁,然後在航班列表頁對想要測試的數據進行斷言。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/4e\/2f\/4e994b0f48b66f8e0016dbc1e672592f.jpg","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/25\/0e\/251d756a40ae6c7cde1cb7f5a54e2e0e.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"如何實現 POM 設計模式"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一個 Page Object 對象,有兩方面特徵:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自身元素"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實現功能"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自身元素就是實實在在的頁面元素,實現功能就是這個頁面對象提供的業務功能,比如用戶登錄。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這樣,即使頁面元素和交互邏輯發生了變化,也可以只更改很少的代碼就可以讓相關的 Case 都能正常運行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"POM 設計模式有以下幾個設計規範:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"public 方法代表 Page 提供的功能"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"儘量不要暴露 Page 的內部細節"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"不要 assertion"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"方法可以返回其他 Page Objects"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Page Objects 不用代表整個頁面,可以是任意一個部分"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一樣的操作,不同的結果應該分開(正確登錄,錯誤登錄)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基於 POM 設計模式,我們做到了很低的 Case 維護成本。即使頁面進行了大改版,Case 也不需要變動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/00\/79\/006b23928b262f4c944ef5ff0321c579.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/58\/6f\/581ce34bb294ae89321d6b6519efb66f.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.5 Json Mock 方案"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實際運行 Case 的過程中,我們發現除了設備環境的問題,還有一個問題非常影響 Case 執行的成功率,就是 Case 需要的數據線上環境不能穩定的提供。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這個問題理論上提供一套寫死的數據進行 Mock 即可,但是很多 Case 需要驗證生單,這裏用 Mock 的數據會失敗,並且一定程度上,我們希望能夠使用實際的數據進行驗證,這樣可以同時發現線上接口的問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"於是我們就需要針對各種數據不穩定的問題具體問題具體分析。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"問題一:如何實時獲取測試需要的線上數據"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於我們業務的複雜性,數據在一定程度上是不可複用的。比如一套生單的數據,只能使用一次,下一次使用就失效了。另外,假如我們想測試往返合單的 Case,我們需要知道哪個航線有這種類型的報價。基於這個客觀情況,我們的測試團隊開發了一套基於線上數據的各種條件篩選的主流程參數生成接口。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"該接口會對歷史存儲的線上數據進行篩選,根據我們指定的數據特徵,返回給我們對應的線上報價。這樣,我們就可以準確的拿到特定的數據進行測試了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"問題二:如何對線上數據進行特定的處理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如線上經常會做一些活動,頁面上就可能非預期的彈出一些彈窗,阻攔我們的操作。如果我們的 Case 對這些情況都做對應的處理,那將會極大的加大 Case 的複雜度,而且要判斷各種情況也會降低 Case 執行速度。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還有我們測試生單可能需要不同類型的乘機人,我們要保證賬號中有這樣的乘機人類型。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於這種情況,我們就需要對線上數據進行實時的修改,以保證 Case 執行需要的數據環境。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們通過 json mock 工具來實現該功能。我們將對接口的處理寫在 Case 中,開始跑 Case 的時候,Case 將處理配置發送給客戶端,當客戶端獲取到數據以後,先被 Mock 工具攔截根據 Case 發送過來的處理配置對數據進行處理,比如刪除掉活動彈窗節點,或者替換乘機人數據。處理完以後再繼續將數據返回給業務代碼。這樣,就可以一定程度上將線上數據 Mock 成我們需要的數據,保證 Case 執行的正確率。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/72\/d9\/726cef7f4e071410bd055a5c6ff509d9.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.6 持續集成方案"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在實際的自動化使用場景中,我們一般是需要在日常的開發和提測過程中進行自動化測試。整個過程一般包括以下幾個階段:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"構建開發分支最新 beta 包"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"安裝到自動化設備上"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"設置運行環境"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"執行自動化 Case"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"執行結束髮送結果報告"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"而且,根據不同的使用場景,我們會執行不同的測試,比如:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"冒煙測試——迴歸重點 Case,保證提測的基本質量"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"業務迴歸測試——迴歸需求相關的業務 Case,輔助 QA 對歷史 Case 進行迴歸"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"性能測試——對比本次修改有沒有造成性能的下降"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"兼容性測試——測試在不同設備上的穩定性"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由人來操作肯定是不現實的,所以我們需要一個持續集成的工具來幫我們自動完成這些工作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們使用 jenkins 作爲我們持續集成的平臺,整個流程大致由下圖所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/75\/e8\/75b9c63e829d99b03bcf6b49653085e8.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在開發提測的時候,會自動觸發自動化任務的構建:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/55\/c4\/5560488395010419fa3d6eea05e1f1c4.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"QA 同學也在測試的時候可以選擇相關的業務 Case 進行迴歸。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4. 實踐過程"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/98\/a5\/9817e608b30d70d6545c950c298ce1a5.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"到9月份整體收益:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接入研發流程:109個項目(9月份57個)和執行205次(9月份90次),自動化迴歸節省人力約370 pd(9月約180 pd);接入發版流程:Q3 臨時灰度版、臨時版和月版共發版24次( iOS 6次和安卓18次),執行 UI 自動化100次左右(覆蓋主包和8個安卓渠道包),發版迴歸人力節約150+ pd;DailyRun:每天執行2次進行線上巡檢;缺陷攔截:發現2個崩潰和3個 P1 bug。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"作者介紹"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"鄒德文"},{"type":"text","text":",去哪兒網移動應用開發總監,負責機票售前與客戶端的管理工作。2012年加入去哪兒,先後任職於攻略和機票事業部,擅長客戶端和跨端技術棧RN,Flutter,對設備指紋有深入研究,主導了機票國內主流程RN遷移,TARS自動化測試系統的開發和推廣。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"崔宇"},{"type":"text","text":",2018年加入去哪兒網,主要負責機票主流程、機票 iOS客戶端、TARS UI自動化系統、iOS端指紋加固等方面的工作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule"},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"頭圖"},{"type":"text","text":":Unsplash"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"原文"},{"type":"text","text":":"},{"type":"link","attrs":{"href":"https:\/\/mp.weixin.qq.com\/s\/5W0IJLNpUSY5mkYc1MLz1Q","title":"","type":null},"content":[{"type":"text","text":"TARS 系統 —— UI 自動化解決方案"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"來源"},{"type":"text","text":":Qunar技術沙龍 - 微信公衆號 [ID:QunarTL]"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"轉載"},{"type":"text","text":":著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章