Appium 怎麼運作:架構、capabilities 與最小起步

#Appium #capabilities #App 自動化 #QA 實戰

很多人第一次跑 Appium,是複製一段程式碼湊出 session,然後看到手機自己動起來。但下一步要改 caps、換裝置、接 CI 的時候就卡住了,原因幾乎都一樣:不知道那個 session 背後在做什麼。 我後來把失敗分類的時候發現,有一類失敗跟腳本、跟 App 都無關,是 server 後面那兩個 driver 出了狀況。不懂這層,這類失敗只會被當成「又 flaky 了」。 client server 架構 你寫的 pytest 是 client ,不直接控制手機,而是把動作翻譯成 HTTP 請求,透過 WebDriver 協定送給 Appium server : Appium server 是中繼層:收命令、轉譯,再叫對應的 driver 去操作裝置。UIAutomator2 負責 Android,XCUITest 負責 iOS。server 要先啟動,pytest 才能送命令;沒啟動就跑測試,拿到的是 ConnectionRefusedError,不是程式錯誤。 「忘了開 server」這件事我後來直接交給框架處理:driver fixture 發現 server 沒開就自己起一個,跑完只關自己起的那個,手動開的不動。這種每次都要記得的小事,交給程式比交給記性可靠。 capabilities 是什麼 capabilities(caps)是你告訴 server「要連哪台裝置、跑哪個 App」的設定包。server 收到後依 caps 決定叫 UIAutomator2 還是 XCUITest,以及要啟動哪個 Activity。 關鍵 caps:platform name(Android/iOS)、automation name(UiAutomator2/XCUITest)、device name(emulator 名或真機名)、app package + app activity(Android 的 app 入口)、udid(多台裝置時必填)。 Android 的標準寫法用 UiAutomator2Options,不要用裸 dict,打錯 cap 名稱時 Python 會直接報錯: 範例為了好讀把值寫死。實際專案裡,裝置名稱、UDID、port 我都不寫在程式裡,而是放在一份裝置設定檔,再允許環境變數覆蓋。原因很實際:不同裝置可能要裝不同版本的 App,caps 寫死就得為每台裝置各維護一份。 最小起步 起 session、做一個動作、關掉,這是最小的完整骨架: driver.quit() 放在 finally 兜底。沒關的 session 會佔住 server 資源,下次起 session 可能撞上殘留狀態,出現莫名其妙的錯誤。正式測試裡這件事交給 fixture 統一管,不用每個 test 自己寫 try/finally,下一篇會把這段包進去。 server 後面那兩個 driver 會壞 架構圖畫起來很乾淨,實際跑起來,最常出事的是箭頭最右邊那兩格。 UiAutomator2:指令不會乖乖排隊 UiAutomator2 在裝置上是單執行緒處理指令的。連續下指令時,指令之間會互相搶,結果是操作失效,嚴重一點整個 server 崩掉。我後來在框架裡定了一條規則:截圖、查找、點擊、滑動之間都要留緩衝,而且緩衝秒數一律用常數,不准到處寫 sleep(0.3)。等待這件事後面有一整篇會細講。 UiAutomator2 崩潰的原因,依常見程度排: 1. 背景程序被殺 :最常見。電池最佳化和 Doze 模式會把測試相關的程序殺掉,不只小米、OPPO、Vivo,Pixel、Samsung 也會。處理方式是把測試 App 和 Appium 相關程式加進電池最佳化的白名單。 2. 儲存空間不足 :內部儲存剩不到 1GB,就可能安裝或啟動失敗。 3. 版本不匹配 :Appium 和 uiautomator2 driver 版本對不上,或多個 Appium 實例互搶。 4. 裝置設定 :USB 偵錯沒開好,或動畫比例太高導致卡住,建議調成 0.5x 或關掉。 5. 殘留程序 :上一次的 UiAutomator2 server 沒清乾淨。 CI 用的 self hosted runner 跑久了一定會碰到這些狀況,所以我在跑測試前加了一段自動救援:檢查裝置連線、清掉 UiAutomator2 殘留、重啟 adb,確認可用才開始跑。 XCUITest:WDA 的兩個固定坑 iOS 這邊,Appium 靠裝在手機上的 WebDriverAgent(WDA)來操作。有兩個坑是固定會遇到的: 兩台 iPhone 同時跑,撞 8100 port。 WDA 預設用 8100,兩台同時起就會看到 port 被佔用。要讓每台裝置各自指定 wdaLocalPort。 免費 Apple 開發者帳號簽的 WDA,每 7 天失效。 這是 Apple 對 sideload 應用的限制,不是 WDA 的 bug。症狀是上週還好好的,這週所有 iOS 測試突然都起不來。 iOS 測試週期性全掛,先想 WDA 簽章是不是過期了,再查別的。我的 iOS 排查文件把這條放在最前面。 這些問題都不在你的測試程式碼裡,但會讓你的測試變紅。了解架構的最大用處就在這裡:測試掛掉的時候,你知道要去哪一層找原因。