處理 WebView 與 hybrid app:context 切換

#Appium #WebView #hybrid app #QA 實戰

寫了 locator、設好等待,測試跑起來卻一直拋 NoSuchElementException。打開 Appium Inspector 根本看不到那個元件。原因幾乎一定是:你在找網頁裡的元件,但 driver 還停在原生層。 我的專案裡有好幾個 WebView 頁面,而且偏偏都在很關鍵的流程上,切 context 這件事躲不掉。 為什麼找不到元件 Hybrid app 有兩層: 原生層 (按鈕、導覽列、底部 tab)和 WebView 層 (內嵌網頁)。Appium session 一啟動,預設落在 NATIVE APP context,只能看到原生元件。WebView 裡的 DOM 對 NATIVE APP 完全不可見,定位自然失敗。 列出與切換 context 切進 WebView 後,定位語法就跟 Selenium 一樣:用 CSS SELECTOR、XPATH、ID 都行,AppiumBy 的原生定位方式(ACCESSIBILITY ID、ANDROID UIAUTOMATOR 等)在 WebView 裡反而不適用。 Android vs iOS 的差異與坑 Android Android WebView 底層走 Chromedriver。 Chromedriver 版本要對上 App 內嵌的 Chrome/WebView 版本 ,版本不對,switch to.context 會直接丟例外或 context 列表只剩 NATIVE APP。 capabilities 裡加 chromedriverAutodownload,Appium server 會自動下載對應版本: 若測試環境不能連外網,就要手動指定: 另外,WebView 必須開啟 debug 模式,App 程式碼裡要有: 少了這行,Appium 看不到 WebView,contexts 只會回傳 ['NATIVE APP']。看到這個結果,先請開發確認 debug 模式有沒有開,再懷疑腳本。 iOS iOS 走 Safari remote debugger,不需要 Chromedriver。但有幾個坑: 1. 多個 WebView :一個畫面有多個 WebView 時,driver.contexts 會回傳多個 WEBVIEW 項目,不能直接取第一個。靠 index 挑也不穩,順序不保證。我的做法是用網址特徵挑:切進去看目前的 URL,含頁面特有的路徑(例如 promo)才是我要的那個。 2. 等 WebView 出現 :WebView 不一定在畫面出現的瞬間就對 Appium 可見,需要等待: 3. 模擬器 vs 真機 :iOS 模擬器上 WebView 切換通常順暢;真機要在裝置設定開啟「Web 檢閱器」,否則 remote debugger 連不上。 包進 BasePage context 切換每次手寫很累,也容易忘記切回來。這種重複行為適合收進 BasePage,用 context manager 包住,確保進出對稱: test 裡就像這樣用,WebView 操作收在 with 區塊,讀起來清楚,忘記切回的問題也消失: 後面講 BasePage 的那篇會把它繼續擴充,把等待、截圖、平台判斷都收進去,讓所有 Page Object 繼承同一套基底。 我專案裡的 WebView,實際長這樣 上面是通用的做法。實際跑下來,還有幾件事是文件不會告訴你的。 同一頁,兩個平台實作不一樣。 有一頁在 iOS 上是 WebView,在 Android 上卻是原生畫面。所以同一個「關掉這一頁」的動作,iOS 要切 context,Android 不用切。這個差異我收在 Page Object 裡,測試層看不到平台分支。 畫面會換技術。 某一版還是 WebView 的頁面,下一版可能改成原生元件,反過來也有。locator 一夕之間全部失效時,我第一步會先看近期的 commit,確認畫面是不是換了實作,再決定要不要修 locator。 RemoteDebugger 偶爾斷線。 WebView 操作有時會莫名丟出 targetId 相關的錯誤,重做一次又好了。這是連線斷了,腳本沒寫錯。我把不穩的 WebView 操作包進一個會自動恢復的函式:失敗時重新切進指定網址的 WebView,再重試,最多兩次。 按鈕會晚一點才出現。 有些頁面的關閉按鈕刻意延遲幾秒才顯示,前端用 delay XXXX 這類 class 控制。這種按鈕要用顯式等待等它出現,不要以為頁面載入完就點得到。 選方法先看按鈕長什麼樣。 我整理了一個簡單的判斷順序: 維護一份 WebView 頁面清單。 哪些頁面是 WebView、網址特徵是什麼、對應哪個 Page Object,我都記在一份清單裡,發現新的就補上去。WebView 頁面在 Inspector 裡跟原生頁面長得很不一樣,有清單可以查,新接手的人(或幾個月後的自己)就不用每次重新確認。