推荐一款超好用的UI自动化工具: UiAutomator2!

以下文章来源于测试开发技术 ,作者狂师

1、 导读
做过Android自动化测试的同学想必都知道,最开始用的UiAutomator是Google提供的⽤来做安卓⾃动化测试的⼀个Java库,基于Accessibility服务,功能强⼤,但仅⽀持Java语⾔,并原生框架一开始并不⽀持Python。

后面一些Python技术爱好者,实在看不过去了,撸起袖子开发了一款UiAutomator Python版本,项目地址:

https://github.com/xiaocong/uiautomator
安装及基本使用:

$ pip install uiautomator

from uiautomator import device as d

d.screen.on()
d(text="Clock").click()
2、UiAutomator2
当然,今天介绍的主角是另外一框架框:UiAutomator2, 有人说UiAutomator2是不是UiAutomator的升级版本,功能确实是升级,但两个框架其实并没有任何直接关系,甚至根本不是一波人开发的。

UiAutomator2框架是阿里的一位大神杰作。

简单介绍一下:

UiAutomator2是⼀个开源的⾃动化测试⼯具,提供了⼀系列的Python API,⽅便测试⼈员⽤Python编写⾃动化测试脚本。

框架原理图:



项目地址:

https://github.com/openatx/uiautomator2












随着近几年UiAutomator2框架的不断迭代,功能也越发强大了,更多详细功能和介绍建议读者去项目官方地址查阅。

快速开始:

先准备一台开启了开发者选项的安卓手机,连接上电脑,确保执行adb devices可以看到连接上的设备。

安装uiautomator2

pip3 install -U uiautomator2
运行python3 -m uiautomator2 init安装包含httprpc服务的apk到手机.

命令行运行python打开python交互窗口。然后将下面的命令输入到窗口中。

import uiautomator2 as u2

d = u2.connect() # connect to device
print(d.info)
3、UiAutomator2 特色功能
在Android自动化测试过程中,经常会遇到一些非期望需要操作的弹框,一旦出现这些非预期弹框,势必对自动化执行稳定带来影响,今天要重点介绍的就是UIAutomator2中watcher(观察者)的功能,或者称之为监听者模式。

本质上watcher的设计思路主要是为了解决一些弹窗或者 确认框诸如此类问题。

具体watcher又该怎么用?

1、官方示例:

# 常用写法,注册匿名监控
d.watcher.when("安装").click()

# 注册名为ANR的监控,当出现ANR和Force Close时,点击Force Close
d.watcher("ANR").when(xpath="ANR").when("Force Close").click()
2、用法说明:

d.watcher("WATCHER_NAME").when(text="确认").click(text="确认")
d.watcher("WATCHER_NAME2").when(text="OK").when(text="Wait").press("back", "home")





解释:

第一句表示:注册一个名字为“WATCHER_NAME”的watcher,当存在UiSelector满足“text='确认'”的时候,执行点击操作
第二句表示:注册一个名字为“WATCHER_NAME2”的watcher,当满足两个条件时,依次按back与home键。
3、回调示例

d.watcher.when("抢红包").press("back")
d.watcher.when("//*[@text = 'Out of memory']").call(lambda d: d.shell('am force-stop com.im.qq'))

# 回调说明
def click_callback(d: u2.Device):
    d.xpath("确定").click() # 在回调中调用不会再次触发watcher

d.xpath("继续").click() # 使用d.xpath检查元素的时候,会触发watcher(目前最多触发5次)
需要注意的是,即便完成watcher注册了,并不代表已经生效,需要手动开启它,有两种方法:

# 方式一:启动所有的观察者,并一直运行在手机后台
d.watchers.watched = True

# 方式二:强制运行所有监控
d.watchers.run()
其他常用Watcher监控命令:

# 移除ANR的监控
d.watcher.remove("ANR")

# 移除所有的监控
d.watcher.remove()

# 开始后台监控
d.watcher.start()
d.watcher.start(2.0) # 默认监控间隔2.0s

# 强制运行所有监控
d.watcher.run()

# 停止监控
d.watcher.stop()

# 停止并移除所有的监控,常用于初始化
d.watcher.reset()

# 查看当前所有watcher
d.watchers

# 判断 某个/所有观察者中的某个 是否已经被触发过
d.watcher("watcher_name").triggered
d.watchers.triggered

当你使用方式一时,在你不想使用它的时候,需要使用d.watchers.watched = False手动关闭;当然,你也可以使用下方的remove方法移除某个watcher,如此它便不会再生效,使用d.watchers.run(),则与方法一不同,它是在这条命令执行的瞬时启动一次,结束后便不会再触发。

4、案例模拟
本案例,假设自动模拟打电话、挂电话操作,如果是使用d.watchers.watched = True,可以先执行脚本,再进行呼叫。

import uiautomator2 as u2
 
# 连接被叫设备
d = u2.connect('192.168.1.105:62001')
 
# 注册一个名字为"Phone"的watcher,当存在UiSelector的description="拒绝"时,点击
d.watcher("Phone").when(description="拒绝").click()

# 启动前,查看Phone是否已经注册且触发过
print("Triggered Before:", d.watcher("Phone").triggered)
 
# 后台启动,持续监控
d.watchers.watched = True

# 查看当前已经注册的watchers
print("Watchers:", d.watchers)

# 启动后,查看Phone是否已经注册且触发过
print("Triggered After:", d.watcher("Phone").triggered)
 
# 重置watchers的triggered状态
d.watchers.reset()
 
# 移除Phone这个watcher
d.watcher("Phone").remove()
 
# 移除后,查看当前已经注册的watchers
print("Watchers:", d.watchers)
 
也可以将启动方式改成d.watchers.run()如果是使用d.watchers.run(),则需要在电话已经处于呼叫的过程中,触发脚本,具体效果,可自行运行尝试。

好了,时间关系,今天就先分享到这,其他更多优秀功能,读者可自行研究。

作者:狂师


欢迎关注微信公众号 :Python测试社区