Midscene.js 怎么用:自然语言驱动 UI 自动化
【免费下载链接】midsceneGUI Agent for E2E Testing项目地址: https://gitcode.com/GitHub_Trending/mid/midscene
🔍 选择器又挂了:卡住的真实场景
用 Midscene.js 做 UI 自动化之前,我最后一次改选择器是深夜十一点:把div:nth-child(3) > span换成.product-card > a:nth-of-type(2),部署完还是挂了。挂的位置更糟——一个 Canvas 画出来的"立即购买"按钮,DOM 里根本没有这个节点,XPath 写得再准也够不着。那一刻我确认了一件事:靠页面结构定位的自动化,在重构和画布界面前就是脆弱的。Midscene.js 走的是另一条路:不看结构,只看截图,用自然语言描述每一步。
🧭 它到底是什么:定位与边界
一句话定位:Midscene.js 是一个 GUI Agent for E2E Testing——用多模态模型看界面截图、按自然语言指令执行操作的 UI 自动化工具,Web、Android、iOS、HarmonyOS、桌面端共用一套 API。
说清楚它不做什么,边界比功能列表更有用:
- 它不是"选择器增强",不帮你写 CSS/XPath。截图是主输入,DOM 只是可选辅助,不是依赖。
- 它第一目标是 UI 测试,不是通用爬虫。抓取、流程自动化是同一套引擎顺带的场景。
- 它不带模型、不带设备:模型服务要你自己接,Android 要 adb,iOS 要 WebDriverAgent。
🚀 最小上手路径:从 YAML 到第一份报告
第一次上手最短的路径是 YAML + CLI,不写一行 JavaScript。
先全局装好命令行工具:
npm i -g @midscene/cli新建一个bing-search.yaml,这就是完整的第一份自动化脚本:
page: url: https://www.bing.com tasks: - name: 搜索天气 flow: - ai: 搜索 "今日天气" - sleep: 3000 - aiAssert: 结果显示天气信息跑之前补一件准备:模型配置。在运行目录放一个.env,写四个以MIDSCENE_MODEL_开头的变量(BASE_URL、API_KEY、NAME、FAMILY),取值按你用的模型服务来,官方文档给了各家示例。配置就位后,一条命令跑起来:
midscene ./bing-search.yaml执行完控制台会打印report file updated: ...html,浏览器打开它:每一步的截图、AI 的规划、耗时都在这份报告里。不想搭环境的话,也可以先装 Chrome 扩展,在侧边栏直接输指令体验,验证过再落到脚本。
Midscene.js 的 Chrome 扩展侧边栏:在任意网页上输入自然语言指令,即可执行操作、提取数据、断言界面
🗺️ 能力地图:按场景对号入座
| 能力域 | 核心 API / 形态 | 典型使用场景 |
|---|---|---|
| 规划式交互 | aiAct | 多步骤、有分支的任务,如"关弹窗→选规格→进结算页" |
| 即时交互 | aiTap/aiInput/aiScroll | 目标明确的单步操作,快且省 token |
| 界面理解 | aiQuery/aiAssert/aiBoolean | 结构化提取、对渲染结果做断言 |
| 异步等待 | aiWaitFor | 加载动画结束、内容出现后再继续操作 |
| 跨平台 | Web / Android / iOS / HarmonyOS / 桌面 | 同一套 API 换设备跑,脚本只换设备段配置 |
| 无代码脚本 | YAML +midsceneCLI | 非测试同学也能维护和执行回归流程 |
| 可视化报告 | HTML 报告 +report-tool | 回放失败步骤、CI 产物归档 |
Midscene.js 控制 Android 设备的 Playground:设备连接后,同样用自然语言驱动操作
表里没写透的两点:桥接模式(Bridge)可以控制本地已登录的浏览器会话,适合复用 Cookie 的站内操作;缓存让重复执行的规划和定位直接复用,工程化部分展开。
Midscene.js 桥接模式:让本地运行的浏览器会话接入自动化控制
🛒 深入案例:电商搜索的视觉回归
选一个最有代表性的场景:电商搜索结果页的视觉回归。传统做法是写一堆选择器抓标题和价格,再用正则对数字,UI 一改版全部重写。思路换成"描述你期望看到什么":脚本里只写意图,页面结构由模型现场看。
Playwright 负责驱动浏览器,PlaywrightAgent把它接进截图-规划-执行的循环:
import { chromium } from 'playwright'; import { PlaywrightAgent } from '@midscene/web/playwright'; const browser = await chromium.launch({ headless: true }); const page = await browser.newPage(); await page.goto('https://www.ebay.com'); const agent = new PlaywrightAgent(page); await agent.aiAct('type "Headphones" in search box, hit Enter'); await agent.aiWaitFor('there is at least one headphone item on page'); // 一次调用拿到结构化结果:标题 + 价格 const items = await agent.aiQuery('{itemTitle: string, price: number}[]'); // 断言渲染结果,而不是断言 DOM 节点存在 await agent.aiAssert('There is a category filter on the left');浏览器侧的接入实现可以看 packages/web-integration/src/playwright/。按官方示例项目的实际输出,aiQuery返回一条条{itemTitle, price},比如 JBL Tour Pro 2 对应 551.21;再问一句"第一个耳机价格是否超过 1000",就能把异常价格写成会失败的断言。(aiWaitFor出现之前我用 sleep 硬等,这个等待时间我调了三遍,最后才明白该用视觉等待。)
跑完打开报告,每一步 AI"看到"的画面和规划都在眼前,失败时定位问题不用猜。
Midscene.js 生成的可视化执行报告:时间轴上每一步都带截图、规划与耗时
模型选型直接影响成本和稳定性:开源的 UI-TARS、Qwen-VL 系列可自部署,商业模型按 API 接入,各家模型的适配层在 packages/core/src/ai-model/。
⚙️ 工程化落地:把视觉测试接进 CI
CI 集成。YAML 脚本 + CLI 天然适合流水线:一条命令跑完一个用例,aiAssert失败即退出码非零,CI 自然把它当测试失败。报告是产物的一部分——多个用例的报告用report-tool的merge-html合并成一份;截图多导致 HTML 过大时,把 reporter 的outputFormat设成html-and-external-assets,截图拆成独立 PNG。注意这种报告必须走 HTTP 访问(npx serve起个服务即可),file://直接打开会因为 CORS 看不到图。命令行工具的实现可以看 packages/cli/src/。
成本与速度。重复跑的回归最适合开缓存:给 Agent 配一个 cache id,AI 规划和 Web 端的 XPath 定位都会落盘复用,官方文档的示例里同一段流程从 51 秒降到 28 秒。YAML 脚本里这样配:
agent: cache: id: ebay-search协作与监控。报告不是只能给人看的 HTML:report-tool支持split拆出原始 JSON 和截图、to-markdown转成 Markdown,喂给任何下游工具都行。非测试同学改流程时只动 YAML,门槛比改代码低得多,测试脚本也就从测试团队的私产变成了产品流程的说明书。
⚠️ 避坑与边界:用过才说得清
- 模型是天花板。要求不是"会 OCR",而是"有 UI 定位能力"——同一个模型能读出按钮文字,不代表能点准按钮。
MIDSCENE_MODEL_FAMILY会影响提示词策略,别漏配。 aiAct贵且慢。每次调用都含规划和可能的重规划,单步操作直接用aiTap/aiInput;目标元素小、容易和周围混淆时,加deepLocate多花一次调用换定位精度。- 缓存会"记错"。规划缓存命中但页面状态变了(比如弹窗这次没出现),会自动回退到 AI 规划并清掉过期流程;查询类 API 永远不走缓存。UI 改版后定位变怪,先怀疑缓存。
- Chrome 扩展冲突。报
Cannot access a chrome-extension:// URL of different extension,是别的扩展往页面注入了 iframe/script。按官方 FAQ:在开发者工具里找到那个 URL,拿扩展 ID 去chrome://extensions/禁用它,刷新重试。 - Node 版本有门槛。CLI 要求 Node 20.19+/22.12+/24+,较旧的 20.x patch 会被 Rspack 直接拒(
Unsupported Node.js version),升级 Node 再装。
📍 下一步:三条延伸路径
- 读官方文档的 Model Strategy 章节,按团队情况定:自部署 UI-TARS / Qwen-VL,还是走云端 API,两者成本和稳定性差得远。
- 做个小实验:同一个 YAML 配上 cache id 连跑两遍,打开两份报告对比每步耗时,直观感受缓存命中与未命中的差别。
- 老版 YAML Runner 官方已标注有下一代 Test Runner(Beta),新项目直接看 Test Runner 概览章节,避免走回头路;问题可以丢到 Discord 或飞书群(仓库 README 里有入口),比翻 issue 快。
【免费下载链接】midsceneGUI Agent for E2E Testing项目地址: https://gitcode.com/GitHub_Trending/mid/midscene
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考