1. 当 Playwright 遇上 MCP:让 AI 智能体自己跑 UI 回归
UI 回归测试最让人头疼的地方,不是写不出脚本,而是页面一改、文案一换,昨天还绿的用例今天就红了。Playwright 已经把「跨浏览器、自动等待、Trace 回放」这些基础能力做得足够扎实,但脚本的编写与维护依然要人盯着 DOM 结构、选择器和断言逻辑。MCP(Model Context Protocol)出现之后,思路变了:把 Playwright 的「打开页面、点击、输入、截图、读取快照」封装成标准工具,交给 AI 智能体去规划步骤、观察页面、决定下一步动作,人只需要给出「测试登录流程」这样的目标描述。
这套组合适合谁?一是手上已有 Playwright 用例、想降低维护成本的测试同学;二是正在做 AI Agent 应用、需要给智能体接一个「能操作浏览器」的工具层的开发者;三是想快速做探索性回归、又不想每次手写脚本的团队。它不能替代稳定的 CI 断言脚本,但作为「自主规划 + 执行 + 报告」的补充层,价值很直接。
下面我从零把 MCP 配置骨架、TaoToken 统一 Key 接入、一次登录回归用例的验证动作串起来,目标是从配置到跑通全流程。中间会给出可复制的 JSON 配置、环境变量写法和排障清单,你照着改域名和账号就能用。
2. 前置准备:TaoToken 统一 Key 与 MCP 运行环境
2.1 为什么这里要接 TaoToken
AI 智能体在回归测试里要频繁调用大模型做「看快照 → 决策 → 生成下一步动作」,token 消耗比普通对话高得多。如果每个模型单独申请 Key、单独配 base_url,配置会散落在 MCP server、Agent 框架、CI 变量好几处,排查起来很痛苦。TaoToken 提供的是统一 API 通道:一个 Key、一个 base_url,就能在模型对话、Coding Plan、API Keys 之间切换,MCP 里的模型配置只写一份。
官网入口在这里,注册和查看文档都从这进:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=
API 通道地址(配置里填这个,不带 UTM):https://taotoken.net/api
2.2 环境与依赖
我用的组合是 Node.js 20 + Playwright MCP server + 一个支持 MCP 的 Agent 客户端。Playwright 官方提供了@playwright/mcp这个 server 包,通过 stdio 暴露工具。先装依赖:
# 初始化一个工作目录 mkdir pw-mcp-regression && cd pw-mcp-regression npm init -y # 安装 Playwright MCP server 与浏览器 npm i -D @playwright/mcp npx playwright install chromium如果你用的是 Python 侧的 Agent 框架,也可以只把 MCP server 当独立进程启动,通过 stdio 连接,语言不冲突。
2.3 拿到 TaoToken Key
进入控制台的 API Keys 页面创建一个 Key,复制出来。这个 Key 后面会写进 MCP 配置的env里,不要硬编码进仓库。控制台地址:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=
注意:Key 只显示一次,建议先存进本地
.env或系统的密钥管理,再往配置文件里引用。
3. 可复制的 MCP 配置骨架(含 TaoToken 通道)
3.1 MCP server 配置 JSON
大多数支持 MCP 的客户端(Claude Desktop 风格、Cline、各类 Agent 框架)都吃这样一份mcpServers配置。把它保存为mcp.config.json:
{ "mcpServers": { "playwright": { "command": "npx", "args": [ "@playwright/mcp@latest", "--headless", "--isolated", "--viewport-size=1280,800" ], "env": { "PLAYWRIGHT_HEADLESS": "true" } }, "taotoken-llm": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-openai-compatible"], "env": { "OPENAI_BASE_URL": "https://taotoken.net/api", "OPENAI_API_KEY": "${TAOTOKEN_API_KEY}", "OPENAI_MODEL": "claude-sonnet-4-5" } } } }几个参数说明,方便你按需改:
| 参数 | 作用 | 建议 |
|---|---|---|
--headless | 无头模式运行浏览器 | CI 里必开,本地调试可去掉看界面 |
--isolated | 每次会话独立上下文 | 回归测试避免脏状态,建议保留 |
--viewport-size | 固定视口尺寸 | 与快照裁剪、截图断言相关,写死更稳 |
OPENAI_BASE_URL | 统一模型通道 | 固定填https://taotoken.net/api |
OPENAI_MODEL | 智能体决策用的模型 | 复杂规划选强模型,简单回归可换轻量模型 |
3.2 环境变量注入
配置里用了${TAOTOKEN_API_KEY}占位,实际运行时通过环境变量注入,避免 Key 进版本库:
# .env(加入 .gitignore) export TAOTOKEN_API_KEY="sk-你的Key" export TAOTOKEN_BASE_URL="https://taotoken.net/api"启动 Agent 客户端前source .env,或者在客户端的 env 配置里直接引用系统变量。这样同一份mcp.config.json可以在本地、CI、同事机器之间复用,只换环境变量。
3.3 验证 MCP server 是否起来
先单独把 Playwright MCP server 拉起来,确认工具列表能正常返回:
npx @playwright/mcp@latest --headless --isolated正常的话进程会挂在 stdio 上等待 JSON-RPC 消息,不报错即视为启动成功。如果客户端支持「查看已连接工具」,应该能看到browser_navigate、browser_click、browser_type、browser_snapshot、browser_take_screenshot这类工具名。看到它们,说明「手和眼」已经接上了。
4. 一次登录回归用例:从指令到跑通
4.1 给智能体的任务描述
MCP 接好之后,回归测试的「脚本」变成了一段自然语言任务。我在客户端里输入的目标是这样的:
打开 https://example.com/login ,用账号 test@example.com / 密码 Test1234 登录,登录后确认页面出现「控制台」字样或用户邮箱,若出现则报告 PASS,否则报告 FAIL 并附上当前页面快照摘要。
智能体的执行链路大致是:browser_navigate打开登录页 →browser_snapshot拿可访问性树快照 → 从快照里识别用户名框、密码框、登录按钮 → 依次browser_type、browser_click→ 跳转后再次browser_snapshot→ 在快照文本里匹配成功标识 → 输出结论。
4.2 快照长什么样
快照不是outerHTML的粗暴拷贝,而是精简过的可访问性树,大致形态如下(示意):
<base url="https://example.com/login"/> <title>用户登录</title> <body> <main aria-label="登录表单"> <h1>欢迎回来</h1> <form> <label for="username">用户名</label> <input id="username" type="text" aria-required="true" placeholder="邮箱或手机号"> <label for="password">密码</label> <input id="password" type="password" aria-required="true"> <button type="submit" aria-busy="false">登录</button> </form> <a href="/forgot-password">忘记密码?</a> </main> </body>智能体就是靠label、role、placeholder这些语义信息定位元素的。这也是为什么后面排障时,第一件事往往是看快照里到底有没有那个元素。
4.3 用 Playwright 脚本固化这次回归
智能体跑通一次之后,最有价值的动作是把这次操作固化成可重复执行的 Playwright 脚本,放进 CI。下面这段就是上面流程的等价脚本:
// tests/login.spec.js const { test, expect } = require('@playwright/test'); test('登录后进入控制台', async ({ page }) => { await page.goto('https://example.com/login'); await page.getByLabel('用户名').fill('test@example.com'); await page.getByLabel('密码').fill('Test1234'); await page.getByRole('button', { name: '登录' }).click(); // 等待跳转并断言成功标识 await expect(page.getByText('控制台')).toBeVisible({ timeout: 10000 }); await expect(page).toHaveURL(/dashboard/); });跑起来:
npx playwright test tests/login.spec.js --reporter=line预期输出类似1 passed。这一步的意义在于:智能体负责「探索和生成」,脚本负责「稳定回归」,两者分工明确。
4.4 成功结果的判定标准
一次回归算跑通,我一般看三个信号:一是智能体最终输出里明确给出 PASS/FAIL 且附了依据(匹配到的文本或 URL);二是browser_take_screenshot截到的落地页与预期一致;三是固化的 Playwright 脚本在本地和 CI 都能稳定通过。三者都满足,这条回归用例才算真正落地。
5. 本篇常见错排查
5.1 MCP server 启动即退出
最常见的原因是npx拉包失败或 Node 版本过低。先手动执行npx @playwright/mcp@latest --help,能打印帮助说明包没问题;如果报EACCES或网络超时,检查 npm 源和代理设置。另外--isolated和--headless拼写错误也会让进程直接退出,日志里通常有unknown option。
5.2 智能体找不到元素
先看快照里有没有目标元素。如果快照里没有,多半是元素被display:none过滤掉了,或者它是伪元素生成的图标。解决办法是给关键交互元素补aria-label或data-testid,让快照能稳定捕获。如果快照里有但智能体点错,通常是页面上有多个同名按钮,这时在任务描述里加上「点击表单内的登录按钮」这类限定语,或者改用更精确的getByRole定位。
5.3 模型调用 401 / 404
401 一般是 Key 没注入成功,检查TAOTOKEN_API_KEY是否在当前 shell 生效,echo $TAOTOKEN_API_KEY能看到值才行。404 多半是 base_url 写错,注意统一通道地址是https://taotoken.net/api,不要多加/v1之类的后缀,具体以接入文档为准。文档入口:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=
5.4 回归结果不稳定
如果同一条用例时好时坏,先排查是不是每次会话复用了浏览器上下文导致状态残留,--isolated能缓解。其次是等待策略,智能体决策有延迟,页面异步渲染没完成就取快照会拿到半成品,可以在任务描述里要求「等待网络空闲后再取快照」,或在固化脚本里用waitForLoadState('networkidle')。
5.5 成本与速度超预期
每一步操作都伴随一次快照和一次模型推理,复杂流程的 token 消耗会明显上升。优化方向有两个:一是把探索阶段和回归阶段分开,探索用强模型,回归用固化脚本不再调模型;二是给快照做裁剪,只保留视口内和交互相关元素,减少上下文长度。长期高频跑回归的场景,可以考虑用 Coding Plan 来承接编码与 Agent 类调用,成本更可控:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=
6. 把这条链路接进你的工作流
配置骨架和验证动作到这里就闭环了:MCP 把 Playwright 的能力暴露成工具,TaoToken 统一 Key 和 API 通道让模型调用只配一份,智能体负责探索和规划,固化的 Playwright 脚本负责稳定回归。实际落地时,我建议先把「登录、下单、搜索」这三类高频流程各跑一遍智能体探索,把生成的脚本收进tests/目录,再挂到 CI 上定时跑。
需要继续往下走的话,模型对话入口可以用来调试智能体的决策提示词:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ;API Keys 管理在控制台里:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。如果你用的是 Claude Code 这类编码 Agent,接入方式参考:https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。先把一条用例跑绿,再谈规模化,这条路我踩过,顺序反了会很痛苦。