在 「UiAutomator 1.0 與 UiAutomator 2.0 差異以及 Appium 實作」 我們瞭解了使用 UiAutomator 2.0 的好處之後,那我們該如何在 Appium 實際使用 UiAutomator 2.0 框架呢?
在實作之前我們先來看看個有趣的實驗,簡易的列出了 appium-android-bootstrap 與 appium-uiautomator2-server 兩者做同一件動作的 Appium Log 的差異,可以明顯的觀察到 appium-uiautomator2-server 分工的狀況,而 appium-android-bootstrap 則耗費許多時間在處理元件。
動作:在 Application 內找一 id 為
button_close
的元件
appium-android-bootstrap:
[AndroidBootstrap] [BOOTSTRAP LOG] [debug] Finding 'button_close' using 'ID' with the contextId: '' multiple: false [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Using: UiSelector[INSTANCE=0, RESOURCE_ID=com.skysoft.kkbox.android:id/button_close] [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Using: UiSelector[INSTANCE=0, RESOURCE_ID=android:id/button_close] [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Using: UiSelector[INSTANCE=0, RESOURCE_ID=button_close] [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Using: UiSelector[DESCRIPTION=button_close, INSTANCE=0] [debug] [AndroidBootstrap] Received command result from bootstrap [AndroidBootstrap] [BOOTSTRAP LOG] [debug] Returning result: {"status":7,"value":"No element found"}
appium-uiautomator2-server:
[debug] [MJSONWP] Calling AppiumDriver.findElement() with args: ["id","button_close","12b1e47f-7455-444c-a0c7-68100c6eb1fa"] [debug] [BaseDriver] Valid locator strategies for this request: xpath, id, class name, accessibility id, -android uiautomator [debug] [BaseDriver] Valid locator strategies for this request: xpath, id, class name, accessibility id, -android uiautomator [debug] [BaseDriver] Waiting up to 0 ms for condition [debug] [JSONWP Proxy] Proxying [POST /element] to [POST http://localhost:8200/wd/hub/session/f065b2c1-9750-49b2-821f-3eba6805c193/element] with body: {"strategy":"id","selector":"button_close","context":"","multiple":false}
由上述差別可以觀察到,在使用 UiAutomator 2.0 上,因為 appium-uiautomator2-server 提供了性能更佳的 Netty Server 來處理 Appium 與受測裝置之間的溝通,讓 Requests 跟 Actions 之間可以由不同單位來分工合作,但是我們可以觀察到 appium-android-bootstrap 是用同一個 Server Socket 來做「所有」的事情,導致動作的步驟被拆解成序列處理,在速度上的確很難提升,列個小小的有趣示範來查證 UiAutomator 2.0 的分工使用狀況,接下來就讓我們來實作 Appium With UiAutomator 2.0 吧!
如何在 Appium 運用 UiAutomator 2.0
以 Android 裝置為例,當 Client 發出一個 Request 要求 Appium 開一個 AndroidDriver 的 Session 時,Client 會將欲開啟 Session 的 desired capabilities
傳送給 Appium Server,而 Appium Server 則會依據 Client 給的 desired capabilities
創造一個 Session 橋接 Client Host 與受測裝置。如下:
def setUp(self): desired_caps = {} desired_caps['platformName'] = 'Android' desired_caps['platformVersion'] = '6.0' desired_caps['deviceName'] = 'Android Emulator' desired_caps['app'] = PATH('/.../.../testing.apk') self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
而在 desired capabilities
內有一參數名為 automationName
,若 Client 沒有定義此參數的值,Appium 則會使用預設值 uiautomator
,所以讓 Appium 搭載 UiAutomator 2.0 其實不難,Client 只需在 desired capabilities
內給定 automationName
參數為 uiautomator2
即可。如下:
def setUp(self): desired_caps = {} desired_caps['platformName'] = 'Android' desired_caps['platformVersion'] = '6.0' desired_caps['deviceName'] = 'Android Emulator' desired_caps['app'] = '/.../.../testing.apk' desired_caps['automationName'] = 'uiautomator2' self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
Appium With UiAutomator 2.0 運作原理及流程
瞭解了如何在 Appium 使用 UiAutomator 2.0 框架後,我們來關注一下背後其運作的原理吧!從 Client 發出 Request 後到 Client 收到 Appium 回饋的紀錄一共分為以下 5 大步驟:
1. Request
當 Client 指定好 desired capabilities
後即可發出 Request,如此一來當 Appium Server 收到 Client 端發出的 desired capabilities
時,收到給予的參數 automationName
Assign 為 uiautomator2
時,Appium Server 會呼叫相對應的 Appium Driver 來啟動 Session。
在此 Appium 即會呼叫
appium-uiautomator2-driver
作為相對應的 Driver
2. appium-uiautomator2-driver
當 appium-uiautomator2-driver
收到 Assign 後,會將 Server Modules 的兩個 APKs 安裝在受測裝置上,確保受測裝置與 Client Host 可如預期運作。
- appium-uiautomator2-server-vx.x.x.apk
- 負責處理所有的 Handler
- appium-uiautomator2-server-debug-androidTest.apk
- 內含一測試,旨在開啟 Netty Server — [GitHub] Test
3. AppiumServlet
AppiumServlet
會負責處理 Requests 並發送新 Requests 給相對應的 Handler。
4. Handler
當各個 Handler
收到 Requests 後會要求 UiAutomator 2.0 做相對應的動作。
其中
Handler
的狀態會統一被 AppiumResponse 紀錄。
5. AppiumResponse
AppiumResponse
紀錄好上述的動作後,會將紀錄回傳給 appium-uiautomator2-driver,最後再由 appium-uiautomator2-driver 將紀錄回饋給 Client。
以上為從 Client 發出 Requests 後一路至 Appium 回饋給 Client 的整理流程,綜合上述步驟,我們能發現 appium-uiautomator2-driver
與 appium-uiautomator2-server
扮演著非常重要的角色,經過上一篇文章也能了解到 UiAutomator 2.0 並非是個已穩定的框架,相對來說運作其的自動化測試框架也會是 成長中 的狀態,這裡也會建議定期檢查 Appium 是否有更新版本,或是手動將 Appium 的 appium-uiautomator2-driver
與 appium-uiautomator2-server
更新,確保自己的測試環境跟隨著框架成長而穩定。
對「Appium With UiAutomator 2.0 實作及原理介紹」的一則回應