前言
很早以前,我用uiautomator+JAVA實(shí)踐過(guò)Android App自動(dòng)化測(cè)試,不過(guò)今天要提的不是uiautomator,而是uiautomator2。聽起來(lái)uiautomator2像是uiautomator的升級(jí)版,但是這兩款框架僅僅是名字上比較相似,實(shí)際上沒有任何關(guān)聯(lián)。
一、uiautomator/uiautomator2的前生今世
項(xiàng)目地址:
https://github.com/openatx/uiautomator2
1.官方文檔介紹
2.梳理一下脈絡(luò)
- 先有的谷歌uiautomator,但是只支持java;
- 后來(lái)一個(gè)名為hexiaocong的開發(fā)者基于uiautomator封裝了Python/ target=_blank class=infotextkey>Python版本,支持python代碼運(yùn)行;
- 而受其啟發(fā),uiautomator2作者開發(fā)了uiautomator2。所以它們的誕生順序應(yīng)該是:uiautomator(谷歌版)-->uiautomator(python版)-->uiautomator2
3.三款框架對(duì)比
|
框架 |
支持語(yǔ)言 |
特點(diǎn) |
|
uiautomator |
java |
谷歌開源,僅支持Android |
|
xiaocong/uiautomator |
python |
開源,僅支持Android |
|
uiautomator2 |
python |
開源,僅支持Android |
二、uiautomator2簡(jiǎn)介
1.項(xiàng)目組成
- uiautomator-server:主服務(wù)
- minicap:實(shí)現(xiàn)實(shí)時(shí)屏幕投屏,以及實(shí)時(shí)截圖
- minitouch:用于精確實(shí)時(shí)控制設(shè)備
- atx-agent:運(yùn)行在設(shè)備上的駐守程序,go開發(fā),用于保活設(shè)備上相關(guān)的服務(wù)
- weditor:類似于uiautomatorviewer,專門為本項(xiàng)目開發(fā)的輔助編輯器
2.工作原理
1)各部分職責(zé)
- Python:編寫腳本,向移動(dòng)設(shè)備發(fā)起http請(qǐng)求;
- 移動(dòng)設(shè)備:運(yùn)行了封裝了uiautomator2的http服務(wù),解析python腳本發(fā)起的請(qǐng)求,并轉(zhuǎn)化成uiautomator2可識(shí)別的代碼;
2)運(yùn)行過(guò)程
- 移動(dòng)設(shè)備上運(yùn)行atx-agent守護(hù)進(jìn)程,隨后atx-agent啟動(dòng)uiautomator2服務(wù),默認(rèn)7912端口進(jìn)行監(jiān)聽;
- 在PC上編寫python腳本并執(zhí)行(相當(dāng)于發(fā)送 HTTP 請(qǐng)求到移動(dòng)設(shè)備的 server 端);
- 移動(dòng)設(shè)備通過(guò) wifi 或 USB 接收到 PC 上發(fā)來(lái)的 HTTP 請(qǐng)求,執(zhí)行指定的操作,從而操作移動(dòng)設(shè)備;
三、環(huán)境搭建
1.安裝uiautomator2
pip install uiautomator2pip install -U weditor # 安裝weditor
2.初始化設(shè)備
python -m uiautomator2 init
初始化成功會(huì)出現(xiàn)如下提示
當(dāng)PC或linux服務(wù)器連接了多臺(tái)adb device的情況下,“python -m uiautomator2 init”默認(rèn)初始化的是所有設(shè)備,若指定設(shè)備初始化,則需使用“--serial”參數(shù):
python -m uiautomator2 init --serial $SERIAL # $SERIAL為手機(jī)序列號(hào),可通過(guò)adb devices查看
3.init時(shí)都干了啥?
執(zhí)行“python -m uiautomator2 init”命令,會(huì)自動(dòng)往手機(jī)上安裝一堆東西:
- app-uiautomator.apk
- app-uiautomator-test.apk
- atx-agent
- minicap
- minitouch
更多信息詳見:
https://github.com/openatx/uiautomator2/wiki/Manual-Init
四、基礎(chǔ)操作
1.連接設(shè)備
uiautomator2提供了3種連接方式
1)通過(guò)WiFi連接
import uiautomator2 as u2d = u2.connect('10.0.0.1') # alias for u2.connect_wifi('10.0.0.1')print(d.info)
2)通過(guò)USB連接
import uiautomator2 as u2d = u2.connect('123456f') # alias for u2.connect_usb('123456f')print(d.info)
3)通過(guò)ADB WiFi連接
import uiautomator2 as u2d = u2.connect_adb_wifi("10.0.0.1:5555")# 等同于# + Shell: adb connect 10.0.0.1:5555# + Python: u2.connect_usb("10.0.0.1:5555")
2.命令行工具
1)截圖
uiautomator2 screenshot test.jpg
2)獲取當(dāng)前APP報(bào)名及Activity
uiautomator2 current
3)卸載應(yīng)用
uiautomator2 uninstall <package-name> # 卸載一個(gè)包uiautomator2 uninstall <package-name-1> <package-name-2> # 卸載多個(gè)包uiautomator2 uninstall --all # 全部卸載
4)停止應(yīng)用
$ uiautomator2 stop com.example.app # 停止一個(gè)app$ uiautomator2 stop --all # 停止所有的app
3.元素定位
1)常見定位方式
ui2支持 android 中 UiSelector 類中的所有定位方式,詳細(xì)可以查看官網(wǎng):
https://developer.android.com/reference/android/support/test/uiautomator/UiSelector,以下僅列出幾種常見的定位方式:
|
定位方式 |
描述 |
|
text |
通過(guò)文本定位 |
|
textMatches |
通過(guò)文本正則匹配定位 |
|
className |
通過(guò)類名定位 |
|
classNameMatches |
通過(guò)類名正則匹配定位 |
|
description |
通過(guò)desc屬性定位 |
|
descriptionMatches |
通過(guò)desc屬性正則匹配定位 |
|
resourceId |
通過(guò)resourceId定位 |
|
resourceIdMatches |
通過(guò)resourceId正則匹配定位 |
2)子元素定位及兄弟元素定位
① 子元素定位-child
#查找類名為android.widget.ListView下的Bluetooth元素d(className="android.widget.ListView").child(text="Bluetooth")# 下面這兩種方式定位有點(diǎn)不準(zhǔn)確,不建議使用d(className="android.widget.ListView").child_by_text("Bluetooth",allow_scroll_search=True)d(className="android.widget.ListView").child_by_description("Bluetooth")
② 兄弟元素定位-sibiling
#查找與google同一級(jí)別,類名為android.widget.ImageView的元素d(text="Google").sibling(className="android.widget.ImageView")
③ 鏈?zhǔn)秸{(diào)用
d(className="android.widget.ListView", resourceId="android:id/list") .child_by_text("Wi?Fi", className="android.widget.LinearLayout") .child(className="android.widget.Switch") .click()
3)相對(duì)定位
d(A).left(B),# 選擇A左邊的Bd(A).right(B),# 選擇A右邊的Bd(A).up(B), #選擇A上邊的Bd(A).down(B),# 選擇A下邊的B#選擇 WIFI 右邊的開關(guān)按鈕d(text='Wi?Fi').right(resourceId='android:id/widget_frame')
4) Xpath定位
Java uiautoamtor中默認(rèn)不支持xpath,這是屬于ui2的擴(kuò)展功能,速度會(huì)相比其它定位方式慢一些。在xpath定位中,ui2中的description 定位需要替換為content-desc,resourceId 需要替換為resource-id
# 只會(huì)返回一個(gè)元素,如果找不到元素,則會(huì)報(bào)XPathElementNotFoundError錯(cuò)誤# 如果找到多個(gè)元素,默認(rèn)會(huì)返回第0個(gè)d.xpath('//*[@resource-id="com.android.launcher3:id/icon"]')# 如果返回的元素有多個(gè),需要使用all()方法返回列表# 使用all方法,當(dāng)未找到元素時(shí),不會(huì)報(bào)錯(cuò),會(huì)返回一個(gè)空列表d.xpath('//*[@resource-id="com.android.launcher3:id/icon"]').all()
4.元素常用API
|
方法 |
描述 |
返回值 |
備注 |
|
exists() |
判斷元素是否存在 |
True,Flase |
@property |
|
info() |
返回元素的所有信息 |
字典 |
@property |
|
get_text() |
返回元素文本 |
字符串 |
|
|
set_text(text) |
設(shè)置元素文本 |
None |
|
|
clear_text() |
清空元素文本 |
None |
|
|
center() |
返回元素的中心點(diǎn)位置 |
(x,y) |
基于整個(gè)屏幕的點(diǎn) |
|
send_keys() |
發(fā)送文本 |
|
|
用法示例:
d(test="Settings").existsd.exists(text='Wi?Fi',timeout=5)
5.設(shè)備交互
1)單擊/雙擊
d(text='Settings').click() # 單擊d.double_click(x, y)d.double_click(x, y, 0.1) # 雙擊默認(rèn)時(shí)間間隔0.1s
2)長(zhǎng)按
d(text='Settings').longclick() # 長(zhǎng)按
3)滑動(dòng)
# "left", "right", "up", "down"d(text="Settings").swipe("up", steps=20) # 元素向上滑動(dòng),步長(zhǎng)20d(text="Settings").swipe("down", steps=20) # 元素向下滑動(dòng)d(text="Settings").swipe("left", steps=20) # 元素向左滑動(dòng)d(text="Settings").swipe("right", steps=20) # 元素向右滑動(dòng)
4)拖動(dòng)
d(text="Settings").drag_to(text="Clock", duration=0.25) # 拖動(dòng)到某個(gè)元素,時(shí)長(zhǎng)0.25秒d(text="Settings").drag_to(877,733) # 拖動(dòng)到屏幕某個(gè)坐標(biāo)點(diǎn),duration時(shí)長(zhǎng)默認(rèn)0.5秒
5)雙指操作(元素放大/縮小)
d(text="Settings").pinch_in() # 縮小d(text="Settings").pinch_out() # 放大
6)等待元素出現(xiàn)/消失
d(text="Settings").wait(timeout=3.0) # 等待元素出現(xiàn)d(text='Settings').wait_gone(timeout=20) # 等待元素消失,返回True False,timout默認(rèn)為全局設(shè)置的等待時(shí)間
7)屏幕滾動(dòng)
# 垂直滾動(dòng)到頁(yè)面頂部/橫向滾動(dòng)到最左側(cè)d(scrollable=True).scroll.toBeginning()d(scrollable=True).scroll.horiz.toBeginning()# 垂直滾動(dòng)到頁(yè)面最底部/橫向滾動(dòng)到最右側(cè)d(scrollable=True).scroll.toEnd()d(scrollable=True).scroll.horiz.toEnd()# 垂直向后滾動(dòng)到指定位置/橫向向右滾動(dòng)到指定位置d(scrollable=True).scroll.to(description="指定位置")d(scrollable=True).scroll.horiz.to(description="指定位置")# 垂直向前滾動(dòng)(橫向同理)d(scrollable=True).scroll.forward()# 垂直向前滾動(dòng)到指定位置(橫向同理)d(scrollable=True).scroll.forward.to(description="指定位置")# 滾動(dòng)直到System元素出現(xiàn)d(scrollable=True).scroll.to(text="System")
8)文本框操作
d.send_keys("test")d.clear_text() # 清空輸入框
9)toast操作
# 獲取toast,當(dāng)沒有找到toast消息時(shí),返回default內(nèi)容d.toast.get_message(timout=5,default='no toast')# 清空toast緩存d.toast.reset()
10)監(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()
更多api詳見:
https://github.com/openatx/uiautomator2
五、weditor元素定位
1.啟動(dòng)weditor服務(wù)
python -m weditor
2.訪問weditor
默認(rèn)端口17310,訪問地址:http://localhost:17310/,手機(jī)連接PC(確保已開啟USB調(diào)試模式),點(diǎn)擊Connect連接設(shè)備,當(dāng)Connect圖標(biāo)變?yōu)榫G色表示連接成功。
3.界面調(diào)試
weditor提供了所操作即所得式的元素定位方式,當(dāng)雙擊屏幕上的圖標(biāo)或按鈕,weditor界面右側(cè)的Coding框會(huì)同步展現(xiàn)元素操作的代碼,同時(shí)手機(jī)界面也會(huì)相應(yīng)同步切換頁(yè)面。
感謝
部分內(nèi)容參考以下:
https://www.cnblogs.com/fnng/p/8486863.html
https://testerhome.com/topics/11357
https://blog.csdn.NET/Master724/article/details/107962349?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163394586216780265448858%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163394586216780265448858&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-107962349.pc_search_ecpm_flag&utm_term=uiautomator2&spm=1018.2226.3001.4187







