App 自动化,Appium 凭什么使用 UiAutomator2?

651 阅读5分钟

image

1. UiAutomator2 是什么

可能很多人对 UiAutomator2 和 UiAutomator 傻傻分不清楚

UiAutomator 是 Google 开发的一款运行在 Android 设备上的 UI 自动化测试工具,基于JAVA语言,使用它有一个限制,就是必须打包成 APK 或 JAR,然后上传到设备,才能运行

事实上,UiAutomator2 同样有 JAVA和 Python 版,今天我们聊的是 Python 版本的 UiAutomator2

至于 JAVA 版本的可以参考之前写的文章:点我查看

Python 版本的 UiAutomator2 项目地址:

github.com/openatx/uia…

2.Appium 和 UiAutomator2

作为移动端自动化的鼻祖,早期版本的 Appium 是基于 UiAutomator 和 Bootstrap.jar

其中,Bootstrap 在 Appium初始化的时候,被推送到 Android 设备上,负责监听 Appium 发过来的请求,并转换后发送给 UiAutomator 去处理,完成自动化操作

最新版本的 Appium 加入了对 UiAutomator2 的支持,原理进行了更新,功能和稳定性更加完善

原理图可以参考:

image

3.准备

在使用 UiAutomator2 之前,需要做如下准备

1、在 PC 端配置 Android 开发环境

2、使用 pip 安装 uiautomator2 依赖

# 安装依赖
pip3 install -U uiautomator2

# 如果需要截屏,需要安装pillow
pip3 install pillow

3、在手机上安装 atx-agent 应用 

ps:atx-agent 作为服务端,一直运行在后台

# 安装apk服务到手机上
python -m uiautomator2 init

4、安装 weditor

WEditor 通过 ip 连接手机,即可以实时查看 App 的界面元素信息

和 Appium DeskTop 类似,可以模拟点击、滑动操作、生成操作源码等功能

首先,通过 pip 安装 weditor 依赖包

# 基于浏览器查看 App 的界面元素
pip3 install -U weditor

然后,在命令行输入 weditor,会自动在浏览器中打开,接着通过 ip 连接对应的设备,即可以获取设备端当前界面的控件信息

信息内容包含:控件的层级关系、控件 ID、文本内容、坐标值等内容

image

4.实战一下

还是以闲鱼搜索商品为例,聊聊 UiAutomator2 的使用 

1、连接设备

使用 UiAutomator2 连接设备有 3 种方式,分别是:

  • 局域网设备 IP 地址

  • USB 连接 + 设备序列号

  • ADB + IP + 端口号

import uiautomator2 as u2

# 方式一:局域网设备ip地址
device = u2.connect(手机ip地址)

# 方式二:USB + 设备序列号
device = u2.connect(手机序列号)

# 方式三:ADB+
# 首先,设备用USB线连接PC,输入命令:adb tcpip 端口号进行映射
# 拔掉USB线,通过ip地址+端口号进行连接
device = u2.connect_adb_wifi(手机ip地址:端口号)

2、打开闲鱼 APP

调用上面 device 对象中 app_start() 方法,传入应用的包名作为参数可以打开应用

需要注意的是,方法中的第二个参数如果传入 True,可以冷启动 App,默认值为 False

# 打开应用
device.app_start(PACKAGE_NAME, stop=True)

3、点击搜索栏进入搜索界面

image

首先,全局设置一个隐式等待,保证查找元素的时候避免因为卡顿、网络导致的异常

# 隐式等待20s,保证控件加载完成
device.implicitly_wait(20)

然后,通过 WEditor 定位到搜索入口控件的基本信息

image

常用的 UiAutomator2 定位方式有 6 种,分别是:

  • ID 定位

  • Text 文本定位

  • Description 定位

  • ClassName 定位

  • Xpath 定位

  • 组合定位

例如:

# 常用的6种定位方式
# 方式一:ID定位
d(resourceId=元素ID).click()

# 方式二:Text文本定位
d(text="公众号:AirPython").click()

# 方式三:Description值定位
d(description="AirPython").click()

# 方式四:ClassName定位
d(className="android.widget.TextView").click()

# 方式五:Xpath定位
d.xpath("//*[@content-desc='AirPython']")

# 方式六:组合定位
d(className="android.widget.ListView", resourceId=元素ID)

需要指出的是,当界面属性值不唯一的时候,组合定位就显得很实用

本例直接使用 ID 去找到元素,然后执行点击操作,跳转到搜索界面

# 点击到搜索页面
device(resourceId="com.taobao.idlefish:id/search_bg_img_front",).click()

4、搜索

UiAutomator2 中提供了 send_keys() 方法,用于向输入框中设置文本

注意:参数 clear 如果设置为 True,则在输入内容之前,会先清空输入框,默认值为 False

# 输入内容
device.send_keys("Python", clear=True)

# 点击搜索按钮
device(text="搜索").click()

5、滑动

UiAutomator2 提供了两个方法用于滑动界面,分别是:

  • swipe_ext( 滑动方向 )

  • swipe( 开始 x 轴,开始 y 轴,结束 x 轴,结束 y 轴值,滑动时间 )

经过测试发现,滑动操作,swipe_ext() 使用效果不稳定,建议使用 swipe() 函数

for i in range(5):
    print('滑动一次')
    swipe_custom(device, 0.5, 0.8, 0.5, 0.2, 1.2)

另外,为了保证兼容不同分辨率的设备,建议通过屏幕百分比自定义滑动方法

def swipe_custom(device, start_x_percent, start_y_percent, end_x_percent, end_y_percent, during=1.0, interval=1):
    """
    自定义滑动,适配性更高
    :param device:
    :param start_x_percent:
    :param start_y_percent:
    :param end_x_percent:
    :param end_y_percent:
    :param during:
    :return:
    """
    # 获取屏幕的宽、高度
    width, height = device.window_size()
    device.swipe(start_x_percent * width, start_y_percent * height, end_x_percent * width, end_y_percent * height,
                 during)

    if interval > 0:
        sleep(interval)

6、关闭应用

在完成自动化操作后,就可以调用 app_stop() 方法强制关闭应用

# 停止App
device.app_stop(PACKAGE_NAME)

当然,可以在每次操作完,使用 UiAutomator2 提供的方法 app_clear() 清除 App 数据

# 清除App数据
# device.app_clear(PACKAGE_NAME)

5.最后

通过上面的实例,我们发现 UiAutomator2 相比 Appium,语法更简洁易懂,代码量也少了很多

但是由于 Uiautomator2 仅适用于 Android 端,Appium 拥有多语言、跨平台的特性,企业级自动化一般会选择后者

我已经将文中全部源码上传到后台,回复「 uiauto2 」即可获得全部源码

如果你觉得文章还不错,请大家 点赞、分享、留言下,因为这将是我持续输出更多优质文章的最强动力!

推荐阅读

带你用 Python 实现自动化群控(入门篇)

聊聊 Python 做微信小程序自动化,那些踩过的坑?

Python 自动化,Helium 凭什么取代 Selenium?