Midscene 视觉驱动 UI 自动化测试实战指南:从零跑通 YAML 脚本
【免费下载链接】midsceneGUI Agent for E2E Testing项目地址: https://gitcode.com/GitHub_Trending/mid/midscene
维护一套基于选择器的 UI 自动化测试有多痛苦,做过重构的人都知道:DOM 一变,几百个选择器全得跟着改,原生 App 和 canvas 更是无从下手。Midscene 换了一条路——它只认屏幕截图,你用自然语言写 UI 自动化测试步骤,多模态模型负责看屏、定位、点击,Web、Android、iOS 到桌面共用同一套接口。
选型背景:为什么换成纯视觉
传统方案依赖选择器、DOM 或可访问性树,结构一重构就失效,且看不见"渲染出来的东西"对不对。Midscene 的定位很直接:只要人能看见的元素它就能操作,包括纯图标按钮、canvas 绘图和原生界面,断言的也是用户真正看到的画面,而不是某个节点是否存在。它内置了 Playwright 和 Puppeteer 两条接入路径,适合已有测试框架想补一层语义化断言的团队,也适合想快速给移动端和桌面补 E2E 覆盖的场景。
5 分钟跑通:第一个 UI 自动化测试脚本
先全局安装 CLI,它自带 Puppeteer,不需要额外起浏览器:
npm install -g @midscene/cliMidscene 的模型配置走统一的环境变量(见 shared 环境变量模块),指向任意 OpenAI 兼容的多模态服务即可:
export MIDSCENE_MODEL_NAME="qwen-vl-max" # 模型名 export MIDSCENE_MODEL_BASE_URL="https://你的网关/v1" export MIDSCENE_MODEL_API_KEY="你的key"仓库里 cli 包 支持直接执行 YAML 脚本,web段配 URL,tasks段写步骤。下面是最小用例:
web: url: https://www.saucedemo.com/ tasks: - name: 登录 flow: - aiAct: 在用户名输入框输入 standard_user,密码输入 secret_sauce,点击登录 - aiWaitFor: 商品列表页出现 - name: 断言与提取 flow: - aiAssert: 页面顶部显示 My Store - aiQuery: "{name: string, price: number}[] 所有商品名称和价格" name: items执行并指定并发数,跑完自动生成本地 HTML 报告:
midscene ./demo.yaml --concurrent 2 --headed--headed能看到浏览器实时操作,第一次跑建议开着,心里有底。执行入口在 cli 主逻辑,--keep-window可以保持窗口不关方便观察。
核心能力拆解
YAML 自然语言用例
解决"写用例必须懂测试框架"的问题。步骤类型在 YAML 类型定义里一目了然:aiAct执行操作、aiWaitFor条件等待、aiAssert断言画面、aiQuery按 schema 提取 JSON 数据、javascript执行页面脚本。非开发同学也能维护测试。
一套脚本多平台
解决"同一业务四端各写一遍"的问题。把顶层的web段换成android或computer即可,任务流原样保留:
android: deviceId: emulator-5554 launch: com.android.settings tasks: - name: 打开设置 flow: - aiAct: 点击 WiFi 开关 - aiAssert: WiFi 开关处于开启状态各平台包负责设备桥接:Android 走 scrcpy/adb、iOS 走 WebDriverAgent、桌面端,上层 Agent 逻辑完全复用。
执行报告与回放
每步动作、截图、AI 思考都会落到 HTML 报告里,由 core 报告模块生成。报告是排查"AI 为什么点错"的第一现场,也是 CI 里给团队看的交付物。
进阶玩法:省调用、提速
问题:同样的登录流程跑一百遍,AI 调用费用也烧一百遍。解法:Agent 层内置缓存,给重复动作打上缓存 ID,命中后直接复用定位结果:
agent: cache: id: saucelab-login # cache 必须显式给 id未开启缓存时的基线耗时,供对照:
问题:几十个用例串行,一次回归跑半小时。解法:用--concurrent把用例打散到多个浏览器实例并行执行;如果多个用例要共享登录态,再加shareBrowserContext和一个setup前置脚本(定义见 YAML 批处理配置),setup 失败会中止整批,适合把登录放在前置里做一次。
踩坑与排障
aiAct 定位失败或点到相邻元素。这个坑我常遇到,通常是描述太泛。把"点击登录"改成"点击输入框右侧蓝色的登录按钮",加上位置、颜色这类视觉锚点;确实在动态区域,再用deepLocate: true让模型多看一层细节,代价是慢一点。
aiWaitFor 超时但人眼看页面已就绪。先确认它等的视觉状态是否真的出现,而不是元素"存在"。异步渲染的页面把timeout适当调大,并在它前面留一个aiAct: 等待页面加载完成做缓冲,比全局 sleep 可控。
cache 报错"requires an explicit cache ID"。见 缓存配置校验,cache: true不会生效,必须写成cache.id + strategy。
旧教程里的midscene --url ... --action ...跑不通。CLI 已移除该交互模式,只认 YAML 脚本,按上文写法迁移即可。Android 设备连不上的话,先在手机上开 USB 调试,再确认 adb 能看到设备,YAML 里用deviceId明确指定。
生态与扩展
项目是 pnpm monorepo,core 服务层负责模型调用与任务规划,shared 包沉淀跨平台的 Agent 工具,周边还有 Playwright/Puppeteer 集成包、可视化控制台和测试报告应用。仓库内 docs 目录有完整的平台接入与模型配置文档,建议配合阅读。
回到开头那个问题:选择器维护的痛,Midscene 用"看屏幕"换成了"写人话"。代价是每次执行都有模型调用的时间和成本,但换来的是重构免疫和真正的跨平台。建议先 clone 下来跑通 saucedemo 这个最小用例,再决定要不要把它带进你的测试体系——大概率你会想把它推到 Android 上再试一把。
【免费下载链接】midsceneGUI Agent for E2E Testing项目地址: https://gitcode.com/GitHub_Trending/mid/midscene
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考