UiAutomator2自动化测试框架带你玩转APP操作

前言

很早以前,我用uiautomator+java实践过Android APP自动化测试,不过今天要提的不是uiautomator,而是uiautomator2。听起来uiautomator2像是uiautomator的升级版,但是这两款框架仅仅是名字上比较相似,实际上没有任何关联。

一、uiautomator/uiautomator2的前生今世

 项目地址:GitHub - openatx/uiautomator2: Android Uiautomator2 Python Wrapper

1.官方文档介绍

2.梳理一下脉络
  • 先有的谷歌uiautomator,但是只支持java;
  • 后来一个名为hexiaocong的开发者基于uiautomator封装了python版本,支持python代码运行;
  • 而受其启发,uiautomator2作者开发了uiautomator2。所以它们的诞生顺序应该是:uiautomator(谷歌版)-->uiautomator(python版)-->uiautomator2
3.三款框架对比

框架

支持语言

特点

uiautomator

java

谷歌开源,仅支持Android

xiaocong/uiautomator

python

开源,仅支持Android

uiautomator2

python

开源,仅支持Android

二、uiautomator2简介
1.项目组成
  • uiautomator-server:主服务
  • minicap:实现实时屏幕投频,以及实时截图
  • minitouch:用于精确实时控制设备
  • atx-agent:运行在设备上的驻守程序,go开发,用于保活设备上相关的服务
  • weditor:类似于uiautomatorviewer,专门为本项目开发的辅助编辑器
2.工作原理

1)各部分职责

  • Python:编写脚本,向移动设备发起http请求;
  • 移动设备:运行了封装了uiautomator2的http服务,解析python脚本发起的请求,并转化成uiautomator2可识别的代码;

2)运行过程

  • 移动设备上运行atx-agent守护进程,随后atx-agent启动uiautomator2服务,默认7912端口进行监听;
  • 在PC上编写python脚本并执行(相当于发送 HTTP 请求到移动设备的 server 端);
  • 移动设备通过 WIFI 或 USB 接收到 PC 上发来的 HTTP 请求,执行指定的操作,从而操作移动设备;

三、环境搭建
1.安装uiautomator2
  1. pip install uiautomator2

  2. pip install -U weditor # 安装weditor

2.初始化设备
python -m uiautomator2 init

初始化成功会出现如下提示

当PC或Linux服务器连接了多台adb device的情况下,“python -m uiautomator2 init”默认初始化的是所有设备,若指定设备初始化,则需使用“--serial”参数:

python -m uiautomator2 init --serial $SERIAL  # $SERIAL为手机序列号,可通过adb devices查看
3.init时都干了啥?

执行“python -m uiautomator2 init”命令,会自动往手机上安装一堆东西:

  • app-uiautomator.apk
  • app-uiautomator-test.apk
  • atx-agent
  • minicap
  • minitouch

 更多信息详见:Manual Init · openatx/uiautomator2 Wiki · GitHub

四、基础操作
1.连接设备

uiautomator2提供了3种连接方式

1)通过WiFi连接


import uiautomator2 as u2


d = u2.connect('10.0.0.1') # alias for u2.connect_wifi('10.0.0.1')

print(d.info)

2)通过USB连接


import uiautomator2 as u2


d = u2.connect('123456f') # alias for u2.connect_usb('123456f')

print(d.info)

3)通过ADB WiFi连接


import uiautomator2 as u2


d = 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)获取当前APP报名及Activity

uiautomator2 current

3)卸载应用


uiautomator2 uninstall <package-name> # 卸载一个包

uiautomator2 uninstall <package-name-1> <package-name-2> # 卸载多个包

uiautomator2 uninstall --all # 全部卸载

 4)停止应用

  1. uiautomator2 stop com.example.app # 停止一个app

  2. uiautomator2 stop --all # 停止所有的app

3.元素定位

1)常见定位方式

ui2支持 android 中 UiSelector 类中的所有定位方式,详细可以查看官网:https://developer.android.com/reference/android/support/test/uiautomator/UiSelector,以下仅列出几种常见的定位方式:

定位方式

描述

text

通过文本定位

textMatches

通过文本正则匹配定位

className

通过类名定位

classNameMatches

通过类名正则匹配定位

description

通过desc属性定位

descriptionMatches

通过desc属性正则匹配定位

resourceId

通过resourceId定位

resourceIdMatches

通过resourceId正则匹配定位

2)子元素定位及兄弟元素定位

① 子元素定位-child


#查找类名为android.widget.ListView下的Bluetooth元素

d(className="android.widget.ListView").child(text="Bluetooth")

# 下面这两种方式定位有点不准确,不建议使用

d(className="android.widget.ListView")\

.child_by_text("Bluetooth",allow_scroll_search=True)

d(className="android.widget.ListView").child_by_description("Bluetooth")

② 兄弟元素定位-sibiling

  1. #查找与google同一级别,类名为android.widget.ImageView的元素

  2. d(text="Google").sibling(className="android.widget.ImageView")

③ 链式调用

  1. d(className="android.widget.ListView", resourceId="android:id/list") \

  2. .child_by_text("Wi‑Fi", className="android.widget.LinearLayout") \

  3. .child(className="android.widget.Switch") \

  4. .click()

3)相对定位

  1. d(A).left(B),# 选择A左边的B

  2. d(A).right(B),# 选择A右边的B

  3. d(A).up(B), #选择A上边的B

  4. d(A).down(B),# 选择A下边的B

  5. #选择 WIFI 右边的开关按钮

  6. d(text='Wi‑Fi').right(resourceId='android:id/widget_frame')

4) Xpath定位

Java uiautoamtor中默认不支持xpath,这是属于ui2的扩展功能,速度会相比其它定位方式慢一些。在xpath定位中,ui2中的description 定位需要替换为content-desc,resourceId 需要替换为resource-id

  1. # 只会返回一个元素,如果找不到元素,则会报XPathElementNotFoundError错误

  2. # 如果找到多个元素,默认会返回第0个

  3. d.xpath('//*[@resource-id="com.android.launcher3:id/icon"]')

  4. # 如果返回的元素有多个,需要使用all()方法返回列表

  5. # 使用all方法,当未找到元素时,不会报错,会返回一个空列表

  6. d.xpath('//*[@resource-id="com.android.launcher3:id/icon"]').all()

4.元素常用API

方法

描述

返回值

备注

exists()

判断元素是否存在

True,Flase

@property

info()

返回元素的所有信息

字典

@property

get_text()

返回元素文本

字符串

set_text(text)

设置元素文本

None

clear_text()

清空元素文本

None

center()

返回元素的中心点位置

(x,y)

基于整个屏幕的点

send_keys()

发送文本

用法示例:

  1. d(test="Settings").exists

  2. d.exists(text='Wi‑Fi',timeout=5)

5.设备交互

1)单击/双击

  1. d(text='Settings').click() # 单击

  2. d.double_click(x, y)

  3. d.double_click(x, y, 0.1) # 双击默认时间间隔0.1s

2)长按

d(text='Settings').longclick()  # 长按

3)滑动

  1. # "left", "right", "up", "down"

  2. d(text="Settings").swipe("up", steps=20) # 元素向上滑动,步长20

  3. d(text="Settings").swipe("down", steps=20) # 元素向下滑动

  4. d(text="Settings").swipe("left", steps=20) # 元素向左滑动

  5. d(text="Settings").swipe("right", steps=20) # 元素向右滑动

4)拖动

  1. d(text="Settings").drag_to(text="Clock", duration=0.25) # 拖动到某个元素,时长0.25秒

  2. d(text="Settings").drag_to(877,733) # 拖动到屏幕某个坐标点,duration时长默认0.5秒

5)双指操作(元素放大/缩小)

  1. d(text="Settings").pinch_in() # 缩小

  2. d(text="Settings").pinch_out() # 放大

6)等待元素出现/消失

  1. d(text="Settings").wait(timeout=3.0) # 等待元素出现

  2. d(text='Settings').wait_gone(timeout=20) # 等待元素消失,返回True False,timout默认为全局设置的等待时间

 7)屏幕滚动

  1. # 垂直滚动到页面顶部/横向滚动到最左侧

  2. d(scrollable=True).scroll.toBeginning()

  3. d(scrollable=True).scroll.horiz.toBeginning()

  4. # 垂直滚动到页面最底部/横向滚动到最右侧

  5. d(scrollable=True).scroll.toEnd()

  6. d(scrollable=True).scroll.horiz.toEnd()

  7. # 垂直向后滚动到指定位置/横向向右滚动到指定位置

  8. d(scrollable=True).scroll.to(description="指定位置")

  9. d(scrollable=True).scroll.horiz.to(description="指定位置")

  10. # 垂直向前滚动(横向同理)

  11. d(scrollable=True).scroll.forward()

  12. # 垂直向前滚动到指定位置(横向同理)

  13. d(scrollable=True).scroll.forward.to(description="指定位置")

  14. # 滚动直到System元素出现

  15. d(scrollable=True).scroll.to(text="System")

8)文本框操作

  1. d.send_keys("test")

  2. d.clear_text() # 清空输入框

9)toast操作

  1. # 获取toast,当没有找到toast消息时,返回default内容

  2. d.toast.get_message(timout=5,default='no toast')

  3. # 清空toast缓存

  4. d.toast.reset()

 10)监控操作

  1. # 移除ANR的监控

  2. d.watcher.remove("ANR")

  3. # 移除所有的监控

  4. d.watcher.remove()

  5. # 开始后台监控

  6. d.watcher.start()

  7. d.watcher.start(2.0) # 默认监控间隔2.0s

  8. # 强制运行所有监控

  9. d.watcher.run()

  10. # 停止监控

  11. d.watcher.stop()

  12. # 停止并移除所有的监控,常用于初始化

  13. d.watcher.reset()

五、weditor元素定位
1.启动weditor服务
python -m weditor

2.访问weditor

默认端口17310,访问地址:http://localhost:17310/,手机连接PC(确保已开启USB调试模式),点击Connect连接设备,当Connect图标变为绿色表示连接成功。

3.界面调试

weditor提供了所操作即所得式的元素定位方式,当双击屏幕上的图标或按钮,weditor界面右侧的Coding框会同步展现元素操作的代码,同时手机界面也会相应同步切换页面。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值