UI-TARS安卓自动化测试实战:5大技巧从入门到精通
2026/6/18 2:54:03 网站建设 项目流程

1. 项目概述与核心价值

最近在团队里推动安卓自动化测试,发现很多同事,无论是测试工程师还是刚入行的开发,一提到自动化就头疼。传统的Appium、Espresso框架,光是搭建环境、学习元素定位和编写脚本,就能劝退一大半人。更别提应用界面一更新,脚本就得跟着大改,维护成本高得吓人。直到我深度体验了UI-TARS,才感觉自动化测试的“平民化”时代真的来了。这东西的核心,是把视觉语言模型(VLM)的能力直接怼到了手机屏幕上,让你用说人话的方式告诉它“点一下登录按钮”、“在搜索框输入XXX”,它就能自己看懂屏幕、理解指令并执行操作。这听起来有点像魔法,但背后是一套相当扎实的技术架构。对于想快速上手安卓自动化,又不想深陷代码泥潭的朋友来说,UI-TARS提供的是一条捷径。它特别适合那些业务逻辑复杂、UI迭代频繁,或者缺乏专职自动化测试人员的中小团队。接下来,我会结合五个从入门到精通的实战技巧,拆解如何把UI-TARS真正用起来,避开我踩过的那些坑。

2. 环境搭建与避坑指南:从零到一的正确姿势

很多人第一步就卡住了,不是包安装失败,就是设备连不上。其实UI-TARS的环境依赖相对干净,但有几个关键点必须注意。

2.1 安装与基础配置:不止是pip install

官方推荐用pip install ui-tars,但如果你直接这么干,很可能会遇到各种依赖冲突,尤其是如果你本地Python环境已经装了一堆机器学习或自动化测试的包。我的建议是,为UI-TARS单独创建一个干净的虚拟环境。用conda或者venv都行,这能避免90%的版本问题。

# 使用conda创建环境(推荐,便于管理) conda create -n ui-tars-env python=3.10 conda activate ui-tars-env # 安装UI-TARS pip install ui-tars

安装成功后,别急着跑demo,先验证核心功能是否正常。除了打印版本号,更重要的是测试其视觉模块的基础能力。你可以写一个简单的脚本,检查它能否正确导入并调用核心模块。

import ui_tars from ui_tars.prompt import get_prompt_template print(f"UI-TARS版本: {ui_tars.__version__}") # 尝试获取移动端模板,这是后续操作的基础 try: mobile_template = get_prompt_template("MOBILE_USE") print("移动端模板加载成功。") except Exception as e: print(f"模板加载失败,请检查安装: {e}")

2.2 安卓设备连接:真机与模拟器的抉择

UI-TARS通过ADB(Android Debug Bridge)与设备通信。这里有个关键选择:用真机还是模拟器?

  • 安卓模拟器:对于纯功能测试和脚本开发,模拟器是首选。它稳定、可快速重置、能方便地切换分辨率。推荐使用Android Studio自带的AVD Manager创建模拟器。别用那些手游模拟器(如雷电、夜神),它们的ADB接口和屏幕渲染方式可能非标准,会导致UI-TARS识别坐标出错。

    • 创建技巧:在AVD中,建议选择“Pixel”系列的设备定义,并安装“Google Play”版本的系统镜像。这能确保最接近真机的API环境和UI组件。
    • 关键步骤:启动模拟器后,务必在终端执行adb devices,确认设备已列出并显示为device状态。
  • 真实安卓手机:如果需要测试摄像头、GPS、传感器等硬件交互,或者验证特定机型上的表现,就必须用真机。

    • 开启开发者模式:进入手机“设置”->“关于手机”,连续点击“版本号”7次。
    • 开启USB调试:在开发者选项中,找到“USB调试”并打开。
    • 连接电脑:用数据线连接,手机上会弹出“允许USB调试吗?”的提示,一定要点击“允许”。再次执行adb devices确认。

避坑经验:无论用哪种方式,确保adb命令在终端中可直接运行。如果报错“adb不是内部或外部命令”,你需要将Android SDK的platform-tools目录路径添加到系统的环境变量PATH中。这是最常被忽略的一步。

2.3 分辨率适配与坐标系统初探

UI-TARS的核心是“看图操作”,所以它需要知道屏幕的尺寸。它会将截图和操作坐标都归一化到一个内部标准尺度,再根据你提供的实际屏幕分辨率进行转换。因此,获取准确的设备分辨率至关重要

你可以通过ADB命令快速获取:

adb shell wm size

输出类似Physical size: 1080x2340。请务必记录下这个宽和高,在后续编写脚本解析模型响应时,origin_resized_widthorigin_resized_height参数就必须填这个值。填错了会导致所有点击位置偏移,脚本完全失效。

3. 核心技巧一:用自然语言设计稳健的测试指令

很多人以为把需求直接丢给UI-TARS就行,比如“测试登录功能”。这种模糊的指令,模型要么无法理解,要么会产生不可预知的操作序列。设计指令是一门学问,目标是让模型“看得懂、做得到、不迷惑”。

3.1 指令设计原则:具体、原子、有序

好的指令应该像一个给新人写的、极其详细的SOP(标准作业程序)。

  • 具体化:避免使用“那个按钮”、“这里”等代词。直接描述UI元素的文本内容(如“登录按钮”)、特征(如“蓝色的、带加号的图标”)或相对位置(如“屏幕右下角的发送按钮”)。
  • 原子化:一个指令只包含一个最简操作。不要写“登录并查看首页”,而是拆成“1. 点击登录按钮。2. 验证首页的‘欢迎’文本是否出现。”
  • 有序化:明确步骤顺序。移动端操作有很强的线性逻辑,比如必须先输入账号才能点登录。

反面教材“帮我测试一下这个购物应用。”优秀范例

请执行以下操作序列: 1. 在桌面找到名为“ShopApp”的图标并点击打开。 2. 等待应用主页完全加载。 3. 点击屏幕底部导航栏的“分类”选项卡。 4. 在顶部的搜索框内输入“蓝牙耳机”。 5. 点击键盘上的“搜索”按钮或回车键。 6. 在搜索结果列表中,点击第一个商品条目。 7. 在商品详情页,找到并点击“加入购物车”按钮。 8. 验证屏幕是否弹出提示“已加入购物车”。

3.2 利用MOBILE_USE模板固化常用操作

UI-TARS的MOBILE_USE模板内置了对移动端通用操作的优化。在你的指令中,可以隐含地调用这些模式。例如,当你描述“返回主屏幕”时,模型更倾向于调用press_home()这类底层操作。但要注意,模板是辅助,清晰的指令才是关键。不要指望模型能完全理解“滑动浏览”这样的复杂手势,你需要拆解为“从屏幕中央向上滑动一段距离”。

4. 核心技巧二:解析与执行——从模型响应到可靠脚本

拿到模型对指令的响应后,这才是真正开始“工程化”的地方。原始响应是一段文本,我们需要把它变成可执行的代码。

4.1 动作解析与坐标转换

parse_action_to_structure_output函数是这个环节的心脏。它把模型返回的思考文本,解析成结构化的动作列表。这里最关键的参数是origin_resized_heightorigin_resized_width,必须与你之前用adb shell wm size获取的值严格一致。

from ui_tars.action_parser import parse_action_to_structure_output # 假设 model_response 是UI-TARS模型返回的文本 parsed_actions = parse_action_to_structure_output( response=model_response, factor=1000, # 缩放因子,通常保持1000,代表坐标是归一化到[0,1000)区间的 origin_resized_height=2340, # 你的设备实际高度 origin_resized_width=1080, # 你的设备实际宽度 model_type="qwen25vl" # 根据你使用的模型类型填写 )

parsed_actions是一个列表,里面每个元素都代表一个操作,比如{"action": "click", "x": 540, "y": 1200}。这个坐标已经是换算到你设备实际屏幕上的坐标了。

4.2 生成与优化PyAutoGUI脚本

接下来,用parsing_response_to_pyautogui_code将结构化动作转换为PyAutoGUI脚本。PyAutoGUI是一个控制鼠标键盘的库,UI-TARS利用它通过ADB模拟触屏操作。

from ui_tars.action_parser import parsing_response_to_pyautogui_code automation_code = parsing_response_to_pyautogui_code( responses=parsed_actions, image_height=2340, # 注意:这里的高度宽度应与解析时一致 image_width=1080 ) with open("generated_test.py", "w") as f: f.write(automation_code)

生成的脚本大致长这样:

import pyautogui import time # 假设操作是点击 pyautogui.click(x=540, y=1200) # 坐标已转换 time.sleep(0.5) # UI-TARS会自动在操作间插入短暂延迟

重要优化点:自动生成的time.sleep延迟可能不够。对于网络加载慢或应用响应迟钝的页面,你需要手动增加等待时间,或者引入更智能的等待机制。这是提升脚本稳定性的第一步。

5. 核心技巧三:提升稳定性的高级策略

脚本能跑起来只是开始,跑得稳、长期可用才是目标。UI-TARS基于视觉,而视觉会受界面变动、加载延迟、动画干扰的影响。

5.1 实现智能等待,而非固定休眠

完全依赖time.sleep是脆弱的。我推荐使用基于视觉的等待。思路是:让脚本在执行下一步前,持续检查某个关键元素是否出现。

import time from PIL import ImageGrab # 或其他截图方式 import ui_tars def wait_for_element(description, timeout=10, interval=1): """ 等待直到屏幕中出现描述的元素 :param description: 元素描述,如‘登录成功的提示弹窗’ :param timeout: 超时时间(秒) :param interval: 检查间隔(秒) """ start_time = time.time() while time.time() - start_time < timeout: # 1. 截取当前屏幕 screenshot = ImageGrab.grab() # 此处需替换为通过ADB截取手机屏幕的方法 # 2. 将截图和描述交给UI-TARS模型进行判断(这里简化流程) # 实际中,你可以调用一个轻量级的判断函数,询问模型“当前屏幕是否有[description]” # 假设有一个函数 check_element_presence(screenshot, description) if check_element_presence(screenshot, description): print(f"元素 '{description}' 已找到。") return True time.sleep(interval) print(f"等待元素 '{description}' 超时。") return False # 在脚本中使用 # 点击登录按钮后... # pyautogui.click(login_button_x, login_button_y) # 使用智能等待,而不是 time.sleep(5) if wait_for_element("欢迎回来,用户!", timeout=15): # 继续执行登录后的操作 pass else: # 执行失败处理,如重试或记录错误 print("登录可能失败,未检测到欢迎信息。")

实现check_element_presence需要你再次调用UI-TARS的模型,但可以是一个更简化的、只返回是否的判断调用。这虽然增加了单次操作的成本,但极大地提升了脚本的鲁棒性。

5.2 建立重试与容错机制

任何自动化操作都可能因瞬时卡顿、弹窗干扰而失败。给关键操作加上重试逻辑。

def safe_click(x, y, max_attempts=3): """带重试的点击操作""" for attempt in range(max_attempts): try: pyautogui.click(x, y) # 点击后,可以简单验证是否成功(例如,通过检查预期变化) time.sleep(0.5) # 给界面反应时间 # 这里可以加入一个简易的验证,比如判断某个标志性颜色是否出现 return True except Exception as e: print(f"点击({x}, {y}) 第{attempt+1}次尝试失败: {e}") if attempt < max_attempts - 1: time.sleep(1) # 失败后等待一秒再试 print(f"点击({x}, {y}) 重试{max_attempts}次后仍失败。") return False # 在生成的脚本中,替换原始的 pyautogui.click 调用 # 原始: pyautogui.click(540, 1200) # 改为: if not safe_click(540, 1200): # 记录失败日志,或触发整个用例的重试 log_error("关键登录按钮点击失败")

5.3 处理动态元素与坐标漂移

即使同一款应用,不同机型、不同版本,按钮位置也可能有细微差别。UI-TARS的视觉识别能解决大部分问题,但如果元素是纯图标、无文字,或者界面布局动态变化,可以采取以下策略:

  • 相对坐标与区域点击:不依赖绝对坐标,而是描述相对于其他稳定元素的位置。例如,“点击登录按钮,它位于用户名输入框的正下方”。这需要模型具备更强的空间推理能力,目前UI-TARS正在这方面不断进化。
  • 多特征备份定位:在指令中同时描述元素的多个特征,如“红色的、圆形的、写着‘提交’的按钮”。给模型更多线索,提高识别容错率。

6. 核心技巧四:构建可维护的测试用例集

当脚本多起来后,管理和维护就成了新挑战。我们不能让一堆零散的Python文件散落在各处。

6.1 用例组织架构

建议按以下结构组织你的UI-TARS自动化项目:

ui-tars-automation/ ├── config/ │ ├── devices.yaml # 设备配置(分辨率、ADB序列号) │ └── app_packages.yaml # 被测应用的包名 ├── core/ │ ├── base_page.py # 封装基础操作(如智能等待、安全点击) │ └── visual_helper.py # 封装与UI-TARS模型的交互 ├── test_cases/ │ ├── login/ │ │ ├── test_login_success.py │ │ └── test_login_failure.py │ └── checkout/ │ └── test_add_to_cart.py ├── tasks/ # 存放自然语言指令文件 │ ├── login_success.txt │ └── checkout_flow.txt ├── scripts/ # 由UI-TARS生成的原始脚本(可定期清理或作为参考) └── run_tests.py # 主运行入口

6.2 数据驱动测试

将测试数据(如用户名、密码、商品名)从脚本中分离出来。可以用JSON、YAML或CSV文件管理。

test_data.json:

{ "login_tests": [ {"username": "valid_user", "password": "correct_pwd", "expected": "success"}, {"username": "invalid_user", "password": "wrong_pwd", "expected": "fail"} ] }

在你的指令模板中,使用占位符:

1. 在用户名输入框输入“{username}”。 2. 在密码输入框输入“{password}”。 3. 点击登录按钮。 4. 验证是否出现“{expected_result}”对应的提示信息。

然后在运行前,用代码读取数据文件,替换占位符,动态生成最终指令传给UI-TARS。这样,增加新测试数据只需改数据文件,无需改指令或脚本。

6.3 集成到CI/CD流水线

UI-TARS脚本可以集成到Jenkins、GitLab CI等平台。核心步骤是:

  1. 环境准备:在CI节点上安装Python环境、UI-TARS库,并连接好安卓模拟器(可以是用Docker运行的Android模拟器容器)。
  2. 脚本执行:CI任务触发后,拉取代码,运行run_tests.py
  3. 结果收集:每个测试脚本应输出结构化的结果(如JUnit XML格式),CI工具能解析这些结果并生成测试报告。
  4. 截图与日志:在测试失败时,自动保存当时的屏幕截图和UI-TARS的解析日志,这对于后续排查问题至关重要。

7. 核心技巧五:超越功能测试——探索UI-TARS的潜力

UI-TARS不仅能做“点击-输入-验证”的功能回归测试,结合其视觉理解能力,还能玩出更多花样。

7.1 视觉回归测试(Visual Regression Testing)

每次应用发布前,可以用UI-TARS自动遍历关键路径,并在每个关键页面截图。将这些截图与上一版本(基线版本)的截图进行像素级或特征对比,自动检测非预期的UI变化,比如布局错乱、颜色错误、文字遮挡等。虽然UI-TARS本身不直接提供对比功能,但你可以用它来驱动应用到达指定页面并截图,然后结合专门的图像对比库(如pixelmatchOpenCV)进行分析。

7.2 探索性测试与猴子测试

你可以给UI-TARS一个更开放的指令,如“在设置页面随意探索并点击,持续5分钟,记录任何导致应用崩溃或无响应的操作”。虽然这有一定风险,但能发现一些在结构化测试中难以触发的深层bug。需要为模型设定一些边界规则,比如“不要退出应用”、“不要修改系统设置”。

7.3 辅助代码生成与录制回放

目前UI-TARS是根据指令生成操作代码。反过来想,你可以手动操作一遍应用,同时用工具录制屏幕和你的操作坐标序列。然后,将这个操作序列和对应的屏幕截图序列提供给UI-TARS,让它“学习”并反向生成描述这段操作的自然语言指令和可复用的脚本。这相当于实现了“录制-生成脚本”的功能,对于快速创建基础测试用例非常有帮助。

8. 常见问题与实战排查清单

在实际使用中,你会反复遇到一些问题。这里是我整理的速查清单:

问题现象可能原因排查步骤与解决方案
adb devices找不到设备1. USB线或连接问题
2. 未开启USB调试
3. 驱动问题(Windows)
4. ADB服务未启动
1. 换线、换USB口。
2. 确认手机“开发者选项”-“USB调试”已开启,并勾选“仅充电模式下允许ADB调试”(如果有)。
3. 在设备管理器中查看安卓设备是否有感叹号,安装对应驱动。
4. 运行adb kill-server && adb start-server
UI-TARS安装失败1. Python版本不兼容
2. 网络问题
3. 依赖冲突
1. 确认使用Python 3.8-3.11。
2. 使用国内镜像源:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ui-tars
3. 在全新的虚拟环境中安装。
脚本点击位置完全偏移origin_resized_widthorigin_resized_height参数错误1. 用adb shell wm size再次确认设备分辨率。
2. 检查在parse_action_to_structure_outputparsing_response_to_pyautogui_code两个函数中传入的分辨率参数是否完全一致且正确。
模型无法识别特定元素1. 截图模糊或延迟
2. 元素描述太模糊
3. 动态内容(如滚动列表)
1. 确保截图是操作前的稳定界面,可适当增加操作前延迟。
2. 在指令中使用更精确的描述,包括文本、邻近元素、颜色。
3. 对于列表,指令明确“滑动直到看到‘某某元素’,然后点击它”。
脚本在某个步骤卡住1. 网络加载慢
2. 动画未完成
3. 意外弹窗(权限、更新)
1. 在该步骤前加入智能等待(见技巧三),而非固定休眠。
2. 增加操作后的固定延迟time.sleep(2)
3. 在脚本开头或关键流程后,加入处理常见弹窗的代码块(如检测到“允许”按钮就点击)。
生成的PyAutoGUI脚本执行报错1. PyAutoGUI未安装
2. 坐标超出屏幕范围
3. ADB连接断开
1. 在虚拟环境中安装pyautogui:pip install pyautogui
2. 检查坐标值。UI-TARS生成的坐标应在屏幕范围内(0< x<宽度,0< y<高度)。
3. 重新运行adb devices确保设备在线,脚本中可加入连接检查。
运行速度慢1. 模型推理需要时间
2. 截图和ADB命令传输耗时
1. 这是VLM模型的固有特点,对于回归测试套件,可以接受。
2. 确保电脑与设备(尤其是模拟器)在同一高性能主机上,减少传输延迟。
3. 优化指令,减少不必要的、复杂的描述。

从我自己的实践来看,UI-TARS确实大幅降低了安卓自动化测试的初始门槛,它让功能测试用例的快速创建成为可能。但它并非银弹,其稳定性和执行效率目前还无法与基于代码定位的传统框架在稳定环境下相提并论。它的最大价值在于应对快速变化的UI缺乏测试代码积累的项目初期。将UI-TARS生成的脚本作为可维护的“初级代码”,再结合工程师对其加入重试、等待、断言等加固逻辑,是一种非常高效的“人机结合”模式。刚开始用的时候,多在指令设计和异常处理上下功夫,会比盲目跑脚本有效得多。随着你对它“脾气”的熟悉,你会逐渐知道什么样的指令它理解得最好,什么样的界面变化需要你额外干预。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询