1. 项目概述与问题引入做移动端自动化测试的朋友对Appium一定不陌生。它就像一把瑞士军刀覆盖了绝大部分的UI交互场景从点击、输入到滑动、长按都能搞定。但这些年我踩过的坑告诉我真实的业务场景远比标准控件复杂。比如教务管理系统里那个动态生成的课程表元素ID每次刷新都变又比如金融App里需要识别验证码图片中的扭曲文字才能继续操作再或者游戏界面里那些非标准控件、Canvas绘制的元素Appium的定位策略直接失效。这些就是所谓的“复杂测试场景”它们往往涉及动态内容、图像识别、非标准控件或需要一定逻辑推理的交互流程。最近一个叫Open-AutoGLM的项目进入了我的视野。它不是一个传统的UI自动化框架而是一个基于大语言模型LLM的智能体框架。简单说它能“看懂”屏幕理解你的指令并像真人一样去操作。这让我眼前一亮那些让Appium头疼的场景是不是可以用这种“视觉推理”的方式来解决这个项目就是一次从零开始的探索目标很明确用Open-AutoGLM来搞定那些Appium覆盖不了或处理起来极其别扭的复杂测试场景。无论你是被动态元素折磨的测试工程师还是对AI应用落地的开发者这篇从环境搭建到实战对抗的完整记录或许能给你一些新的思路。2. 核心思路为什么是Open-AutoGLM在深入代码之前我们必须先想清楚为什么是Open-AutoGLM它和Appium的根本区别在哪里理解了这一点才能用好它。Appium的核心是“控件驱动”。它通过UIAutomator2Android或XCUITestiOS等底层引擎获取当前屏幕的控件树一个XML结构。我们的自动化脚本本质上是根据控件的resource-id、text、xpath等属性来定位元素然后执行预设的点击、输入等操作。这个模式非常高效、稳定但它的天花板就是控件树。一旦界面元素无法被标准控件树捕获如游戏、部分Flutter/React Native控件、自定义绘制视图或者元素的属性动态变化难以定位Appium就无能为力了。Open-AutoGLM走的是另一条路“视觉-语言驱动”。它不关心底层的控件树是什么它只处理两样东西屏幕截图和你的自然语言指令。其工作流程可以概括为观察通过ADB或其他方式获取设备当前的屏幕截图。理解将截图和你的指令如“登录教务系统”一起输入给大语言模型通常是多模态模型。规划大模型分析截图理解当前界面状态和你的目标然后规划出下一步操作如“点击用户名输入框”。执行框架将规划出的操作通常是坐标点击、滑动、输入文本通过ADB指令发送给设备执行。循环执行后再次截图观察结果继续下一步规划直到任务完成。这个模式的巨大优势在于泛化能力。只要模型能“看懂”屏幕上是什么它就能操作。动态生成的图表、验证码图片、游戏界面里的虚拟按钮对人眼来说是可识别的对训练好的多模态模型来说同样可以识别。这就绕开了控件树这个瓶颈。当然它也有代价执行速度慢且成本高。每一步都需要调用大模型进行推理相比Appium的直接控件操作耗时更长且如果使用云端API会产生费用。因此Open-AutoGLM不是用来替代Appium的而是作为其强有力的补充专门攻坚那些Appium的“盲区”场景。注意Open-AutoGLM的成功极度依赖所选用的多模态大模型的能力。模型对图像的理解精度、对指令的遵循能力直接决定了自动化任务的成败。目前项目主要支持GLM系列、Qwen-VL等开源模型也可以接入GPT-4V等闭源API。3. 环境搭建与核心工具链解析工欲善其事必先利其器。用Open-AutoGLM做移动端自动化需要搭建一个融合了AI模型和移动设备操控的环境。下面是我一步步搭建的详细过程其中有不少需要注意的坑。3.1 基础移动端测试环境这部分和传统Appium环境有重叠是必须的基石。Android开发环境ADB确保adb命令可用。这是与手机通信的桥梁。连接你的真机或启动模拟器如Android Studio的AVD通过adb devices确认设备已连接。Python环境建议使用Python 3.8。创建一个独立的虚拟环境conda create或venv来管理依赖避免包冲突。待测应用以“教务管理系统”为例。你需要准备好该应用的APK文件并通过adb install安装到设备上。同时你最好能拿到一些测试账号。3.2 Open-AutoGLM项目部署Open-AutoGLM是一个开源项目我们需要将其克隆到本地并进行配置。# 克隆项目仓库 git clone https://github.com/OpenBMB/Open-AutoGLM.git cd Open-AutoGLM # 安装项目依赖 pip install -r requirements.txt这里可能会遇到第一个坑依赖冲突。特别是torchPyTorch的版本需要与你的CUDA版本如果使用GPU匹配。如果遇到问题建议先根据官方PyTorch网站的命令安装匹配的torch和torchvision然后再安装其他依赖。3.3 多模态大模型准备核心这是项目的“大脑”。Open-AutoGLM支持多种模型我们需要选择并加载一个。方案一使用开源轻量模型推荐入门例如Qwen-VL-Chat。它模型较小可以在消费级GPU甚至CPU上运行适合快速验证想法。# 安装Qwen-VL的Python库 pip install qwen-vl然后在代码中指定模型路径如果从ModelScope或Hugging Face下载。方案二使用云端API稳定但有成本例如OpenAI的GPT-4V。这种方式无需本地GPU资源响应稳定但需要API Key并支付费用。你需要在项目配置文件中设置你的API Key。方案三使用GLM系列模型项目对GLM支持较好如果你有GLM-4V等模型的权限可以按照项目文档配置。我个人的经验是初期验证和简单场景用Qwen-VL-Chat足矣。它的识别精度对于标准的App界面元素按钮、输入框、文字已经不错。等到需要处理更复杂的图像如验证码时再考虑换用更强大的模型。3.4 辅助工具Appium Inspector可选但重要虽然我们最终不用Appium执行但Appium Inspector仍然是一个 invaluable 的工具。为什么因为Open-AutoGLM在开发调试阶段我们经常需要知道屏幕某个位置的坐标或者验证模型识别得对不对。启动Appium Server和Inspector连接到你的设备。在Inspector里点击你想要操作的元素右侧的详细信息中通常会包含该元素的坐标bounds属性。这个坐标信息可以用来和我们Open-AutoGLM模型输出的点击坐标进行对比验证是调试的黄金标准。环境搭好后你的工具链应该是Python脚本 - Open-AutoGLM框架 - 多模态模型 - ADB - 手机设备。同时Appium Inspector作为“坐标校验器”在一旁待命。4. 实战对抗攻克教务系统登录与动态课表理论说再多不如一行代码。我们以“教务管理系统”的两个核心场景为例看看Open-AutoGLM如何实战。4.1 场景一带有验证码的登录模块这是一个经典难题。假设教务系统登录界面有用户名、密码输入框和一个动态生成的图形验证码。Appium处理验证码通常需要OCR服务介入流程割裂。而Open-AutoGLM可以尝试“端到端”解决。第一步定义任务指令我们的指令需要足够清晰。不要只说“登录”而是描述最终状态。task_instruction “使用账号‘student01’和密码‘test123456’登录教务管理系统并正确输入图片中显示的验证码。”第二步编写执行脚本下面是一个高度简化的示例代码框架展示了核心流程import os from autoglm import AutoGLM # 假设这是框架的主要类 from PIL import Image import subprocess import time # 1. 初始化AutoGLM智能体指定使用的模型 agent AutoGLM(model_nameqwen-vl-chat, devicecuda:0) # 或使用‘cpu’ # 2. 启动教务管理系统App app_package “com.example.edusys” subprocess.run([“adb”, “shell”, “monkey”, “-p”, app_package, “-c”, “android.intent.category.LAUNCHER”, “1”]) time.sleep(3) # 等待App启动 # 3. 定义主循环 max_steps 20 for step in range(max_steps): # 3.1 获取当前屏幕截图 subprocess.run([“adb”, “shell”, “screencap”, “-p”, “/sdcard/screen.png”]) subprocess.run([“adb”, “pull”, “/sdcard/screen.png”, “./current_screen.png”]) current_screen Image.open(“./current_screen.png”) # 3.2 让智能体观察屏幕并决定下一步动作 # 这里需要根据框架的具体API来调用以下为示意 action agent.observe_and_plan(current_screen, task_instruction) # action 可能是一个字典如{‘action_type’: ‘click’, ‘coordinates’: (x, y)} 或 {‘action_type’: ‘type’, ‘text’: ‘abc’} print(f“Step {step}: {action}”) # 3.3 执行动作 if action[‘action_type’] ‘click’: x, y action[‘coordinates’] subprocess.run([“adb”, “shell”, “input”, “tap”, str(x), str(y)]) elif action[‘action_type’] ‘type’: text action[‘text’] # ADB输入文本需要特殊处理可能要先点击输入框聚焦 subprocess.run([“adb”, “shell”, “input”, “text”, text]) elif action[‘action_type’] ‘done’: print(“任务完成”) break time.sleep(2) # 等待操作执行和界面响应第三步调试与优化实际运行中模型可能不会一次成功。常见问题及对策问题1模型点击位置不准。用Appium Inspector获取正确坐标与模型输出对比。如果偏差有规律可以在代码里加入一个校准偏移量。更根本的方法是提供更详细的指令例如“点击屏幕上方中央偏右的那个蓝色‘登录’按钮”。问题2模型无法识别验证码。这是对模型视觉能力的考验。如果Qwen-VL失败可以尝试切换至更强大的模型如GPT-4V。或者可以采用混合策略用Open-AutoGLM完成用户名、密码的输入和登录按钮的点击而验证码识别单独用一个专业的OCR服务如PaddleOCR来完成然后将识别结果通过框架的“输入文本”动作填入。这体现了“AI智能体为主传统工具为辅”的灵活思路。问题3任务陷入死循环。模型可能在某些界面困惑。需要设置最大步数max_steps防止无限循环并在指令中增加更明确的成功条件描述。4.2 场景二元素属性动态变化的课程表查询教务系统的课程表页面很可能是一个WebView或者复杂自定义视图每天/每周的课程格子DOM结构或控件属性都可能变化。用Appium写XPath或CSS选择器会非常脆弱。我们的策略是让Open-AutoGLM进行“视觉查询”。指令设计指令需要从“操作型”变为“查询型”。task_instruction “查看当前页面的课程表告诉我下周一2024-05-20下午的第一节是什么课在哪个教室”流程调整智能体不需要执行点击、输入等物理操作而是需要观察课程表截图。理解课程表的结构横轴可能是时间纵轴可能是星期。定位到“下周一下午第一节”这个视觉区域。读取该区域内的文本信息课程名、教室。将结果以结构化文本如JSON或自然语言的形式输出。框架支持这要求Open-AutoGLM框架或底层模型支持“视觉问答”VQA能力。你需要检查框架是否提供了observe_and_answer这类API或者通过巧妙的提示词Prompt让模型直接输出答案。这个场景完美体现了Open-AutoGLM的价值它不关心源码只关心渲染后的最终视觉呈现。只要课程表对人眼是可读的理论上模型就能解读它。这省去了我们为动态元素编写和维护脆弱定位器的大量工作。5. 深入原理提示词工程与动作空间设计要让Open-AutoGLM智能体可靠工作仅仅调用API是不够的。我们需要深入一层理解它是如何“思考”的从而更好地引导它。这涉及到两个核心概念提示词工程和动作空间设计。5.1 构建有效的系统提示词系统提示词System Prompt定义了智能体的角色、能力和行为规范。一个糟糕的提示词会导致模型行为混乱。对于移动端自动化测试智能体一个有效的提示词应该包含角色定义“你是一个专业的移动端自动化测试助手能够通过观察手机屏幕截图来理解界面状态并执行精确的操作以完成用户指定的任务。”能力描述“你可以执行以下类型的操作点击屏幕指定坐标、在焦点输入框输入文本、向上/下/左/右滑动屏幕、按物理返回键、长按等。”输出格式约束至关重要“你必须以严格的JSON格式输出你的决策且只包含以下字段action_type只能是 click, type, swipe_up, swipe_down, press_back, long_press, done 中的一个、coordinates仅当action_type为click或long_press时存在格式为[x, y]、text仅当action_type为type时存在、swipe_distance仅当滑动时存在。不要输出任何其他解释性文字。”观察指导“在决定行动前仔细分析截图。识别按钮、输入框、文本标签、图标等关键UI元素。描述当前界面并规划达成目标的最短路径。”错误处理“如果当前界面与完成任务无关或无法理解输出action_type为done并结束任务。”实操心得输出格式的约束是稳定性的关键。大模型喜欢“说话”但我们需要它“行动”。强制JSON输出能极大提高后续代码解析的可靠性。你可以把这个系统提示词看作给智能体编写的“测试脚本规范”。5.2 设计合理的动作空间动作空间Action Space定义了智能体可以执行的所有操作集合。Open-AutoGLM默认可能提供一些基础动作但针对移动端测试我们需要对其进行设计和扩充使其更贴合实际。一个基本的移动端测试动作空间可以包括动作类型 (action_type)参数 (parameters)ADB命令示例 (示意)用途click{“coordinates”: [x, y]}adb shell input tap x y点击屏幕某处type{“text”: “要输入的字符串”}adb shell input text “hello”输入文本需先聚焦输入框swipe{“start”: [x1, y1], “end”: [x2, y2], “duration”: ms}adb shell input swipe x1 y1 x2 y2 [duration]从一点滑动到另一点press_back{}adb shell input keyevent KEYCODE_BACK按返回键press_home{}adb shell input keyevent KEYCODE_HOME按Home键long_press{“coordinates”: [x, y], “duration”: 2000}adb shell input swipe x y x y 2000长按某处done{“reason”: “成功/失败原因”}无任务结束注意事项坐标[x, y]必须是基于当前屏幕分辨率的绝对坐标。模型输出坐标后务必进行边界检查确保x, y在屏幕宽高范围内必要时可以加入随机微小偏移如±5像素模拟真人操作的不精确性避免被应用的反爬机制检测。5.3 迭代式提示词优化提示词不是一蹴而就的。你需要像一个测试经理训练新人一样不断优化给智能体的指令。记录与回放运行你的自动化脚本保存每一步的截图、模型接收的指令、模型输出的决策JSON以及最终执行的ADB命令。分析失败步骤当任务失败时查看是哪一步的决策出了问题。是模型没识别出按钮还是识别错了位置或者是输出了不符合规定的格式修正提示词如果是识别问题在系统提示词中加强关于特定UI元素的描述。例如如果它总是忽略那个灰色的“下一步”按钮可以在提示词中加入“特别注意那些颜色对比度可能不高的按钮例如灰色背景上的深灰色文字按钮。”如果是逻辑问题在用户指令中增加更多上下文和约束。例如把“登录”改为“首先确保位于登录页面然后在用户名输入框输入‘xxx’在密码输入框输入‘yyy’最后点击蓝色的‘登录’按钮”。如果是格式问题再次强调并简化输出格式要求。这个过程是Open-AutoGLM项目落地的核心工作需要耐心和细致的观察。我通常会准备一个“提示词版本库”记录每次修改和对应的效果。6. 工程化实践稳定性提升与持续集成单个脚本跑通只是第一步。要想把Open-AutoGLM用于实际的测试项目尤其是持续集成CI pipeline我们必须解决稳定性和效率问题。6.1 增强稳定性多重保障策略AI模型具有不确定性我们不能指望它100%成功。必须建立“安全网”。动作执行前校验在将模型输出的坐标发送给ADB前增加校验逻辑。def safe_execute_action(action, screen_width, screen_height): action_type action.get(‘action_type’) if action_type ‘click’ or action_type ‘long_press’: x, y action.get(‘coordinates’, (0, 0)) # 校验1坐标是否在屏幕内 if not (0 x screen_width and 0 y screen_height): print(f“警告坐标({x},{y})超出屏幕范围({screen_width},{screen_height})已置中。”) x, y screen_width // 2, screen_height // 2 # 校验2坐标是否在可点击区域这里可以加入一个简单的历史记录避免短时间内重复点击同一位置。 # 执行ADB命令...超时与重试机制为每个步骤设置合理的超时时间。如果模型在一步卡住比如done信号一直不出现或者执行后界面没有发生预期变化通过图像对比或关键元素检测判断应触发重试。重试时可以稍微修改指令例如“上次点击似乎没反应请再尝试一次”。关键状态检查点不要完全依赖模型的自主规划。在流程的关键节点如登录成功后应进入主页通过传统的图像模板匹配或OCR主动检查特定元素如“欢迎学生01”字样是否出现。如果检查失败则判定当前步骤失败触发重试或整个用例失败。这相当于在AI自动驾驶的路上设置了几个必须通过的“路标”。备用方案Fallback对于极其关键且模型识别率不高的步骤准备一个备用方案。例如登录时的验证码如果模型连续3次识别失败则自动切换到备用OCR服务并将结果通过type动作输入。6.2 提升效率缓存与并行模型推理是耗时的瓶颈。我们可以从两个方向优化截图与推理结果缓存对于相对静态的界面如App的启动页、设置菜单其UI布局是固定的。我们可以建立一个缓存字典键为界面截图的特征哈希如PHash值为该界面下模型对常见指令的响应如“点击登录按钮”的坐标。下次遇到相同界面时直接使用缓存结果跳过模型推理。这能大幅提升回归测试的速度。异步并行处理在CI环境中可以并行运行多个测试任务。每个任务独占一个手机设备或模拟器和一个模型推理实例。需要一套资源调度系统来管理设备池和模型服务。6.3 集成到CI/CD流程将Open-AutoGLM测试脚本集成到Jenkins、GitLab CI等工具中可以实现自动化回归。环境准备阶段CI Job开始时启动一个干净的模拟器或连接专用真机安装指定版本的待测APK。测试执行阶段调用你的Open-AutoGLM主脚本执行定义好的复杂场景测试用例。将模型输出的决策日志、每一步的截图保存为产物。结果分析与报告成功判定不仅看脚本是否跑完更要看关键检查点是否通过以及最终界面是否符合预期可通过截图对比或OCR验证关键文本。失败分析收集失败的截图和日志。由于AI的不确定性失败可能是“非致命”的如一次偶然的识别错误。可以设定一个重试阈值只有连续失败超过阈值才标记为用例失败。可视化报告生成HTML报告展示测试步骤的截图序列并用高亮框标出模型每次点击的位置一目了然地看到智能体的“操作轨迹”。资源清理测试结束后卸载App清理设备为下一次任务做好准备。重要提示在CI中运行要特别注意模型服务的稳定性和成本控制。如果使用云端API需设置预算警报。使用本地模型则需要确保CI机器有足够的GPU内存。7. 常见问题排查与效能调优实录在实际把玩Open-AutoGLM的过程中我遇到了不少“坑”。这里把一些典型问题和解决思路记录下来希望能帮你节省时间。7.1 模型相关的问题问题模型响应速度极慢或经常超时。排查首先确认是网络问题还是模型本身问题。如果是本地部署的模型检查GPU使用率nvidia-smi和内存占用。可能是模型太大显存不足导致反复换页。解决尝试量化模型如使用GPTQ、AWQ等方法在精度损失可接受的前提下大幅减少显存占用和提升推理速度。换用更小的模型如Qwen-VL-Chat-Int4。如果是API调用检查网络延迟考虑使用国内可访问的镜像或代理此处需注意合规性仅指技术上的网络优化。问题模型“看不懂”界面输出无意义的动作或直接说无法完成。排查查看模型接收到的完整提示词系统提示词用户指令历史截图。可能是截图分辨率太高或太低导致模型无法识别细节。解决调整截图质量将截图缩放至模型训练时常见的分辨率如336x336, 448x448。Open-AutoGLM框架可能内置了处理如果没有需要手动PIL.Image.resize。增强指令在用户指令中加入更明确的上下文。例如不要只说“点击登录”而是说“在当前这个以蓝色为背景的登录页面点击右下角那个白色的‘登录’按钮”。提供示例Few-Shot在系统提示词中加入一两个成功的操作示例教模型应该如何输出。例如“示例1当屏幕是一个有用户名和密码输入框的界面时如果目标是输入用户名‘admin’则应输出{‘action_type’: ‘type’, ‘text’: ‘admin’}。”7.2 框架与执行相关的问题问题ADB命令执行成功但App没有反应。排查最常见的原因是坐标点击在了无效区域。用adb shell getevent或Appium Inspector的“Tap”功能验证你发送的坐标是否真的对应了可点击元素。解决在代码中增加点击前的日志打印出即将点击的坐标。用Appium Inspector手动点击该坐标看是否有反应。考虑在点击前先让模型执行一个swipe或press_back等无关操作“唤醒”一下界面有时界面元素加载有延迟。检查应用是否有无障碍模式或特殊权限要求某些操作可能需要开启。问题任务陷入循环模型在两个状态间来回切换。排查这通常是因为模型没有准确感知到界面状态的变化。例如点击登录按钮后应该跳转到主页但模型可能认为还在登录页于是又去点击登录按钮。解决强制状态刷新在执行一个预期会引起界面大变动的操作如点击登录后增加一个等待时间time.sleep(3)并强制重新截图。引入状态记忆让模型在输出动作时也简单描述一下它认为的当前界面。在下一步的提示词中把上一步的界面描述和历史截图一起喂给模型帮助它建立连续记忆。Open-AutoGLM框架可能支持会话历史需要查阅其文档。设置状态检查点如前所述在关键节点用传统方法验证状态如果验证不通过则给模型一个明确的错误反馈引导它修正。7.3 效能调优建议截图频率优化不是每一步之后都需要立即截图。对于快速连续的操作如输入一串文字可以在所有输入完成后再截图减少模型调用次数。模型预热在开始正式测试套件前先跑一个简单的热身任务如打开设置菜单让模型加载到GPU显存中避免第一个任务因冷启动而超时。操作聚合对于一些复杂的、模型不擅长的精细操作如在文件管理器里按特定顺序选择多个文件可以将其封装成一个“宏动作”由传统脚本完成而对模型只暴露一个高级指令“选择文件A、B、C”。结果置信度如果框架支持可以关注模型输出动作时的置信度分数。对于低置信度的操作比如模型自己都很犹豫该点哪里可以触发重试或启用备用方案而不是盲目执行。经过这些调试和优化Open-AutoGLM从一個“有趣的概念验证”逐渐变成了一个能在特定复杂场景下稳定工作的“特种兵”。它确实无法像Appium那样进行高速、大规模的全量UI遍历但在攻坚那些动态、非标准、需要视觉理解的测试堡垒时它展现出了不可替代的独特价值。