ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Midscene AI UI 自动化测试运行原理拆解:截图、多模态大模型与 Playwright 如何串成一条链路?

Midscene AI UI 自动化测试运行原理拆解:截图、多模态大模型与 Playwright 如何串成一条链路? 1. 从一次“找不到按钮”的崩溃说起如果你写过 Playwright 或 Selenium 脚本大概率经历过这种时刻昨天还能跑通的用例今天页面改了个 class 名page.click(#submit-btn)直接超时。你打开 DevTools 一看按钮还在那儿只是 ID 从submit-btn变成了submitBtn。于是你花半小时改选择器改完发现另一个元素也挂了。Midscene 想解决的就是这个问题。它是一个 AI 驱动的 UI 自动化测试框架核心思路很直接既然人是用眼睛看屏幕来操作的那就让 AI 也“看”屏幕——截图丢给多模态大模型模型告诉你“登录按钮在坐标 (420, 310)”然后 Playwright 去点这个坐标。整个过程不依赖 DOM、不依赖选择器页面结构怎么改都不影响。这篇文章面向想搞懂 Midscene 内部运行链路的开发者。我会把“截图 → 多模态大模型理解 → Playwright 执行”这条链路拆开讲清楚同时给出可复制的 Playwright 配置骨架以及 Midscene 接入 TaoToken 统一 Key/API 通道的settings.json示例。最后用一个从截图到点击的验证动作确认整条链路真的跑通了。适合谁看已经会用 Playwright 写基础脚本但对 AI UI 自动化的内部机制好奇想自己动手接一套跑起来的人。不需要你懂模型训练但需要你能看懂 TypeScript 和 JSON 配置。2. 前置准备TaoToken 统一 Key 与 Midscene 环境Midscene 本身不绑定某一家模型厂商它通过环境变量或配置文件读取模型名称、API Key、Base URL。这意味着你可以把模型调用统一走一个兼容 OpenAI 协议的中转通道TaoToken 就是干这个的——一个 Key 覆盖多家视觉语言模型省得你在豆包、Qwen、GLM 之间来回注册和切换。先拿到 Key。访问 TaoToken 控制台https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite注册后在 API Keys 页面创建一个新 Key复制出来形如sk-xxxxxxxx。这个 Key 后面会写进 Midscene 的配置里。Midscene 的模型调用走的是 OpenAI 兼容接口所以 Base URL 填https://taotoken.net/api注意这里不加 UTM 参数API 地址保持干净。模型名称填你实际要用的视觉语言模型比如qwen3-vl-plus或doubao-seed-1.6。具体支持哪些模型可以在模型对话页面https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite确认当前可用的列表。环境侧需要 Node.js 18 和 Playwright。如果你还没装 Playwright先跑npm init -y npm install playwright midscene/web npx playwright install chromiummidscene/web是 Midscene 的 Web 端包它内部依赖 Playwright 或 Puppeteer 作为执行层。装完之后你的项目目录里应该有node_modules/midscene/web说明环境就绪。3. 可复制配置settings.json 与 Playwright 骨架Midscene 的配置有两种方式环境变量和settings.json。环境变量适合 CI 里临时注入settings.json适合本地开发固定下来。我推荐用settings.json因为模型分层配置写在一起更清晰。在项目根目录创建midscene/settings.json{ modelConfig: { MIDSCENE_MODEL_NAME: qwen3-vl-plus, MIDSCENE_MODEL_API_KEY: sk-你的TaoTokenKey, MIDSCENE_MODEL_BASE_URL: https://taotoken.net/api, MIDSCENE_MODEL_FAMILY: qwen3-vl, MIDSCENE_PLANNING_MODEL_NAME: gpt-5.1, MIDSCENE_PLANNING_MODEL_API_KEY: sk-你的TaoTokenKey, MIDSCENE_PLANNING_MODEL_BASE_URL: https://taotoken.net/api, MIDSCENE_INSIGHT_MODEL_NAME: qwen-vl-plus, MIDSCENE_INSIGHT_MODEL_API_KEY: sk-你的TaoTokenKey, MIDSCENE_INSIGHT_MODEL_BASE_URL: https://taotoken.net/api }, cache: { id: midscene-demo, strategy: read-write } }这里有三层模型MIDSCENE_MODEL_*是默认模型负责元素定位visual groundingMIDSCENE_PLANNING_MODEL_*负责把自然语言拆成步骤MIDSCENE_INSIGHT_MODEL_*负责数据提取和断言。三层可以指向同一个模型也可以分开。分开的好处是规划用强推理模型、定位用强视觉模型各干各的活。MIDSCENE_MODEL_FAMILY这个字段容易被忽略但它很重要。它告诉 Midscene 当前模型属于哪个家族框架会根据家族调整 prompt 模板和坐标解析逻辑。填错了会导致定位坐标偏移或解析失败。Qwen 系列填qwen3-vl豆包系列填doubao-vl具体值参考接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite。接下来是 Playwright 骨架。创建test/login.spec.tsimport { test, expect } from playwright/test; import { PlaywrightAgent } from midscene/web; test(GitHub 登录页 AI 操作验证, async ({ page }) { const agent new PlaywrightAgent(page, { // 指向 settings.json 所在目录 aiActionContext: 这是一个 GitHub 登录页面, }); await page.goto(https://github.com/login); // 截图 → 模型定位 → Playwright 点击 await agent.aiTap(用户名输入框); await agent.aiInput(用户名输入框, testuser); await agent.aiTap(密码输入框); await agent.aiInput(密码输入框, password123); await agent.aiTap(Sign in 按钮); // AI 断言页面是否出现错误提示或跳转 await agent.aiAssert(页面显示了错误提示或跳转到了首页); });aiTap和aiInput属于 Instant Action 模式——你明确告诉它“点哪个元素”AI 只负责定位不负责规划。这种模式比aiAct更快更稳因为省掉了规划层的模型调用。如果你要写多步复杂流程再用aiAct让规划模型拆解。4. 验证请求一次截图到点击的完整链路配置写好了怎么确认整条链路真的通了我建议用一个最小验证动作打开一个空白页放一个按钮让 Midscene 截图、定位、点击然后检查点击是否生效。创建test/verify.spec.tsimport { test, expect } from playwright/test; import { PlaywrightAgent } from midscene/web; test(最小链路验证截图到点击, async ({ page }) { const agent new PlaywrightAgent(page); // 构造一个带按钮的页面 await page.setContent( html body stylepadding: 100px; button idtarget stylewidth:200px;height:60px;font-size:20px; onclickdocument.getElementById(result).innerTextclicked 确认提交 /button div idresult stylemargin-top:20px;not clicked/div /body /html ); // 截图 → 模型定位 → 点击 await agent.aiTap(确认提交按钮); // 验证点击是否真的生效 const result await page.locator(#result).innerText(); expect(result).toBe(clicked); });跑这个用例npx playwright test test/verify.spec.ts --headed你会看到浏览器打开Midscene 截取当前页面把截图和指令“找到确认提交按钮”发给 TaoToken 通道模型返回按钮坐标Playwright 在坐标处执行点击。页面上的#result从not clicked变成clicked说明整条链路跑通了。运行结束后Midscene 会在midscene_run/report/下生成一个 HTML 报告。打开它你能看到每一步的截图、模型返回的坐标、耗时和 Token 消耗。这个报告是调试利器——如果定位偏了你能直接看到模型“看到”的截图长什么样判断是截图问题还是 prompt 问题。5. 本篇常见错排查报错一MIDSCENE_MODEL_FAMILY不匹配导致坐标偏移现象是模型返回了坐标但点击位置偏了几十像素。原因通常是MIDSCENE_MODEL_FAMILY填的值和实际模型不匹配框架用了错误的坐标归一化逻辑。解决方法是确认模型家族值Qwen3-VL 系列填qwen3-vl不要填qwen或qwen-vl。如果拿不准去接入文档查对应模型的 family 值。报错二401 Unauthorized或Invalid API Key先检查settings.json里的 Key 有没有多余空格再确认 Base URL 是https://taotoken.net/api而不是带路径的完整地址。Midscene 会在 Base URL 后面自动拼/v1/chat/completions如果你填了https://taotoken.net/api/v1就会变成/api/v1/v1/chat/completions直接 404。Key 的管理和重新生成在 API Keys 页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite。报错三截图成功但模型返回“找不到元素”这种情况多半是截图分辨率太低或者元素在视口外。Midscene 默认截取当前视口如果目标元素需要滚动才能看到模型自然找不到。解决办法是先page.scrollIntoView或者用aiScroll滚动到目标区域再定位。另外如果页面有大量动态加载内容截图时可能还没渲染完加一个await page.waitForLoadState(networkidle)再截图。报错四缓存导致定位结果过期cache.strategy设为read-write时第二次运行会直接读缓存跳过模型调用。如果页面结构变了但缓存没失效定位就会用到旧坐标。调试阶段建议把 strategy 改成read-only或直接删掉midscene_run/cache/目录。CI 环境用read-only本地开发用read-write这是比较稳的组合。报错五Playwright 版本和 Midscene 不兼容midscene/web对 Playwright 版本有要求太新或太旧都可能出问题。如果遇到agent.aiTap is not a function这类错误先检查package.json里 Playwright 的版本对照 Midscene 的 peerDependencies 调整。一般锁在最近两个大版本内比较安全。6. 把链路接进你的项目Midscene 的运行链路拆开看就三件事Playwright 负责截图和执行多模态大模型负责理解截图并返回坐标Midscene 框架负责把两者串起来并处理规划、缓存、报告。你不需要改 Playwright 的底层逻辑只需要在现有脚本里把page.click(selector)换成agent.aiTap(自然语言描述)。如果你打算长期在项目里用这套方案建议把模型调用统一走 TaoToken 的 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite一个 Key 覆盖规划、定位、理解三层模型省去多厂商切换的麻烦。接入文档里有完整的模型家族对照表和配置字段说明遇到 family 值不确定的时候直接查表。最后留一个实操建议先用aiTap和aiInput这类 Instant Action 把核心流程跑通确认定位稳定之后再逐步引入aiAct和deepThink处理复杂多步场景。不要一上来就全用aiAct规划层的模型调用会增加不确定性和 Token 消耗调试起来也更费劲。
返回列表