杰瑞科技汇

Python uiautomator库如何高效实现UI自动化测试?

uiautomator 是一个非常强大的 Android UI 自动化测试框架,它最初是由 Sony 开发的,后来被 Google 接管并集成到了 Android 开发者工具中,其核心思想是通过控件的属性(如 text, resource-id, content-desc 等)来定位和操作 UI 元素,而不是依赖于屏幕的绝对坐标,这使得测试脚本更加稳定和可维护。

Python uiautomator库如何高效实现UI自动化测试?-图1
(图片来源网络,侵删)

核心概念:UiDeviceUiObject

在使用 uiautomator 时,你会和两个核心概念打交道:

  • UiDevice: 代表你的 Android 设备或模拟器,它是所有操作的入口点,负责设备级别的操作,

    • 模拟按键(Home, Back, Menu, Volume 等)
    • 获取屏幕截图
    • 检查屏幕是否锁定
    • 获取当前活动包名
  • UiObject: 代表屏幕上的一个 UI 控件(一个按钮、一个文本框、一个列表项等),你可以通过它来:

    • 获取控件的信息(文本、ID、内容描述等)
    • 对控件进行操作(点击、长按、输入文本、滑动等)
    • 判断控件是否存在、是否可见、是否被选中

如何安装和配置

1 环境准备

  1. 安装 Python: 确保你的电脑上安装了 Python (推荐 3.6+)。
  2. 安装 ADB (Android Debug Bridge): 这是 Android SDK 的一个工具,用于与设备通信。
    • Windows: 将 adb.exe 所在的目录(通常是 Android SDK\platform-tools)添加到系统的 PATH 环境变量中。
    • macOS / Linux: 通常会随 Android Studio 或 Homebrew 安装,同样需要确保其路径在 PATH 中。
  3. 开启开发者选项和 USB 调试:
    • 在你的 Android 设备上,进入 "设置" -> "关于手机"。
    • 连续点击 "版本号" 或 "内部版本号" 7次,直到提示 "你已处于开发者模式"。
    • 返回 "设置",找到 "开发者选项",开启 "USB 调试"。
  4. 连接设备:
    • 使用 USB 线连接手机和电脑,或者通过 Wi-Fi 连接(确保在同一局域网内)。
    • 在电脑上打开终端或命令提示符,运行 adb devices,如果能看到你的设备序列号,并且后面显示 device,则连接成功。

2 安装 Python 库

uiautomator 的 Python 封装库叫做 uiautomator2,它是对原始 uiautomator 的极大改进和扩展,是目前的主流选择。

Python uiautomator库如何高效实现UI自动化测试?-图2
(图片来源网络,侵删)
pip install --pre uiautomator2

3 初始化设备

首次使用时,需要初始化你的设备,安装必要的 ATX (Android Test eXpert) Agent 应用。

import uiautomator2 as u2
# 连接设备(USB连接或Wi-Fi连接)
# USB连接
d = u2.connect_usb() 
# Wi-Fi连接(需要先通过USB连接一次获取IP地址)
# d = u2.connect("192.168.1.100:5555")
# 初始化设备,安装或更新ATX Agent
d.session("com.android.settings") # 可以指定任意已安装的App包名来初始化

运行这段代码后,你的手机上会自动安装一个名为 "ATX" 的应用,这是 uiautomator2 的服务端。


核心 API 使用示例

下面是一些最常用的 API 示例,我们假设已经通过 d = u2.connect_usb() 获取了 UiDevice 实例 d

1 设备级别操作

# 1. 获取设备信息
print("设备名称:", d.info.get('productName'))
print("屏幕分辨率:", d.info.get('displayResolution'))
print("当前包名:", d.current_app()['package'])
# 2. 模拟按键
d.press("home")      # 按下 Home 键
d.press("back")      # 按下返回键
d.press("recent")    # 按下多任务键
# 3. 截图
d.screenshot("screen.png")
# 4. 解锁屏幕(需要配合密码或图案)
if d.info.get('screenOn') == False:
    d.unlock() # 需要先设置好锁屏密码

2 控件定位与操作

uiautomator2 提供了非常灵活的定位方式,核心是 d(resourceId="...")d(text="...") 这样的语法。

Python uiautomator库如何高效实现UI自动化测试?-图3
(图片来源网络,侵删)

定位方式:

  • d(resourceId="com.android.settings:id/title") - 通过资源ID定位(最推荐,最稳定)
  • d(text="WLAN") - 通过文本内容定位
  • d(description="搜索") - 通过内容描述定位
  • d(textContains="设置") - 文本包含
  • d(textStartsWith="Wi") - 文本以...开头
  • d(textMatches="^WLAN$") - 文本匹配正则表达式
  • d(className="android.widget.TextView") - 通过类名定位
  • d(packageName="com.android.settings") - 通过包名定位(通常用于切换应用)
  • d.enabled(True).clickable(True) - 通过属性筛选

操作方法:

  • .click(): 点击
  • .long_click(): 长按
  • .swipe("left", 0.5): 滑动(百分比方式)
  • .drag_to(target_obj): 拖拽到另一个控件
  • .input("Hello World"): 输入文本(适用于输入框)
# 示例:打开手机设置,进入 WLAN 设置
try:
    # 1. 启动设置应用
    d.app_start("com.android.settings")
    print("已启动设置应用")
    # 2. 定位 "WLAN" 文本并点击
    # 注意:不同手机/系统版本,resource-id 可能不同
    wlan_text = d(text="WLAN")
    if wlan_text.exists:
        wlan_text.click()
        print("已点击 WLAN")
    else:
        # 如果找不到,尝试用 resource-id 定位
        d(resourceId="com.android.settings:id/title", text="WLAN").click()
    # 3. 等待新页面加载,并查找一个可点击的开关
    # 使用 .wait_gone() 等待旧元素消失,表示页面已跳转
    wlan_text.wait_gone(timeout=5000) # 等待5秒
    # 定位一个开关控件
    wifi_switch = d(resourceId="com.android.settings:id/switch_widget")
    if wifi_switch.exists:
        print(f"WIFI 开关当前状态: {'开启' if wifi_switch.info['checked'] else '关闭'}")
        # 点击切换开关
        wifi_switch.click()
        print("已点击 WIFI 开关")
        # 再次检查状态
        d(resourceId="com.android.settings:id/switch_widget").wait.exists(timeout=5000)
        print(f"WIFI 开关新状态: {'开启' if wifi_switch.info['checked'] else '关闭'}")
    # 4. 返回上一页
    d.press("back")
except Exception as e:
    print(f"发生错误: {e}")
    d.press("home") # 发生错误时返回桌面,避免卡在某个页面
finally:
    # 5. 关闭设置应用
    d.app_stop("com.android.settings")
    print("已关闭设置应用")

高级功能

1 选择器

当需要更复杂的定位逻辑时,可以使用 Selector

from uiautomator2 import Selector
# 组合条件:查找包名是 "com.android.settings" 且文本是 "WLAN" 的控件
selector = Selector().package_name("com.android.settings").text("WLAN")
obj = d(selector)
if obj.exists:
    obj.click()

2 Toast 消息处理

Toast 是 Android 中短暂显示的小提示。uiautomator2 可以方便地监听和获取 Toast 消息。

# 启动一个会显示 Toast 的 App(这里用微信举例)
d.app_start("com.tencent.mm")
# 监听 Toast
toast_monitor = d.toast.get_message(5.0, default="") # 等待5秒获取最新的Toast
if toast_monitor:
    print(f"获取到 Toast: {toast_monitor}")
# 或者持续监听
print("开始监听 Toast (按 Ctrl+C 停止)...")
try:
    while True:
        msg = d.toast.get_message(2.0, default=None)
        if msg:
            print(f"Toast: {msg}")
except KeyboardInterrupt:
    print("停止监听 Toast")

3 手势操作

除了对单个控件操作,还可以在屏幕上进行自由的手势。

# 从屏幕 (50%, 50%) 滑动到 (10%, 90%)
d.swipe(0.5, 0.5, 0.1, 0.9)
# 在指定区域内滑动
d.swipe_ext("right", 0.8, scale=0.9) # 在屏幕90%的区域内向右滑动

4 与 Appium 的关系

uiautomatorAppium 经常被放在一起比较。

  • uiautomator: 是一个底层的、专门为 Android 设计的自动化框架。uiautomator2 是它的一个现代化 Python 封装。
  • Appium: 是一个跨平台的移动应用自动化测试框架,它内部就是调用了各平台的原生自动化框架(iOS 用 XCUITest,Android 用 uiautomator2)。

uiautomator2 是 Appium 在 Android 上的默认“引擎”,你可以直接使用 uiautomator2 进行快速、轻量级的自动化,也可以通过 Appium 来获得更统一的接口、更好的测试报告集成和并行执行能力。


最佳实践和注意事项

  1. 使用 resourceId 定位: 这是 uiautomator 的最大优势。resourceId 在 App 的版本更新中通常最稳定,远比文本或坐标可靠。
  2. 添加等待和异常处理: UI 操作是异步的,在操作之间添加等待(如 d.wait.exists(timeout=10000))或使用 try...except 块可以大大提高脚本的稳定性。
  3. 元素检查: 在操作前,使用 .exists.wait.exists() 检查元素是否存在,避免因元素未找到而报错。
  4. 清晰的脚本结构: 将常用的操作封装成函数,login(), search_item(keyword) 等,使脚本更易于维护和阅读。
  5. 清理工作: 在测试脚本的最后,最好能回到桌面或关闭测试应用,确保设备处于一个干净的状态,便于下次测试。
  6. 性能: uiautomator2 性能不错,但过于频繁的截图或复杂的控件查找仍可能影响速度,应根据需要使用。

希望这份详细的介绍能帮助你快速上手 uiautomator 库!

分享:
扫描分享到社交APP
上一篇
下一篇