用自然语言驱动Android UI测试:UI-TARS三步上手实战指南
最近在忙一个Android端到端回归的改造翻了一堆自动化方案突然发现一个叫UI-TARS的开源项目直接把我之前的测试脚本思维给颠覆了。简单说你不需要再写一堆findElement、sendKeys而是用一句人话告诉它“从首页进入设置把无线网络关掉再回到首页确认连接状态显示为已断开”它就自己去理解界面、找入口、点击、断言然后把结果告诉你。这篇文章我不打算做那种“很厉害的项目介绍”直接聊怎么用。我会围绕“三步玩转”这条主线把我在模拟器和真机上跑通的完整流程拆开包括环境准备、自然语言用例编写、常见踩坑和调试思路。适合的对象很明确正在用Appium、UIAutomator或Espresso写脚本、被元素选择和等待策略折磨的同学以及想在大模型时代重新思考UI测试方式的项目组。你不需要有很强的机器学习背景只要会Python、懂基本ADB命令就能跟着上手。1. 为什么UI-TARS值得关注从自动化脚本到自然语言操作1.1 传统Android UI自动化到底痛在哪先说说我之前用传统框架做Android自动化的感受。以UIAutomator2或Appium为例常规做法是定位控件比如通过resourceId、text、content-desc去抓一个按钮再执行点击。看上去挺稳实际跑起来全是小问题。最大的坑是选择器不稳定。同一个按钮在不同版本的系统上resourceId可能不变但控件层级会变有些第三方开源组件或者WebView混排页面压根不暴露可用的resourceId只能靠坐标点击。坐标一旦屏幕分辨率变了整套脚本就像沙子一样散架。再加上Android自带的各种弹窗——定位权限、存储权限、更新提示——每次弹的位置和文案不一样脚本里得写一堆try...except去处理越到后面维护成本越高。还有一个经常被忽略的痛点跨步骤的流程验证。比如“登录后检查个人信息是否显示正确”这种用例拆成代码要十几步点登录、等页面加载、找输入框、输内容、点提交、等跳转、再找某段文本去断言。每一步之间都要处理等待策略sleep短了容易误报sleep长了一个回归下来跑掉一晚上。UI-TARS这类“大模型驱动的UI自动化”方案恰好从根上绕开了选择器脆弱和流程拆分繁琐这两个问题。它直接把整个屏幕当图像和语义整体来理解用自然语言来描述行为再由模型生成操作序列。对于很多场景它比传统框架更像一个“人”在操作手机。1.2 UI-TARS的工作原理与设计取向UI-TARS的核心思路是把界面截图、操作历史和目标指令都丢给一个经过训练的视觉-语言模型让模型输出下一步动作。动作一般是“点击某个坐标”“输入某段文字”“滑动某块区域”“等待若干毫秒”这类结构化指令由框架转换成真实的ADB或系统事件。这不是简单调用一个现成的大模型接口就完事。UI-TARS针对UI理解做了专门的数据集和推理优化它能识别图标语义、列表项边界、输入框等视觉元素并具备一定的“多步任务规划”能力。比如你让它“把通知栏拉下来点开蓝牙图标”它能理解通知栏的位置、图标旁边一般有状态文字、点击之后要确认开关状态整个过程并不需要你预先写死坐标。我在实际使用中感觉它更像是“测试逻辑和交互视觉之间的翻译层”。你负责描述业务意图它负责映射成具体操作。这种设计在应对系统弹窗、动态加载内容和不同分辨率机型时容错率比传统选择器方案高很多。1.3 UI-TARS与传统自动化测试的核心对比把UI-TARS和我过去常用的几套方案放在一起看区别会很清楚维度UIAutomator2/Appium纯坐标脚本UI-TARS用例表达代码定位控件写死坐标自然语言描述界面变更影响选择器失效需重写坐标全变需重录重新生成指令即可动态弹窗处理需脚本内显式判断基本无法处理模型识别后自动绕开或点击跨步骤上下文自己写状态管理无可在多步内保持意图脚本维护成本高极高相对低前置学习门槛中等低中等重点是自然语言表述稳定性依赖控件树分辨率模型推理质量截图清晰度这里不是说要立刻抛弃传统框架。对于纯按钮“点击后断言文本”这种简单场景UIAutomator2的稳定性还是很高执行速度也更快。但如果是业务流程回归、多机型适配检查、以及UI频繁改版的产品UI-TARS的自然语言方案维护成本会低很多。2. 三步快速把UI-TARS跑起来很多人看到“大模型驱动”就以为要搭一套复杂的推理服务。其实UI-TARS的上手路径比想象中直接。我这里总结的三步是我在项目里实际跑通的流程也是相对最快能够看到效果的方式。2.1 第一步环境准备与项目安装先说环境。我当前的验证环境是这样一套组合一台MacBookPython 3.10一个Android模拟器API 34外加一台Android真机备用。UI-TARS本身依赖比较常见的Python包用虚拟环境隔离一下最稳妥。基础准备工作分成三块Python环境、Android调试环境、模型相关配置。python3 -m venv uitars_env source uitars_env/bin/activate pip install ui-tars如果安装比较慢可以把pip源切到国内镜像。另外需要确认电脑能正常用ADBadb devices执行后能看到已连接的设备序列号。真机需要开启开发者选项和USB调试模拟器则天然支持ADB。接下来要做的是准备模型。UI-TARS的推理可以使用云端大模型API也可以在本地部署量化后的模型。如果只是先体验流程、验证测试思路我更推荐使用云端API方式因为本地部署要准备显卡显存和推理框架这里就不展开。需要说明的是我用的是当前社区发布的推理分支模型权重文件需要从模型仓库单独下载或者通过接口配置访问。以API方式举例你需要在配置里填好API_BASE和密钥相关字段model: provider: openai-compatible base_url: 你的API服务地址 api_key: 你的密钥 model_name: ui-tars这套配置看起来像在调用一个大语言模型服务实际上它返回的是“下一步动作”的结构化表述框架拿到之后再去执行。2.2 第二步连接设备并初始化会话环境装好后核心是让UI-TARS能“看到”你的手机屏幕。连接这一步和传统自动化一样依赖ADB但不需要你手动写UIAutomator选择器。from ui_tars import UITarsDriver driver UITarsDriver(device_idemulator-5554) driver.connect() status driver.get_screen_status() print(status)执行这段代码UI-TARS会主动通过ADB截图并初始化上下文。截图分辨率建议设置为设备原始分辨率因为模型理解图标和文字依赖清晰度过低的截图分辨率会导致误判。这里有个容易忽略的细节UI-TARS接待的很可能是“整块屏幕截图的图像”而不是控件树信息。所以要确保模拟器或真机的屏幕处于亮屏状态锁屏界面或者熄屏状态会直接造成识别失败。我习惯在连接前先把设备屏幕唤醒。adb shell input keyevent KEYCODE_WAKEUP adb shell wm dismiss-keyguard这两条命令分别负责点亮屏幕和解除锁屏。如果你用的是模拟器最好顺手把“显示大小”和“字体大小”调成标准值避免因为缩放导致截图中的元素相对位置失真。2.3 第三步用一句话写你的第一个自然语言用例设备连接正常后就进入最核心的用法用自然语言描述操作。我写了一个最简单的用例——打开计算器点击数字2加3验证结果为5。result driver.run_task( 打开计算器应用依次点击数字2、加号、数字3、等号 然后读取显示结果确认结果等于5如果正确请返回PASS ) print(result)这里不需要指定任何控件坐标或资源ID整个过程由模型自行规划。运行后UI-TARS会循环执行“截图-理解-操作-再截图”的动作直到任务完成或超出轮次限制。跑完之后你可以打开生成的报告目录里面按时间顺序保存了每一步的截图、模型决策日志和执行操作记录。这种trace日志在做问题定位的时候特别好用能直接看到模型在哪一步理解错了比传统自动化那种只看失败堆栈直观得多。我个人认为三步法里面最重要的不是安装而是第三句自然语言怎么描述。模型对任务的理解深度直接决定了执行效果。这个我在下一章单独展开。3. 核心细节解析自然语言任务描述与执行条件3.1 怎么把业务逻辑翻译成模型能懂的话这一步是UI-TARS使用中真正的分水岭。拿“验证登录功能”举例不同写法效果差距很大。低质量描述是这样 “登录一下看看能不能成功。”这个描述缺乏起点和终点模型不知道账号密码是什么也不知道“成功”的判定标准是什么。质量高一点的描述是这样 “在登录页面输入账号test01和密码abc123456点击登录按钮等待页面跳转到首页并检查首页右上角是否显示用户名test01如果显示则返回登录成功否则返回登录失败。”对比一下就能看出高质量描述包含四个关键信息起始位置、具体操作、跳转等待、断言条件。其中“断言条件”尤其重要它决定了模型在执行完之后怎么给你一个可判断的结果而不是只输出“已点击”。我一般把这类描述拆成“前置状态、操作序列、预期结果”三段式。前置状态避免模型找错页面操作序列要拆得足够细每个动作单独成句预期结果要写清楚“看到了什么就判定成功没看到就判定失败”。如果你希望模型在发现非预期弹窗时自动关闭再继续可以在描述里加上一句“如果出现权限弹窗点击允许后继续操作”。3.2 多步流程与上下文记忆的工作机制UI-TARS的一个突出优势是支持多步任务中的上下文记忆。传统脚本执行多步操作时每个步骤是割裂的需要开发者自己维护“当前页面是什么、已经完成到哪一步”的状态UI-TARS则会在推理时保留前序的截图和动作记录结合当前截图做决策。举个例子这样一个多步任务“从桌面打开设置进入WiFi设置页连接名为office_5G的无线网络输入密码test8888连接成功后等待3秒再返回设置首页确认WiFi总开关处于开启状态。”模型在处理这个任务时不会看到一个大列表线性执行而是每一步结合上下文判断进入设置后看到左侧菜单它知道点“WiFi”进入的是WiFi页面输入密码后遇到弹窗它知道这是保存连接的等待返回首页后看到开关是绿色它就知道“开启状态”成立。从框架角度讲UI-TARS维护了一个Thought思考到Action动作的循环模型先分析当前屏幕和已完成的步骤输出一句内部推理然后选择一个可执行动作框架执行并拿到新截图循环继续。你可以在日志文件里看到每一轮完整记录这种透明度很深的地方在于你不仅能知道它“做了什么”还能知道它“为什么这么做”。3.3 截图、分辨率与模型推理参数的影响这部分直接影响自动化稳定性值得多说几句。UI-TARS依赖视觉理解那么“看得清”就是第一前提。第一截图质量。真机如果开启了“降低透明度”或“深色模式”模型在识别某些控件时可能会受影响尤其是一些本身对比度就低的按钮。我建议测试期间统一使用浅色主题、标准字体并关闭屏幕自动旋转。锁屏超时也要设置得足够长避免测试中途熄屏。模拟器上可以这样设置adb shell settings put system screen_off_timeout 1800000 adb shell settings put system accelerometer_rotation 0第二分辨率与缩放比例。高分辨率但系统缩放比例很大的设备截图内容会自动放大或缩小图标相对位置会变化。最好在设备开发者选项里把“最小宽度”调整为统一值比如360dp或411dp不同机型跑起来视觉结构更接近。第三模型推理参数。框架配置里通常有temperature、max_actions、timeout这类参数。temperature控制输出随机性自动化任务建议调低到0.1以内这样模型的动作选择更确定。max_actions是最大执行轮数一个任务如果超过30-40步还没完成基本可以判定进入了死循环设一个上限让任务自动失败比干等更省时间。timeout是单次动作的超时时间主要针对页面加载慢的情况一般2-5秒。第三点特别提醒不要觉得模型能力够就忽略超时策略。我见过“页面加载中”这种半白屏状态模型在截图上根本识别不出完好的元素结果一顿乱点。这种情况下我会在任务描述里加上“如果页面还在加载等待2秒后再继续”比在框架底层反复调参更有效。3.4 有必要引入的辅助能力OCR与通用组件适配UI-TARS虽然以视觉理解为主但它也支持OCR文本提取能力也在适配Android系统状态栏。项目文档里提到的OCR能力比较扎实我在中文界面上测试识别率在过得去的水平。系统级弹窗比如“充电提醒”“SIM卡状态变化”在较新版本中也能够识别并处理不完全依赖模型“猜”。不过需要提醒的是这不是一个“开箱即全自动”的工具。对于游戏类、自定义绘制类的应用模型往往没有足够的先验知识判断哪些是按钮哪些是装饰元素。遇到这种情况光靠自然语言还不够需要配合项目里的额外辅助标注能力来划区域。属于进阶用法这里先不展开。4. 实操过程与核心环节实现从任务编排到报告输出4.1 一个可复用的任务编排示例我把日常工作里比较典型的“设置WiFi并验证连接”流程封装成一个示例包含断言结果回传。这个示例可以直接作为模板来改。from ui_tars import UITarsDriver driver UITarsDriver( device_idemulator-5554, max_actions50, action_timeout5, temperature0.1, ) task_prompt ( 从桌面进入设置应用。 在设置页面中找到并进入WiFi设置页面。 如果当前WiFi总开关是关闭的先点击总开关打开。 在可用网络列表中找到名为office_5G的网络并点击连接。 如果弹出密码输入框输入密码test8888然后点击连接或加入按钮。 等待连接成功状态显示为已连接后返回设置首页。 最后确认WiFi总开关仍然处于打开状态。 如果以上所有步骤都成功返回PASS否则返回FAIL并说明失败原因。 ) result driver.run_task(task_prompt) print(任务结果:, result) driver.save_trace(wifi_connect_trace)这个脚本是参照常见实践补全的你可以直接复制使用。跑完以后wifi_connect_trace目录下会生成每次操作的截图和推理记录方便回放。实际执行一遍你会发现模型在“返回设置首页”这一步可能会有不同选择比如有的版本系统是左上角返回箭头有的版本是手势返回。UI-TARS通常能根据截图判断出来。如果它一直点错我会在Prompt里写明“使用屏幕左上角的返回按钮”人为降低歧义。4.2 三种运行模式CLI、Python API、高级批量调度UI-TARS给使用者提供了几种交互模式适合不同阶段。CLI模式适合快速验证。打开终端输入一行命令配合参数传递任务描述适合“临时点一下”的场景。Python API模式适合把UI-TARS集成进现有的测试框架。你可以把run_task的返回值作为测试断言的一部分配合pytest做流程编排。这是我推荐的方式因为可以复用原来的报告体系、CI调度和失败通知。批量调度模式适合回归场景。把几十条自然语言任务组织成JSON或YAML列表循环执行。因为每个任务都是独立调度的天然适合并行——只要你的设备资源和API调用额度允许。我目前的做法是同时挂两台模拟器把“兼容性检查类”任务拆成两组并行跑效率提升接近一倍。并行时的注意点不要多个任务同时操作一台设备截图会互相覆盖模型也会错乱。每个并行任务必须对应独立的device_id。4.3 报告与日志里到底应该看什么很多人跑完自动化只看通过率但UI-TARS这种方案里最值得看的是它的决策日志。日志里会记录每一轮模型的Thought和Action判断是“继续操作”“等待”还是“任务已完成”。有一种常见情况任务返回FAIL但页面其实已经完成了操作只是模型在最后一步断言时没找对目标。这时去看日志通常会看到类似“截图未找到用户名字段因此判定登录失败”的思考过程。你立刻就知道是断言目标描述不够精确而不是自动化流程真的失败。这种可解释性是传统自动化日志给不了的。我也会把日志里的错误类型简单归类误点、找不到元素、断言不准、任务超时。整理几轮之后你会发现大部分误点都集中在动态弹窗和可滚动列表区域接下来针对性地在任务描述里加约束就可以了。5. 常见问题与排查技巧实录5.1 设备连接失败与权限问题错误现象执行driver.connect()时报找不到设备或者所有截图都是黑色。排查思路从这三条入手先确认ADB层面能看到设备adb devices。如果显示unauthorized说明真实设备上的调试授权弹窗需要手动确认。模拟器截图黑屏大概率是模拟器本身的图形渲染问题。尝试冷启动模拟器关掉“快速启动”选项。多设备连接时一定要显式指定device_id。不指定的话框架可能选到错误设备界面不匹配导致后续识别率锐降。5.2 模型误点击与错误操作这是体验UI-TARS时最容易遇到的一个坑。“误点击”通常不是模型变笨了而是你的任务描述里信息不够充分。常见的解决方式是在Prompt里加入“防误触条款”“在点击任意按钮之前请先确认目标按钮的文字或图标与描述严格匹配。如果界面出现弹窗或加载状态先暂停操作等待界面稳定。”我实测加了这个前缀之后误点明显减少代价是多了一点点执行时间。这个交换是值得的。如果误点集中在某类控件比如广告卡片、弹窗上的关闭按钮也可以在任务描述里额外强调“忽略页面右上角可能出现的推广卡片”。把负面约束写清楚模型的判断会稳很多。5.3 中英文混合界面与文本断言不准UI-TARS默认具备较好的中英文理解能力但断言时如果目标文本本身就动态变化比如时间、订单号很容易判断失败。这时候不要试图让模型去读精确时间而是改用“包含”或“格式匹配”这类模糊断言。比如“检查订单号是否以字母A开头”就比“检查订单号是否为AB20240501”更稳。如果要严格精确匹配建议把预期文本放到Prompt里让它逐字对比。某次我遇到一个中英混排的页面模型把英文字号识别成了中文全角字符导致断言失败。这种情况下我会把目标文本拆成关键词让模型分别确认而不是一次性整句匹配。5.4 性能与超时调整策略回到最开始说的“三步玩转”最后一步是让任务稳定落在一个可控的时间范围内。单步操作包含一次截图、一次模型推理和一次动作执行。如果每轮推理都耗时好几秒一个20步的任务就奔着几分钟去了。我建议做三件事第一把temperature调到0到0.1之间降低模型犹豫不决的概率第二合理设置action_timeout避免高延迟网络下卡在等待上第三任务粒度不要太大一个任务控制在10-20步之间。步骤太多中途一个误判产生的错误叠加会非常难排。如果发现某条流程反复超时我的建议是别硬调参数优先把任务拆细。把“从首页进入设置并完成WiFi设置并返回首页”改成“进入设置”和“完成WiFi设置”两个独立任务中间用测试用例去衔接。这样排错成本会降一个量级。6. 写在最后的个人小经验我把一个项目的核心回归流程从UIAutomator2迁移到UI-TARS之后最明显的感受是写用例的时间变短了但调Prompt的时间变长了。这其实是好事因为自然语言描述业务逻辑比写控件定位更接近产品需求本身一旦描述准确脚本的生命周期会比传统写法长很多。给准备尝试的同学一个建议初期不要一上来就把所有用例都改成自然语言。先从手工测试里最容易出错的5条业务流程开始跑一周积累一套适合自己产品界面的“描述模板”。后面再扩大范围时你会发现大部分任务都可以套用“前置-动作-断言”这个模板只是中间的描述细节不同。UI-TARS不是万能的但当你吃透了它的行为边界之后它的确能把Android UI自动化的维护成本拉到一个很低的水平。