天天看點

Android UI 自動化測試工具 uiautomator2 介紹

作者:魚柒柒

前面一篇文章實作了一個很簡單的 Android UI 自動化測試的 demo,接下來會分兩篇文章分别介紹下 uiautomator2 和 pytest 的使用,最後會結合兩者完成一個 Android UI 自動化測試的項目。此篇文章則主要介紹 uiautomator2。

連接配接手機

首先你要已經安裝了 uiautomator2,安裝指令是:

pip install uiautomator2           

然後将已經開啟了開發者模式,且已允許調試的手機連接配接至電腦,然後運作以下指令:

python -m uiautomator2 init           

上面代碼會在你手機上安裝兩個用于控制手機的 app,可以這樣說 uiautomator2 實作自動化操作手機主要就是依靠的這兩個 app。其實如果不運作以上代碼,在運作 u2.connect() 的時候也會自動進行初始化操作,提前初始化可以稍微縮短代碼運作時間。一般該操作在一台手機上運作一次即可。

接着我們需要建立一個 .py 檔案,寫入以下代碼:

import uiautomator2 as u2

# connect() 不傳入任何參數的話會預設連接配接 device list 内的第一台手機,當電腦連接配接有多台裝置時,
# 可以傳入指定裝置的 device id,如果裝置時通過 WiFi 進行連接配接的,則可以傳入裝置在網絡上的位址
d = u2.connect()
print(d.app_current())           

啟動你手機上任意一個應用,運作以上代碼,正常情況下會輸出目前運作的這個應用的包名和程序。

如果前面的流程你都可以走通,那麼接下來就可以來使用代碼控制手機了,如果沒走通的話可以留言或私信我,也可以自己搜尋報錯資訊來找尋解決辦法。

操作手機

通過坐标點選

我們現在已經連上了手機,相當于我們已經手裡拿到了一台手機,如果我們要操作手機,我們肯定是要在手機螢幕上點選我們要點選的内容,我們就需要知道那個内容的坐标。那麼我們可以直接點選這個坐标,點選坐标可以使用

d.click(x, y)    # x, y 可以是具體的坐标,也可以是坐标百分比           

具體坐标的擷取可以使用 weditor,上一篇文章裡有安裝及使用方法。使用 weditor 加載出手機界面以後,滑鼠點選下需要點選的位置,在頁面中間有一行是點選位置的坐标,如圖。

Android UI 自動化測試工具 uiautomator2 介紹

weditor 顯示點選點坐标

滑鼠點選圖中标注①位置的方框,可以切換顯示具體坐标還是坐标百分比。由于安卓手機分辨率各式各樣并不統一,是以使用坐标百分比在一定程度上可以增加代碼的相容性,友善相同的代碼去操作不同型号的手機。

通過元素屬性點選

通過坐标點選來操作手機會特别不穩定。因為實際運作過程中,由于手機的網絡,性能等不确定因素,會造成我們的界面不能正常加載,而我們的代碼無法判斷界面是否已經加載出來,隻會順序的執行點選,造成腳本運作異常。

我們可以通過根據要點選的元素屬性定位元素,然後再點選,我們還可以設定定位這個元素的逾時時間,在這個時間内如果符合這個屬性的元素出現則點選或執行其它操作,如果沒出現則報錯。

uiautomator2 主要通過以下方式來定位元素:

隻列舉了主要的定位方式,不常用的未列舉。

  • text,textContains,textMatches,textStartsWith
  • resourceId,resourceIdMatches
  • className,classNameMatches

上面三種屬性定位方式開頭都是精确比對,後面是模糊比對。

比如下圖中的發送按鈕:

Android UI 自動化測試工具 uiautomator2 介紹

短信發送界面

上面的發送按鈕我們可以用以下方式定位:

# text
d(text="發送")

# resourceId
d(resourceId="com.android.mms:id/send_button")

# className,由于界面上 className 相同的元素會特别多,是以此種定位方式用到的比較少
# 一般會作為輔助定位
d(className="android.widget.TextView")

# 多種方式結合,通過一種方式無法唯一定位到某個元素時可以多種方式結合
d(text="發送", resourceId="com.android.mms:id/send_button")           

上面代碼隻是定位到了元素,也就是說通過執行上面任意一種定位方式的代碼,我們隻是找到了那個元素,如果要對該元素執行操作,則需要告訴腳本:

# 點選發送按鈕,逾時時間10秒,10秒内元素出現則點選,未出現報錯
d(resourceId="com.android.mms:id/send_button").click(timeout=10)

# 判斷發送按鈕是否出現,逾時時間為10秒,10秒内未出現該元素傳回 False
d(resourceId="com.android.mms:id/send_button").exists(timeout=10)

# 擷取按鈕的文本,逾時時間10秒
d(resourceId="com.android.mms:id/send_button").get_text(timeout=10)

# 輸入文本,此處需要元素是輸入框
d(text="請輸入内容").send_keys("測試")           

上面是我們平時最常用的對元素的操作,分别是點選元素、判斷元素是否出現、擷取元素的文本内容及輸入文本内容。中間兩項對我們自動化測試斷言比較有用,比如有的用例是點選某元素後另外一個元素會出現,就可以用 exists(),如果是我們要對某個元素文本進行斷言,則可以使用 get_text()。最後是向輸入框輸入文本,比如我們需要執行搜尋操作,我們便可以定位到搜尋輸入框,然後使用 send_keys() 輸入搜尋關鍵字。需要注意如果元素不是輸入框會報錯。

通過XPath方式定位元素

有些元素既沒有 text,id 等屬性,無法直接定位到的時候我們可以使用 XPath 的方式定位元素。XPath 定位元素的方式是通過元素層級,從有 text,id 等屬性的元素一層一層去找到我們需要的元素,是以一般 XPath 定位元素的方式會比較慢一些。下面舉個例子:

Android UI 自動化測試工具 uiautomator2 介紹

聯系人添加群組

上面手機聯系人應用裡我們想要添加群組,發現“+”這個按鈕既沒有 text,也沒有 id,如果想唯一定位到該元素就要用 XPath 的方式了。看右側的 Hierarchy 發現該元素屬于 id為 com.android.contacts:id/titleBtnBar 的元素,那麼我們可以這樣定位到該元素

d.xpath("//*[@resource-id='com.android.contacts:id/titleBtnBar']/android.widget.LinearLayout[3]/android.widget.Button")           

這裡主要介紹 uiautomator2 怎麼使用 XPath 定位,關于 XPath 表達式如何寫,可能需要很長的篇幅來寫,大家可以搜尋相關教程學習。

手機的其它操作

上面其實主要是操作應用的方法,uiautomator2 還有很多其它操作手機的方法,下面列舉一些

  • 安裝應用
d.app_install(data)  # data 可以是安裝包路徑,安裝包二進制資料或安裝包下載下傳連結           
  • 啟動應用
d.app_start("com.package_name")  # 傳入要啟動的應用的包名           
  • 停止應用
d.app_stop("com.example")  # 強行停止包名為 com.example 的應用
d.app_clear('com.example')  # 清除包名為 com.example 的應用的應用資料
d.app_stop_all(excludes=['com.example'])  # 強行停止所有正在運作的應用,除了包名為 com.example 的應用           
  • 截圖
d.screenshot("screenshot.png")  # 對手機進行截圖并儲存在腳本所在目錄

img = d(resourceId="com.android.mms:id/send_button").screenshot()
img.save("send_button.jpg")  # 對頁面上指定的元素截圖           
  • 推送檔案
# 向手機推送檔案
d.push("test.txt", "/sdcard/")  # 推送檔案至手機 /sdcard/ 目錄下
d.push("test.txt", "/sdcard/file.txt")  # 推送檔案至手機 /sdcard/ 目錄下并命名為 file.txt

# 從手機向電腦推送檔案
d.pull("/sdcard/file.txt", "test.txt")  # 将檔案推送至電腦,如果手機上沒有此檔案則會報錯           

寫在最後

此篇文章向大家介紹了 uiautomator2 的一些用法,下一篇文章會介紹 pytest 的一些基本使用方法,包括 fixture 方法、contest 檔案、pytest.ini 配置檔案的一些知識。

繼續閱讀