Appium With UiAutomator 2.0 實作及原理介紹

「UiAutomator 1.0 與 UiAutomator 2.0 差異以及 Appium 實作」 我們瞭解了使用 UiAutomator 2.0 的好處之後,那我們該如何在 Appium 實際使用 UiAutomator 2.0 框架呢?

在實作之前我們先來看看個有趣的實驗,簡易的列出了 appium-android-bootstrapappium-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-driverappium-uiautomator2-server 扮演著非常重要的角色,經過上一篇文章也能了解到 UiAutomator 2.0 並非是個已穩定的框架,相對來說運作其的自動化測試框架也會是 成長中 的狀態,這裡也會建議定期檢查 Appium 是否有更新版本,或是手動將 Appium 的 appium-uiautomator2-driverappium-uiautomator2-server 更新,確保自己的測試環境跟隨著框架成長而穩定。

參考資料

對「Appium With UiAutomator 2.0 實作及原理介紹」的一則回應

發表留言