前面一篇文章实现了一个很简单的 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 加载出手机界面以后,鼠标点击下需要点击的位置,在页面中间有一行是点击位置的坐标,如图。

androiduiautomator2.0(AndroidUI自动化测试工具)(1)

weditor 显示点击点坐标

鼠标点击图中标注①位置的方框,可以切换显示具体坐标还是坐标百分比。由于安卓手机分辨率各式各样并不统一,所以使用坐标百分比在一定程度上可以增加代码的兼容性,方便相同的代码去操作不同型号的手机。

通过元素属性点击

通过坐标点击来操作手机会特别不稳定。因为实际运行过程中,由于手机的网络,性能等不确定因素,会造成我们的界面不能正常加载,而我们的代码无法判断界面是否已经加载出来,只会顺序的执行点击,造成脚本运行异常。

我们可以通过根据要点击的元素属性定位元素,然后再点击,我们还可以设定定位这个元素的超时时间,在这个时间内如果符合这个属性的元素出现则点击或执行其它操作,如果没出现则报错。

uiautomator2 主要通过以下方式来定位元素:

只列举了主要的定位方式,不常用的未列举。

上面三种属性定位方式开头都是精确匹配,后面是模糊匹配。

比如下图中的发送按钮:

androiduiautomator2.0(AndroidUI自动化测试工具)(2)

短信发送界面

上面的发送按钮我们可以用以下方式定位:

# 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 定位元素的方式会比较慢一些。下面举个例子:

androiduiautomator2.0(AndroidUI自动化测试工具)(3)

联系人添加群组

上面手机联系人应用里我们想要添加群组,发现“ ”这个按钮既没有 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 配置文件的一些知识。

,