iOS自动化测试驱动工具探索
本文主要介紹了字節(jié) iOS 自動(dòng)化測(cè)試驅(qū)動(dòng)工具的探索過程及實(shí)現(xiàn)原理
作者:字節(jié)跳動(dòng)終端技術(shù)——陳友輝
一、背景
隨著業(yè)務(wù)的擴(kuò)張,單個(gè) App 的功能越來(lái)越多,工程復(fù)雜度越來(lái)越高,每天MR可達(dá)上百次,代碼變更可達(dá)上千處,航母級(jí)的 App 在這一點(diǎn)上更為嚴(yán)重。如何在頻繁的代碼變更中保障App質(zhì)量,成了各個(gè)業(yè)務(wù)的痛點(diǎn)。靠傳統(tǒng)的人工測(cè)試已無(wú)法滿足各業(yè)務(wù)的需求,我們需要將更多的測(cè)試場(chǎng)景自動(dòng)化。
自動(dòng)化測(cè)試需要將人工交互行為變成自動(dòng)化的原子操作。比如應(yīng)用安裝卸載、屏幕點(diǎn)拖拽及縮放、實(shí)體按鍵點(diǎn)擊、設(shè)備信息獲取、應(yīng)用啟停等等。這就需要一款工具來(lái)驅(qū)動(dòng) iOS 設(shè)備完成以上操作。這篇文章主要介紹字節(jié) iOS 自動(dòng)化測(cè)試驅(qū)動(dòng)工具 bdc 的探索過程及實(shí)現(xiàn)原理。
二、功能介紹
在介紹 bdc 的探索過程及實(shí)現(xiàn)原理之前,先介紹一下 bdc 的能力:
三、探索歷程
早期方案
在字節(jié)開始大規(guī)模建設(shè)自動(dòng)化建設(shè)時(shí),Android 已經(jīng)有較為完善的解決方案,包括其生態(tài)自帶的驅(qū)動(dòng)工具 adb 及開源的云真機(jī)管理平臺(tái) STF。但 iOS 在這方面相對(duì)滯后,主要是 iOS 缺少一款類似 adb 功能齊全且穩(wěn)定的驅(qū)動(dòng)工具。
早期 iOS 采用了 Facebook 開源的方案,Facebook 在驅(qū)動(dòng)工具方面先后開源了 wda 與 idb,wda 支持 UI 交互操作,idb 支持應(yīng)用管理,這在一定程度上滿足了我們的需求,基于這套方案,搭建了第一個(gè)版本的自動(dòng)化測(cè)試機(jī)架。
早期的機(jī)架也很簡(jiǎn)單,機(jī)器的規(guī)模也不大 經(jīng)過一段時(shí)間的實(shí)踐,我們遇到了以下幾個(gè)問題
- wda 部分接口執(zhí)行耗時(shí)較長(zhǎng),效率低下,無(wú)法滿足高頻率調(diào)度的需求
- idb 很多命令只支持模擬器,對(duì)真機(jī)不夠友好,無(wú)法滿足我們的功能擴(kuò)展
- 命令執(zhí)行失敗率高,工具穩(wěn)定性差,且出問題后難以排查
- 整套流程強(qiáng)依賴 Xcode 環(huán)境,規(guī)模化、自動(dòng)化部署成本高,無(wú)法應(yīng)對(duì)上千臺(tái)手機(jī)的部署
工具改良
UI 交互改造
為了解決上述問題,我們結(jié)合 wda 的實(shí)現(xiàn)思路,實(shí)現(xiàn)了一個(gè)更高效穩(wěn)定的 XCTest 工具。我們對(duì) XCTest 相關(guān)的接口進(jìn)行了review,并找到了XCTest 實(shí)現(xiàn)跨進(jìn)程調(diào)用最底層的接口。通過這些接口,可以直接調(diào)用 testmanagerd 進(jìn)程。隨后基于這些底層接口封裝了一套新的接口,可以實(shí)現(xiàn)屏幕的點(diǎn)拖拽、實(shí)體按鍵點(diǎn)擊、文本輸入等操作。相比 wda,在執(zhí)行速度和穩(wěn)定性上獲得大幅提升。
testmanagerd 進(jìn)程是一個(gè)開發(fā)者守護(hù)進(jìn)程,在 iOS 設(shè)備開啟開發(fā)者模式后,testmanagerd 進(jìn)程的鏡像會(huì)被掛載到 iOS 設(shè)備系統(tǒng)的 Developer 目錄,并被 launchd 進(jìn)程啟動(dòng)。XCTest 使用蘋果自帶的 XPC 機(jī)制與 testmanagerd 進(jìn)行通信,利用 NSXPCConnection,只需知道服務(wù)的 id 即可建立通信,testmanagerd 服務(wù)的 id 可在其鏡像文件里找到。鏡像的路徑位于:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport
解壓鏡像后,可在 Library/LaunchDeamons 目錄下找到名為 com.apple.testmanagerd 的 plist 文件,打開后可以看到其 id 為 com.apple.testmanagerd(iOS14 后 id 有所變動(dòng))
設(shè)備交互工具
搞定 UI 交互后,接下來(lái)就需要找到能完美支持設(shè)備管理、應(yīng)用管理、沙盒文件管理的方案。一開始我們也是想基于 idb 進(jìn)行優(yōu)化,但隨后發(fā)現(xiàn) idb 內(nèi)部使用了大量的 api,這些 api 絕大部分缺少文檔,優(yōu)化成本較高,且這些私有 api 會(huì)隨著 Xcode 版本的變動(dòng)而更新,維護(hù)會(huì)很麻煩。所以放棄了 idb 轉(zhuǎn)而尋找其他替代方案。
這時(shí)我們發(fā)現(xiàn)了另一個(gè)開源實(shí)現(xiàn) libimobiledevice,libimobiledevice 支持通過 USB 的方式與 iOS 設(shè)備進(jìn)行通信,且支持應(yīng)用安裝卸載、設(shè)備信息獲取、沙盒文件操作等功能。libimobiledevice 在使用體驗(yàn)上,操作簡(jiǎn)單,功能穩(wěn)定。但缺點(diǎn)是功能有限,不能完全符合我們的訴求,接下來(lái)我們對(duì) libimobiledevice 的實(shí)現(xiàn)原理進(jìn)行了探究。
基于 USB 與 iOS 設(shè)備通信
蘋果自身有一些 Mac App 需要通過 USB 跟 iOS 設(shè)備進(jìn)行通信,比如 iTunes、XCode 及其套件等等。雙端通信需要基于一定的協(xié)議,通過USB通信需要使用USB協(xié)議,但USB協(xié)議具有一定的局限性,直接使用成本較高。所以蘋果在USB協(xié)議的基礎(chǔ)上支持了TCP通信的能力,以此減小使用成本。
蘋果通過 usbmuxd 來(lái)提供基于 USB 實(shí)現(xiàn) TCP 通信的能力。usbmuxd是一個(gè)守護(hù)進(jìn)程,它在 USB協(xié)議上實(shí)現(xiàn)了多路 TCP 連接,可以讓應(yīng)用層無(wú)感知的基于 USB 通道進(jìn)行 TCP 通信。
macOS 上的 usbmuxd 配置文件位于/Library/Apple/System/Library/LaunchDaemons,打開后如下:
usbmuxd 的配置文件記錄了加載屬性、服務(wù)名稱、可執(zhí)行文件路徑、socket 屬性等信息。從上面的配置文件可以看到,usbmuxd 創(chuàng)建了一個(gè) Unix 域的 socket。這個(gè) socket 主要用于跟上層應(yīng)用建立連接,實(shí)現(xiàn)跨進(jìn)程通信。基于 usbmuxd 進(jìn)行網(wǎng)絡(luò)通信的流程如下:
發(fā)現(xiàn)iOS設(shè)備系統(tǒng)服務(wù)并完成調(diào)用
從上述 usbmuxd 的通信流程可知,想要跟iOS設(shè)備中的服務(wù)進(jìn)行通信,只需要知道具體服務(wù)的端口即可。那么服務(wù)端口該如何獲取?一般有兩種方式,一種是直接hardcode,另一種是動(dòng)態(tài)獲取。iOS設(shè)備內(nèi)部的服務(wù)眾多,如果全部 hardcode,其維護(hù)成本較高,且安全性及穩(wěn)定性較低。如果是動(dòng)態(tài)獲取,那么獲取的方式將成為另一個(gè)問題,因?yàn)閯?dòng)態(tài)獲取本身也需要通信。
蘋果則采用了兩者結(jié)合的方式。蘋果在iOS系統(tǒng)內(nèi)部增加了一個(gè) lockdownd 的守護(hù)進(jìn)程,這個(gè)守護(hù)進(jìn)程以 root 特權(quán)運(yùn)行,具有訪問 iOS 系統(tǒng)信息的能力,且運(yùn)行在固定的端口。lockdownd 的配置文件如下,其路徑位于 iOS 系統(tǒng)的/System/Library/LaunchDaemons/目錄。
由此可以看出,lockdownd 分別支持 Unix 域的 socket 與非 Unix 域的 socket,對(duì)于非 Unix 域的socket,其監(jiān)聽的端口固定在62078。
當(dāng) PC 端想要跟 iOS 設(shè)備中的某個(gè)服務(wù)進(jìn)行通信時(shí),先通過 lockdownd 查找對(duì)應(yīng)服務(wù)的端口,然后再跟對(duì)應(yīng)的服務(wù)建立 socket 連接,其流程如下:
libimobiledevice 就是利用以上流程對(duì) iOS 設(shè)備中的服務(wù)進(jìn)行了調(diào)用,比如在操作沙盒文件時(shí),就是調(diào)用了 iOS 設(shè)備中的 afc、house_arrest 服務(wù)。
服務(wù)類型
搞清楚了調(diào)用流程,那么 iOS 設(shè)備中都有哪些服務(wù)呢?iOS 系統(tǒng)服務(wù)主要分為兩類:一類是debug相關(guān)服務(wù),打開開發(fā)者選項(xiàng)后才具備相應(yīng)服務(wù)。另一類是非 debug 服務(wù),默認(rèn)都具備。
debug 相關(guān)服務(wù)的配置文件及可執(zhí)行文件都被打包放在了 Xcode 中,位于/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/目錄,當(dāng) iOS 設(shè)備連接 Xcode 時(shí),Xcode 會(huì)自動(dòng)將此目錄下對(duì)應(yīng)的DeveloperDiskImage掛載到 iOS 系統(tǒng)中。其包含的服務(wù)如下: 上述提到的 testmanagerd 就位于其中。
非debug服務(wù)位于iOS系統(tǒng)的/System/Library/LaunchDaemons目錄。通過越獄后,我們可以查看/System/Library/LaunchDaemons目錄下的內(nèi)容,以下是部分服務(wù)的截圖,可以看到,服務(wù)非常之多。
能力擴(kuò)展
搞清楚 libimobiledevice 實(shí)現(xiàn)原理后,基于這個(gè)思路,我們又自行探索了其他一些服務(wù)的能力,這其中就包括 Xcode 相關(guān)的服務(wù)。Xcode 為開發(fā)者提供了專業(yè)、穩(wěn)定的工具集,而 Xcode 的工具集也是利用以上機(jī)制與 iOS 設(shè)備進(jìn)行通信。基于Xcode 的能力,我們實(shí)現(xiàn)了 Trace 采集、設(shè)備應(yīng)用管理等功能。
支持 Linux
工具的問題解決了,接下來(lái)就是部署的問題。我們需要面對(duì)上千臺(tái) iOS 設(shè)備接入及每天上萬(wàn)次的服務(wù)調(diào)度,且設(shè)備之間的環(huán)境需要相互隔離,互不干擾。所以在設(shè)備及工具的部署上需要簡(jiǎn)單、高效。比較好的解決方案是采用 docker 部署,每臺(tái)設(shè)備及其對(duì)應(yīng)的驅(qū)動(dòng)工具都用 docker 分離開,這樣能做到環(huán)境隔離,且部署簡(jiǎn)單。但 Mac 對(duì) docker 的支持并不那么友好,且我們的工具本身依賴 Xcode 環(huán)境。
既然 Mac 對(duì) docker 的支持不友好,那我們是否能擺脫對(duì) Mac 的依賴,將設(shè)備及工具部署在 Linux 上。順著這個(gè)思路,我們開始了對(duì)工具的第二次改造。
支持 XCTest 啟動(dòng)
工具對(duì) Mac 的依賴主要來(lái)源于 XCTest 工具的啟動(dòng),類似于 wda。我們將 XCTest 的接口封裝在了一個(gè)普通的 App 里,然后在這個(gè)普通的 App 里搭建一個(gè) websocket server,這樣就可以通過網(wǎng)絡(luò)與這個(gè) App 通信,實(shí)現(xiàn) XCTest API 的調(diào)用。但經(jīng)過嘗試后,發(fā)現(xiàn)普通的 App 調(diào)用 XCTest API 并不會(huì)產(chǎn)生預(yù)期的效果。所以還需要一些特殊的操作才能使普通App具備調(diào)用 XCTest API 的能力。
我們從正常的 XCTest-Runner 入手探索其啟動(dòng)流程。以home鍵的點(diǎn)擊方法為切入點(diǎn),通過 LLDB 追蹤testmanagerd 進(jìn)程中接口的調(diào)用流程,發(fā)現(xiàn)了如下關(guān)鍵的接口:
_IDE_authorizeTestSessionWithProcessID:分析后發(fā)現(xiàn),testmanagerd 會(huì)維護(hù)一個(gè)進(jìn)程白名單,只有將 App 的進(jìn)程 ID 加到這個(gè)白名單里,這個(gè)App 才具備調(diào)用 XCTest API 的能力。而上述注冊(cè)白名單的接口則可以通過前面提到的 lockdownd 的方式調(diào)用。基于此,我們實(shí)現(xiàn)了擺脫對(duì) Mac 環(huán)境的依賴,在 Linux 實(shí)現(xiàn)了 docker 化部署。
四、運(yùn)行效果
bdc 工具上線已有一年多。目前支撐了公司自動(dòng)化測(cè)試平臺(tái)上千臺(tái) iOS 設(shè)備每日上萬(wàn)次的設(shè)備調(diào)度及測(cè)試任務(wù)執(zhí)行。自動(dòng)化測(cè)試平臺(tái)涵蓋了穩(wěn)定性、UI、性能、單元測(cè)試等多項(xiàng)測(cè)試能力,服務(wù)公司上百個(gè)業(yè)務(wù)。
設(shè)備機(jī)架從原有的簡(jiǎn)陋設(shè)備已升級(jí)為全球機(jī)房,服務(wù)于全球業(yè)務(wù)。
🔥 火山引擎 APMPlus 應(yīng)用性能監(jiān)控是火山引擎應(yīng)用開發(fā)套件 MARS 下的性能監(jiān)控產(chǎn)品。我們通過先進(jìn)的數(shù)據(jù)采集與監(jiān)控技術(shù),為企業(yè)提供全鏈路的應(yīng)用性能監(jiān)控服務(wù),助力企業(yè)提升異常問題排查與解決的效率。目前我們面向中小企業(yè)特別推出「APMPlus 應(yīng)用性能監(jiān)控企業(yè)助力行動(dòng)」,為中小企業(yè)提供應(yīng)用性能監(jiān)控免費(fèi)資源包。現(xiàn)在申請(qǐng),有機(jī)會(huì)獲得60天免費(fèi)性能監(jiān)控服務(wù),最高可享6000萬(wàn)條事件量。
👉 點(diǎn)擊這里,立即申請(qǐng)
總結(jié)
以上是生活随笔為你收集整理的iOS自动化测试驱动工具探索的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 16.jsp结构
- 下一篇: html5 筛子,html5摇骰子游戏