Android自动化测试入门:uiautomator2环境搭建与实战脚本编写
1. 从手动点点点到脚本自动化为什么我们需要uiautomator2做Android应用测试或者自动化操作的朋友肯定都经历过这样的场景为了验证一个功能或者复现一个偶现的Bug需要一遍又一遍地在手机上重复点击、滑动、输入。日复一日这种机械劳动不仅枯燥效率低下更重要的是它无法保证每次操作的一致性——人的手指有误差注意力会分散而机器不会。这就是自动化测试工具存在的核心价值。在Android自动化领域uiautomator2简称u2是一个绕不开的名字。它不像Appium那样庞大而复杂也不像Monkey那样随机而无序。u2定位清晰一个基于Python的、轻量级的、直接与Android系统底层UI自动化框架UiAutomator对话的工具。它让你能用简洁的Python代码精准地控制手机上的任何一个UI元素实现从环境准备、应用安装、UI操作到断言验证的全流程自动化。今天我就以一个多年移动端测试开发者的视角带你从零开始手把手搭建uiautomator2的完整工作环境并用一个实实在在的例子演示如何让它为你工作。你会发现从“手动点点点”到“脚本自动化”其实只差一个清晰、正确的环境配置。2. 环境搭建全景图理清工具链与依赖关系在开始敲命令之前我们必须先理清uiautomator2正常工作需要哪些“零件”。很多新手卡在环境问题上根本原因是对整个工具链的依赖关系不清晰。uiautomator2不是一个孤立的工具它是一个“桥梁”和“控制器”。它的工作模式是在你的电脑PC上运行Python脚本脚本通过HTTP协议与安装在手机上的一个守护服务atx-agent通信atx-agent再调用手机系统自带的UiAutomator框架来执行具体的UI操作。因此整个环境涉及PC端和Android设备端两部分并且需要一条稳定的通道将它们连接起来。PC端核心依赖Python 3.6这是运行我们自动化脚本的语言环境。uiautomator2是一个Python库。uiautomator2 Python库通过pip安装的核心工具包。ADBAndroid Debug Bridge这是整个Android开发的基石也是PC与手机通信的“万能钥匙”。u2在初始化设备时重度依赖ADB命令来安装atx-agent等组件。Android设备端核心组件开发者选项与USB调试这是允许PC通过ADB控制手机的前提必须开启。atx-agent由uiautomator2项目提供的守护进程由PC端通过ADB推送到手机并启动。它负责接收来自PC的HTTP请求并转化为对UiAutomator的调用。UiAutomatorAndroid系统自带的UI测试框架从Android 4.3API 18开始提供。它拥有最高权限可以获取和操作系统内任何应用的界面元素。连接通道USB数据线最稳定、最推荐的方式。无线网络Wi-Fi在USB连接初始化后可以切换到无线连接方便同时操作多台设备。理清了这个关系我们的搭建步骤就有了明确的路线图先配置好PC端的Python和ADB然后通过USB连接手机并开启调试最后利用u2的命令行工具完成手机端atx-agent的部署。接下来我们进入具体的实操环节。3. 步步为营PC端基础环境配置详解3.1 Python环境安装与校验Python是这一切的起点。如果你电脑上还没有Python或者版本老旧建议直接安装Python 3.8或3.9版本这两个版本在兼容性和稳定性上经过了广泛验证。安装建议Windows用户从Python官网下载安装包时务必勾选“Add Python 3.x to PATH”选项这能省去手动配置环境变量的麻烦。macOS用户推荐使用Homebrew安装brew install python。系统自带的Python 2.7已废弃切勿使用。Linux用户通常系统已自带Python 3可通过包管理器安装如sudo apt install python3 python3-pip(Ubuntu/Debian)。安装完成后打开终端Windows上是CMD或PowerShellmacOS/Linux是Terminal通过以下命令验证python --version # 或 python3 --version pip --version # 或 pip3 --version正常应显示Python 3.x.x和pip的版本号。如果提示“不是内部或外部命令”说明环境变量未配置成功需要手动将Python的安装目录如C:\Users\YourName\AppData\Local\Programs\Python\Python39和其下的Scripts目录添加到系统的PATH环境变量中。3.2 ADB的安装与配置ADB是Android SDK Platform-Tools组件的一部分。你不需要安装完整的Android Studio只需下载独立的Platform-Tools即可。步骤下载访问Android开发者网站找到“Command line tools only”中的Platform-Tools包根据你的操作系统Windows、macOS、Linux下载ZIP文件。解压将ZIP文件解压到一个你容易找到的目录例如C:\android-sdk或~/android-sdk。配置环境变量将解压后文件夹的路径例如C:\android-sdk\platform-tools添加到系统的PATH环境变量中。验证打开新的终端窗口输入adb version。如果成功会显示Android Debug Bridge的版本信息。注意配置环境变量后务必关闭所有旧的终端窗口并重新打开一个新的新的终端才会加载更新后的PATH。3.3 安装uiautomator2 Python库PC端最后的准备工作就是安装uiautomator2库本身。使用pip安装非常简单但这里有个关键点强烈建议使用国内镜像源速度会快很多。pip install uiautomator2 -i https://pypi.tuna.tsinghua.edu.cn/simple或者使用阿里云镜像pip install uiautomator2 -i https://mirrors.aliyun.com/pypi/simple/安装完成后uiautomator2会提供一个名为uiautomator2的命令行工具简称u2cli我们接下来就会用到它来初始化设备。4. 设备端准备与初始化打通PC与手机的任督二脉现在让我们把目光转向Android手机或模拟器。4.1 开启手机的开发者模式与USB调试这是让ADB能够识别设备的关键一步不同手机型号菜单略有差异但大同小异。开启开发者选项进入手机“设置” - “关于手机”连续点击“版本号”7次直到出现“您已处于开发者模式”的提示。启用USB调试返回设置找到新出现的“开发者选项”或“系统与更新”下的“开发者选项”打开“USB调试”开关。连接电脑使用USB数据线将手机连接到电脑。此时手机会弹出“是否允许USB调试”的授权对话框勾选“始终允许”并点击“确定”。这一步至关重要务必点击允许。在终端中输入adb devices你应该能看到你的设备序列号后面跟着device字样。如果显示unauthorized请检查手机上的授权对话框如果设备未列出请检查数据线、USB端口或驱动程序Windows系统可能需要安装手机厂商的USB驱动。4.2 使用u2cli初始化设备设备被ADB识别后我们就可以使用uiautomator2的命令行工具来为这台设备安装必要的组件了。这个步骤是自动化的“临门一脚”。在终端中执行python -m uiautomator2 init或者直接使用安装后提供的uiautomator2命令如果PATH配置正确uiautomator2 init这个命令背后做了哪些事情检查连接首先通过ADB确认当前连接的设备。推送atx-agent将PC端的atx-agent可执行文件推送到手机的/data/local/tmp目录。安装辅助APK向手机安装两个辅助APKcom.github.uiautomator负责提供UI查找和操作能力和com.github.uiautomator.test用于测试。这些APK在自动化过程中运行在后台。启动服务在手机端启动atx-agent守护进程并监听7912端口默认。验证尝试通过HTTP连接到手机的7912端口确认服务启动成功。执行成功后终端会显示类似[I 230101 10:00:00 init:189] Successfully init AdbDevice(serialxxxxxx)的信息。此时你的手机通知栏可能会多出一个“UIAutomator”的小图标这表明服务正在运行。实操心得init命令在绝大多数情况下都能一次成功。如果失败最常见的原因是网络问题因为安装APK时可能需要从GitHub下载。解决方法是指定--mirror参数使用国内镜像uiautomator2 init --mirror。另一个常见问题是手机系统特别是小米、华为等的“纯净模式”或“安装未知应用”权限限制需要在手机设置中为“USB安装”或相关选项授权。5. 第一个自动化脚本从打开计算器到完成计算环境搭建完毕是时候见证自动化的魔力了。我们选择一个所有Android手机都有的、界面标准的应用——系统计算器作为我们第一个演示例子。目标是写一个脚本自动打开计算器输入一个算式如9 * 9 并验证结果是否正确。5.1 连接设备与获取界面元素信息首先我们需要知道计算器界面上各个按钮的“坐标”或“标识”。uiautomator2提供了强大的实时界面查看工具weditor。我们先安装它pip install weditor -i https://pypi.tuna.tsinghua.edu.cn/simple安装后在终端输入weditor它会自动打开浏览器并显示一个界面。确保你的手机已连接且u2服务正常运行在Weditor页面的顶部输入框输入adb或你的设备序列号点击“Connect”。连接成功后你就能在浏览器中实时看到手机的屏幕镜像并且鼠标悬停在镜像上时右侧会显示对应UI元素的详细信息最关键的属性是resourceId、text、className和bounds。我们用它来定位计算器的按钮数字“9”的按钮text属性很可能就是9。乘号“×”的按钮text属性可能是×。等号“”的按钮text属性可能是。结果框可能是一个EditText或TextView我们可以用className或resourceId来定位。假设我们通过Weditor观察到数字9text9乘号text×等号text结果框classNameandroid.widget.EditText且resourceIdcom.android.calculator2:id/formula5.2 编写并解析自动化脚本接下来我们创建一个Python脚本例如first_demo.py。import uiautomator2 as u2 import time # 1. 连接设备。如果只有一台设备通过USB连接可以直接用 u2.connect()。 # 也可以指定设备序列号u2.connect(‘你的设备序列号’) # 或者使用无线连接需先用adb tcpipu2.connect(‘手机IP:7912’) d u2.connect() # 默认连接通过adb devices找到的第一台设备 # 2. 启动计算器应用。需要知道计算器的包名和启动Activity。 # 通用方法在终端执行 adb shell dumpsys window | grep mCurrentFocus然后操作计算器再执行一次命令对比找出包名和Activity。 # 这里以常见的Android原生计算器为例包名可能是 com.android.calculator2 app_package “com.android.calculator2” d.app_start(app_package) time.sleep(2) # 等待应用完全启动这是一个好习惯 # 3. 清空可能存在的历史输入非必须但保证环境干净 # 我们尝试点击“清除”C或AC按钮根据实际界面text定位 if d(text“C”).exists: d(text“C”).click() elif d(text“AC”).exists: d(text“AC”).click() time.sleep(0.5) # 4. 执行计算9 × 9 d(text“9”).click() time.sleep(0.2) # 加入短暂停顿模拟真人操作节奏有时更稳定 d(text“×”).click() time.sleep(0.2) d(text“9”).click() time.sleep(0.2) d(text“”).click() time.sleep(1) # 等待计算结果刷新 # 5. 验证结果 # 定位结果框并获取其文本内容 result_element d(className“android.widget.EditText”, resourceId“com.android.calculator2:id/formula”) if result_element.exists: actual_result result_element.get_text() print(f“计算结果显示为{actual_result}”) # 进行断言判断 expected_result “81” if expected_result in actual_result: # 有些计算器显示 ‘81’ 或 ‘ 81’ print(“✅ 测试通过9 × 9 等于 81”) else: print(f“❌ 测试失败期望包含 ‘{expected_result}‘实际得到 ‘{actual_result}’”) else: print(“未找到结果框元素”) # 6. 结束后可以停止应用可选 d.app_stop(app_package)脚本逻辑深度解析连接对象du2.connect()创建了一个设备对象后续所有操作都基于这个对象。它自动处理了与手机端atx-agent的HTTP通信。元素定位器d(text“9”)是一个元素选择器Selector它返回一个代表该定位条件的对象并非立即找到元素。只有调用.click()、.exists等方法时才会真正去查找。链式调用与等待d(text“9”).click()是典型的链式调用。u2内部有隐式等待机制默认会等待元素出现超时时间可配置。但我们仍然在关键操作后加了time.sleep这有两个目的一是让脚本执行速度更符合人类可观察的节奏便于调试二是在某些动画过渡或网络加载场景下给界面足够的稳定时间避免因元素状态未就绪而操作失败。结果验证自动化测试的灵魂在于“验证”。我们不仅操作还要通过get_text()获取UI上的结果并与预期值对比完成一个完整的测试用例闭环。5.3 运行脚本与结果分析在终端中切换到脚本所在目录运行python first_demo.py观察你的手机你会看到计算器被自动打开按钮被依次点击最终显示结果81。同时终端会打印出验证信息。可能遇到的问题与排查uiautomator2.exceptions.UiObjectNotFoundError最常见的错误意思是没找到元素。检查Weditor首先确认你通过Weditor看到的元素属性text, resourceId是否与脚本中写的一致。特别注意中英文符号和空格text“×”乘号和text“x”字母x是天壤之别。检查界面状态点击操作后界面是否真的跳转或更新了比如点击“”后结果框的文本内容可能变了但它的resourceId可能没变。确保你在正确的界面上查找元素。增加等待时间在某些性能较差的设备或应用启动初期元素加载慢。可以适当增加time.sleep或者使用u2更智能的等待方法d(text“”).wait(timeout10.0)# 等待最多10秒直到元素出现。应用无法启动d.app_start失败。确认包名使用adb shell pm list packages | grep calculator来查找准确的计算器包名。不同手机厂商的计算器包名可能不同如com.xx.calculator。检查应用是否安装d.app_info(“包名”)可以查看应用信息确认其存在。脚本执行无反应手机也没动静检查连接首先运行adb devices确认设备在线。再运行python -m uiautomator2 doctor检查u2环境这个命令会诊断设备连接、服务状态等并给出修复建议。重启atx-agent在终端执行uiautomator2 restart这会重启手机端的服务。6. 进阶技巧与最佳实践让自动化更稳健高效通过上面的例子你已经掌握了uiautomator2的基本操作。但要写出能在项目中稳定运行的自动化脚本还需要一些进阶技巧。6.1 更优雅的元素定位策略依赖text定位是最直观但也是最脆弱的因为文本容易变化且可能不唯一。应该建立优先级更高的定位策略resourceId这是首选只要开发为控件设置了唯一的id它就是最稳定可靠的定位方式。例如d(resourceId“com.xxx:id/btn_login”)。组合定位当单个属性不唯一时可以组合使用。例如d(className“android.widget.Button”, text“登录”)。相对定位与兄弟节点u2支持XPath但更推荐使用其内置的相对定位方法如child,sibling但学习成本稍高。对于复杂层级可以先用Weditor分析结构。使用坐标点击的注意事项d.click(x, y)应作为最后的手段因为它在不同分辨率设备上不兼容。如果必须使用请确保脚本有良好的设备适配逻辑。6.2 等待机制的深入应用抛弃硬编码的time.sleep拥抱智能等待。显式等待d(text“提交”).wait(timeout20.0)等待元素出现最多20秒。等待元素消失d(text“加载中…”).wait_gone(timeout30.0)等待“加载中”提示消失再进行下一步这对于处理网络请求场景非常有用。自定义等待条件你可以写一个循环结合d.info获取当前界面信息判断某个特定条件是否满足。6.3 异常处理与截图自动化脚本必须考虑异常情况并在失败时留下“现场证据”。import traceback import uiautomator2 as u2 from datetime import datetime d u2.connect() try: # 你的主要操作逻辑 d(text“关键按钮”).click() except uiautomator2.exceptions.UiObjectNotFoundError as e: print(f“未找到元素错误信息{e}”) # 在异常时截图以时间戳命名 screenshot_path f“./error_{datetime.now().strftime(‘%Y%m%d_%H%M%S’)}.png” d.screenshot(screenshot_path) print(f“已保存错误截图至{screenshot_path}”) # 也可以打印当前页面层级信息辅助调试 print(d.dump_hierarchy()) except Exception as e: print(f“发生未知错误{e}”) traceback.print_exc() # 打印完整的错误堆栈养成在关键步骤前后截图或出错时自动截图的习惯能极大提升调试效率。6.4 无线连接与多设备管理USB连接稳定但无线连接在多设备并行测试时更方便。先用USB连接一台设备。在终端执行adb tcpip 5555。这个命令会重启手机上的ADB守护进程并监听TCP/IP端口5555。拔掉USB线。确保手机和电脑在同一个局域网获取手机的IP地址通常在设置-关于手机-状态信息里。使用adb connect 手机IP:5555进行无线连接。之后在u2脚本中就可以用d u2.connect(‘手机IP:7912’)来连接了。注意端口是uiautomator2服务的7912不是ADB的5555。对于多台设备你可以在脚本中为每台设备创建独立的连接对象并行执行不同的测试任务这对于兼容性测试和性能压力测试场景非常有价值。7. 常见“坑点”与避坑指南即使按照步骤操作依然可能会遇到一些令人困惑的问题。这里总结几个高频“坑点”坑点一init成功但weditor连接不上或脚本无法控制。排查首先执行adb shell ps | grep atx查看atx-agent进程是否存在。如果不存在手动启动adb shell /data/local/tmp/atx-agent server -d。检查防火墙电脑或手机的防火墙可能屏蔽了7912端口。尝试暂时关闭防火墙测试。检查Wi-Fi与USB网络如果使用无线连接确保PC和手机在同一个子网且路由器没有设置客户端隔离。坑点二脚本在模拟器上运行正常到真机上就找不到元素。分辨率与DPI不同设备的屏幕密度不同可能导致基于坐标的操作失败或者某些元素的bounds属性发生变化。坚决避免使用绝对坐标定位。系统版本与厂商定制不同Android版本和手机厂商小米MIUI、华为EMUI等对系统UI和底层接口有修改可能影响uiautomator2的某些功能。遇到问题时查阅uiautomator2的GitHub Issues看是否有相同机型的反馈。悬浮窗与权限某些手机需要为“UIAutomator”或测试应用开启“悬浮窗”或“显示在其他应用上层”的权限否则无法正常获取界面信息。一般在手机设置-应用管理-特殊权限设置里。坑点三自动化操作被系统中断如出现“检测到无障碍服务”提示或自动化被自动停止。电池优化进入手机设置-电池优化找到“ATX”或相关组件设置为“不优化”。后台锁定在手机多任务界面将测试应用或atx-agent相关进程锁定防止被系统清理。无障碍服务某些深度定制的系统可能会监控并提示无障碍服务UiAutomator底层依赖它的使用按照提示允许即可。坑点四运行一段时间后脚本变慢或无响应。内存与资源泄漏长时间运行大量自动化用例后手机内存可能不足。定期在脚本中安排重启应用或甚至重启atx-agent服务d.service(“uiautomator”).stop()然后d.service(“uiautomator”).start()。日志清理uiautomator2和atx-agent会产生日志定期清理手机端/data/local/tmp目录下的相关日志文件。环境搭建和第一个脚本的跑通只是自动化之旅的起点。uiautomator2的真正威力在于其完整的生态系统图像识别uiautomator2[image]、插件扩展、与测试框架如pytest的集成等。当你熟悉了基本操作后可以尝试将这些工具组合起来构建覆盖安装、卸载、UI功能、性能监控、兼容性测试的全流程自动化方案。记住好的自动化脚本不是一蹴而就的它需要你在实际项目中不断打磨、调试和优化最终成为保障应用质量、提升研发效率的可靠利器。