使用 Playwright MCP 实现 UI 自动化测试:从本地调试到 TaoToken 统一 Key 接入
1. 为什么我把 Playwright MCP 接进了日常 UI 自动化测试Playwright MCP 是一套把浏览器自动化能力封装成 MCP 工具、让大模型通过自然语言直接驱动浏览器的方案能做什么简单说就是你不再手写一堆page.click()、page.fill()而是让模型根据你的指令去点按钮、填表单、断言页面状态。适合谁适合已经在写 UI 自动化、但被选择器维护和脚本调试拖慢节奏的测试同学也适合想把冒烟用例交给 AI 辅助生成的团队。我之前的痛点很具体本地用 Playwright 写登录页冒烟脚本选择器一改就得全量回归同时手上还有 Cline、Claude Code 几个工具每个都要单独配一份模型 Key切换一次就要改一次环境变量维护成本高得离谱。后来我把 Playwright MCP 的浏览器能力和模型调用统一收敛到 TaoToken 的 endpoint 上本地调试和团队协作才顺过来。这篇就按“先跑通本地录制与断言再把 MCP 服务端 endpoint 与鉴权改到 TaoToken”的顺序写给出可复制的 MCP 配置片段、环境变量清单以及一条登录页冒烟用例的验证动作与预期输出。你照着做能拿到一个能跑、能改、能复用的最小闭环。2. Playwright MCP 本地跑通录制、断言与最小冒烟用例先把本地环境跑通这一步不碰任何远端服务纯本地验证 Playwright MCP 能不能驱动浏览器。我用的方案是官方playwright/mcp通过 npx 直接拉起省去全局安装的污染。第一步确认 Node 版本。Playwright MCP 依赖较新的 Node建议 18 以上node -v # 期望输出 v18.x 或更高第二步安装 Playwright 浏览器驱动。如果你之前装过 Playwright 库这步可以跳过没装过就执行npx playwright install chromium国内网络下载慢的话可以设置镜像环境变量再装export PLAYWRIGHT_DOWNLOAD_HOSThttps://npmmirror.com/mirrors/playwright npx playwright install chromium第三步用录制功能生成一份可靠的登录页脚本。这是我最推荐的新手入口codegen会把你手动操作的过程转成带语义定位器的代码npx playwright codegen https://example.com/login浏览器打开后你手动输入用户名、密码、点登录右侧 Inspector 会实时生成代码。重点看它生成的选择器——优先用getByRole、getByLabel这类语义定位器而不是#username这种脆弱 ID。录完把代码存成login.spec.ts。第四步写一条最小冒烟断言。录制出来的代码通常只有操作没有断言我补上登录成功和登出两个关键校验import { test, expect } from playwright/test; test(登录页冒烟, async ({ page }) { await page.goto(https://example.com/login); await page.getByLabel(用户名).fill(testuser); await page.getByLabel(密码).fill(testpass); await page.getByRole(button, { name: 登录 }).click(); // 断言登录后 dashboard 可见 await expect(page.locator(.dashboard)).toBeVisible(); await expect(page).toHaveTitle(/Dashboard/); // 登出并确认回到登录表单 await page.getByRole(button, { name: 退出 }).click(); await expect(page.locator(.login-form)).toBeVisible(); });第五步跑起来看结果npx playwright test login.spec.ts --headed预期输出是浏览器自动打开、完成登录登出、终端显示1 passed。如果这一步就失败先别急着接远端把本地选择器和等待逻辑调稳否则后面排查会分不清是脚本问题还是配置问题。本地跑通后你会得到一个纯本地的 MCP 配置形如{ mcpServers: { playwright: { command: npx, args: [playwright/mcplatest], timeout: 300 } } }这份配置只驱动浏览器不涉及模型调用。接下来才是重点把模型侧的统一 Key 接进来。3. 把 MCP 服务端 endpoint 与鉴权改到 TaoToken 统一 Key本地脚本能跑但真正让 AI 驱动浏览器时模型调用才是 Key 消耗的大头。我之前的做法是每个工具配一份 KeyCline 一份、Claude Code 一份改一次要动好几个文件。统一到 TaoToken 后Base URL、Key、Model ID 三件套只维护一份。先说清楚 TaoToken 在这里的角色它是一个统一的模型调用入口提供兼容常见协议风格的 endpoint你把手上的工具都指向同一个 Base URL用同一把 Key模型 ID 按需切换。官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个不加 UTM。第一步去控制台创建 Key。打开 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 新建一个 API Key复制出来先存到本地环境变量别硬编码进配置文件。第二步配置环境变量清单。我习惯用一个.env文件管理内容如下# TaoToken 统一入口 TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYsk-你的Key TAOTOKEN_MODEL_IDclaude-sonnet-4-5 # Playwright MCP 浏览器参数 BROWSER_TYPEchromium BROWSER_HEADLESSfalse MCP_TIMEOUT300这里TAOTOKEN_MODEL_ID按你实际要用的模型填不同工具对模型 ID 的写法可能略有差异以控制台里列出的为准。第三步改 MCP 配置。以 Cline 的 MCP 配置为例把模型侧指向 TaoToken浏览器侧仍用 Playwright MCP{ mcpServers: { playwright: { command: npx, args: [playwright/mcplatest], env: { BROWSER_TYPE: chromium, BROWSER_HEADLESS: false }, timeout: 300 } }, modelProvider: { baseUrl: https://taotoken.net/api, apiKey: ${TAOTOKEN_API_KEY}, modelId: ${TAOTOKEN_MODEL_ID} } }如果你用的是 Claude Code配置走的是settings.json路径通常在~/.claude/settings.json片段如下{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的Key, ANTHROPIC_MODEL: claude-sonnet-4-5 } }注意这里三件套必须齐全Base URL 指向https://taotoken.net/apiKey 用控制台创建的Model ID 填你实际要调用的模型。少任何一个请求都会在鉴权或路由阶段失败。第四步如果你用 Codex 系工具配置落在auth.json结构类似{ base_url: https://taotoken.net/api, api_key: sk-你的Key, model: claude-sonnet-4-5 }改完配置后重启对应工具让它重新加载环境变量。这一步别偷懒很多“配置没生效”的问题就是没重启。4. 验证请求登录页冒烟用例的完整动作与预期输出配置改完得验证模型侧和浏览器侧是不是真的串起来了。我用一条登录页冒烟用例做端到端验证动作和预期输出都写清楚你照着比对。验证动作分三步。第一步在支持 MCP 的客户端里发起一条自然语言指令让它驱动 Playwright MCP 完成登录流程打开 https://example.com/login在用户名输入 testuser密码输入 testpass 点击登录按钮等待 .dashboard 元素可见确认页面标题包含 Dashboard 然后点击退出按钮确认 .login-form 重新出现。第二步观察 MCP 工具调用链。正常情况下你会看到客户端依次调用navigate、fill、click、wait_for_selector这类工具每一步都有返回。如果模型侧没接对这一步会直接报鉴权错误根本走不到浏览器。第三步用命令行再跑一次本地脚本做交叉验证npx playwright test login.spec.ts --headed预期输出Running 1 test using 1 worker 1 passed (3.2s)同时浏览器窗口里能看到完整的登录、登出动作。如果模型侧指令能跑通、本地脚本也能跑通说明两条链路都正常。再补一个模型侧的连通性验证直接打一次对话接口确认 Key 和 Base URL 没问题curl -X POST https://taotoken.net/api/v1/messages \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: claude-sonnet-4-5, max_tokens: 64, messages: [{role: user, content: 回复 ok}] }预期返回里包含模型输出内容HTTP 状态 200。这一步过了说明统一 Key 接入是通的。你也可以在模型对话页面 https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel-chatutm_campaignrewrite 里手动发一条消息做可视化确认。验证通过后把这条冒烟用例固化进 CI每次提交自动跑一遍选择器改动导致的回归能第一时间发现。5. 本篇常见报错排查401、local proxy failed、reading choices、OAuth接入过程中我踩过的坑基本集中在几个固定报错上逐个对照排查能省很多时间。401 Unauthorized最常见。原因通常是 Key 没读到或写错。检查三处环境变量TAOTOKEN_API_KEY是否真的导出到当前 shell配置文件里是否用了${TAOTOKEN_API_KEY}这种引用但工具没加载.envKey 本身是否在控制台被禁用。排查命令echo $TAOTOKEN_API_KEY # 应输出 sk- 开头的完整 Key如果输出为空说明环境变量没生效重启终端或手动source .env。local proxy failed / connection refused这个报错通常出现在 MCP 服务端启动阶段不是模型侧问题。检查npx playwright/mcplatest能否单独跑起来npx playwright/mcplatest --verbose如果报端口占用或命令找不到先确认 Node 版本和 npx 缓存。清缓存重试npx clear-npx-cache npx playwright/mcplatest --verbosereading choices of undefined这个报错说明模型返回结构不符合预期多半是 Base URL 或 Model ID 填错请求打到了不兼容的端点。核对TAOTOKEN_BASE_URL是否为https://taotoken.net/api以及 Model ID 是否在控制台支持列表里。改完重启工具。OAuth 相关报错如果你用的是 Claude Code 且之前登录过官方账号它可能优先走 OAuth 而不是 API Key。检查settings.json里是否同时存在 OAuth 配置和ANTHROPIC_API_KEY两者冲突时以显式 API Key 为准。必要时清掉旧的凭据缓存再重启。元素定位超时这个不是接入问题是脚本问题。用codegen重新录制或把选择器换成getByRole语义定位。加显式等待await page.waitForSelector(.dashboard, { state: visible, timeout: 10000 });排查顺序建议固定为先确认 Key 和 Base URL再确认 MCP 服务端能独立启动最后才看脚本选择器。顺序反了容易在错误的地方浪费时间。6. 长期编码与 Agent 场景把统一 Key 用成基础设施单次冒烟跑通只是起点。如果你打算把 Playwright MCP 长期用在日常回归、Agent 自动巡检这类场景Key 的管理方式会直接影响维护成本。我的做法是把 TaoToken 的 Base URL 和 Key 收敛成团队级环境变量所有工具——Cline、Claude Code、Codex、以及各种 MCP 客户端——都从同一份配置读取。这样换模型、换额度、轮换 Key 都只改一处。长期跑编码和 Agent 任务的话可以看下 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它更适合高频调用的场景。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite API Key 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。Claude Code 相关配置参考 https://taotoken.net/claudecode-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecode-anthropicutm_campaignrewrite 。一个实用技巧把 Playwright MCP 的浏览器参数和模型参数分开管理浏览器侧用本地配置模型侧统一走环境变量。这样本地调试和 CI 环境可以共用同一套脚本只在环境变量层面区分。我实测下来这套结构跑三个月没再因为 Key 切换出过问题。