推薦一款超好用的UI自動(dòng)化工具: UiAutomator2!
以下文章來(lái)源于測(cè)試開發(fā)技術(shù) ,作者狂師
1、 導(dǎo)讀
做過Android自動(dòng)化測(cè)試的同學(xué)想必都知道,最開始用的UiAutomator是Google提供的?來(lái)做安卓?動(dòng)化測(cè)試的?個(gè)Java庫(kù),基于Accessibility服務(wù),功能強(qiáng)?,但僅?持Java語(yǔ)?,并原生框架一開始并不?持Python。
后面一些Python技術(shù)愛好者,實(shí)在看不過去了,擼起袖子開發(fā)了一款UiAutomator Python版本,項(xiàng)目地址:
https://github.com/xiaocong/uiautomator
安裝及基本使用:
$ pip install uiautomator
from uiautomator import device as d
d.screen.on()
d(text="Clock").click()
2、UiAutomator2
當(dāng)然,今天介紹的主角是另外一框架框:UiAutomator2, 有人說UiAutomator2是不是UiAutomator的升級(jí)版本,功能確實(shí)是升級(jí),但兩個(gè)框架其實(shí)并沒有任何直接關(guān)系,甚至根本不是一波人開發(fā)的。
UiAutomator2框架是阿里的一位大神杰作。
簡(jiǎn)單介紹一下:
UiAutomator2是?個(gè)開源的?動(dòng)化測(cè)試?具,提供了?系列的Python API,?便測(cè)試?員?Python編寫?動(dòng)化測(cè)試腳本。
框架原理圖:
項(xiàng)目地址:
https://github.com/openatx/uiautomator2
隨著近幾年UiAutomator2框架的不斷迭代,功能也越發(fā)強(qiáng)大了,更多詳細(xì)功能和介紹建議讀者去項(xiàng)目官方地址查閱。
快速開始:
先準(zhǔn)備一臺(tái)開啟了開發(fā)者選項(xiàng)的安卓手機(jī),連接上電腦,確保執(zhí)行adb devices可以看到連接上的設(shè)備。
安裝uiautomator2
pip3 install -U uiautomator2
運(yùn)行python3 -m uiautomator2 init安裝包含httprpc服務(wù)的apk到手機(jī).
命令行運(yùn)行python打開python交互窗口。然后將下面的命令輸入到窗口中。
import uiautomator2 as u2
d = u2.connect() # connect to device
print(d.info)
3、UiAutomator2 特色功能
在Android自動(dòng)化測(cè)試過程中,經(jīng)常會(huì)遇到一些非期望需要操作的彈框,一旦出現(xiàn)這些非預(yù)期彈框,勢(shì)必對(duì)自動(dòng)化執(zhí)行穩(wěn)定帶來(lái)影響,今天要重點(diǎn)介紹的就是UIAutomator2中watcher(觀察者)的功能,或者稱之為監(jiān)聽者模式。
本質(zhì)上watcher的設(shè)計(jì)思路主要是為了解決一些彈窗或者 確認(rèn)框諸如此類問題。
具體watcher又該怎么用?
1、官方示例:
# 常用寫法,注冊(cè)匿名監(jiān)控
d.watcher.when("安裝").click()
# 注冊(cè)名為ANR的監(jiān)控,當(dāng)出現(xiàn)ANR和Force Close時(shí),點(diǎn)擊Force Close
d.watcher("ANR").when(xpath="ANR").when("Force Close").click()
2、用法說明:
d.watcher("WATCHER_NAME").when(text="確認(rèn)").click(text="確認(rèn)")
d.watcher("WATCHER_NAME2").when(text="OK").when(text="Wait").press("back", "home")
解釋:
第一句表示:注冊(cè)一個(gè)名字為“WATCHER_NAME”的watcher,當(dāng)存在UiSelector滿足“text='確認(rèn)'”的時(shí)候,執(zhí)行點(diǎn)擊操作
第二句表示:注冊(cè)一個(gè)名字為“WATCHER_NAME2”的watcher,當(dāng)滿足兩個(gè)條件時(shí),依次按back與home鍵。
3、回調(diào)示例
d.watcher.when("搶紅包").press("back")
d.watcher.when("http://*[@text = 'Out of memory']").call(lambda d: d.shell('am force-stop com.im.qq'))
# 回調(diào)說明
def click_callback(d: u2.Device):
d.xpath("確定").click() # 在回調(diào)中調(diào)用不會(huì)再次觸發(fā)watcher
d.xpath("繼續(xù)").click() # 使用d.xpath檢查元素的時(shí)候,會(huì)觸發(fā)watcher(目前最多觸發(fā)5次)
需要注意的是,即便完成watcher注冊(cè)了,并不代表已經(jīng)生效,需要手動(dòng)開啟它,有兩種方法:
# 方式一:?jiǎn)?dòng)所有的觀察者,并一直運(yùn)行在手機(jī)后臺(tái)
d.watchers.watched = True
# 方式二:強(qiáng)制運(yùn)行所有監(jiān)控
d.watchers.run()
其他常用Watcher監(jiān)控命令:
# 移除ANR的監(jiān)控
d.watcher.remove("ANR")
# 移除所有的監(jiān)控
d.watcher.remove()
# 開始后臺(tái)監(jiān)控
d.watcher.start()
d.watcher.start(2.0) # 默認(rèn)監(jiān)控間隔2.0s
# 強(qiáng)制運(yùn)行所有監(jiān)控
d.watcher.run()
# 停止監(jiān)控
d.watcher.stop()
# 停止并移除所有的監(jiān)控,常用于初始化
d.watcher.reset()
# 查看當(dāng)前所有watcher
d.watchers
# 判斷 某個(gè)/所有觀察者中的某個(gè) 是否已經(jīng)被觸發(fā)過
d.watcher("watcher_name").triggered
d.watchers.triggered
當(dāng)你使用方式一時(shí),在你不想使用它的時(shí)候,需要使用d.watchers.watched = False手動(dòng)關(guān)閉;當(dāng)然,你也可以使用下方的remove方法移除某個(gè)watcher,如此它便不會(huì)再生效,使用d.watchers.run(),則與方法一不同,它是在這條命令執(zhí)行的瞬時(shí)啟動(dòng)一次,結(jié)束后便不會(huì)再觸發(fā)。
4、案例模擬
本案例,假設(shè)自動(dòng)模擬打電話、掛電話操作,如果是使用d.watchers.watched = True,可以先執(zhí)行腳本,再進(jìn)行呼叫。
import uiautomator2 as u2
# 連接被叫設(shè)備
d = u2.connect('192.168.1.105:62001')
# 注冊(cè)一個(gè)名字為"Phone"的watcher,當(dāng)存在UiSelector的description="拒絕"時(shí),點(diǎn)擊
d.watcher("Phone").when(description="拒絕").click()
# 啟動(dòng)前,查看Phone是否已經(jīng)注冊(cè)且觸發(fā)過
print("Triggered Before:", d.watcher("Phone").triggered)
# 后臺(tái)啟動(dòng),持續(xù)監(jiān)控
d.watchers.watched = True
# 查看當(dāng)前已經(jīng)注冊(cè)的watchers
print("Watchers:", d.watchers)
# 啟動(dòng)后,查看Phone是否已經(jīng)注冊(cè)且觸發(fā)過
print("Triggered After:", d.watcher("Phone").triggered)
# 重置watchers的triggered狀態(tài)
d.watchers.reset()
# 移除Phone這個(gè)watcher
d.watcher("Phone").remove()
# 移除后,查看當(dāng)前已經(jīng)注冊(cè)的watchers
print("Watchers:", d.watchers)
也可以將啟動(dòng)方式改成d.watchers.run()如果是使用d.watchers.run(),則需要在電話已經(jīng)處于呼叫的過程中,觸發(fā)腳本,具體效果,可自行運(yùn)行嘗試。
好了,時(shí)間關(guān)系,今天就先分享到這,其他更多優(yōu)秀功能,讀者可自行研究。
作者:狂師
歡迎關(guān)注微信公眾號(hào) :Python測(cè)試社區(qū)