Claude + Playwright MCP 实战:让 UI 自动化测试脚本编写效率翻倍
自动化测试脚本写起来不累累的是手工重复那些“找按钮、等加载、对数据、改选择器”。尤其项目进入稳定迭代期之后真正的成本不是功能测试本身而是每次页面一改测试脚本就跟着碎一地。我身边很多团队早就把主流程测试切到了 Playwright 这类浏览器自动化框架但脚本本身还是靠人肉维护一个用例从写到跑通顺利的话一两个小时遇到动态元素和登录态半天就交代了。最近我一直在用 Claude 配合 Playwright MCP 来加速这个环节。所谓 MCP简单理解就是把浏览器本身变成一个可供模型直接调用的工具箱Claude 不再只是“凭空生成一段代码”而是能实时打开被测页面、观察真实 DOM、点按钮、填表单最后把整个操作过程沉淀成可以直接放进项目里的自动化测试脚本。这篇就把我在实际项目里怎么配置、怎么描述需求、怎么让生成的脚本少返工的经验完整写出来踩过的坑也一并交代。1. 为什么我最后把手写脚本这事交给了 MCP1.1 手工维护脚本的真正痛点UI 自动化测试脚本最耗时的从来不是写 Playwright 语法而是两件事一是把需求翻译成一连串可操作的浏览器动作二是处理页面特征不明显时那些不稳定因素。举个很常见的例子。产品经理给的需求一句话“登录后进入订单列表能看到上个月的订单编号。”落到脚本里你得先确认登录框是 label 关联还是 placeholder 关联登录按钮是 button 还是 div 伪装的进入列表后表格是静态渲染还是接口返回来再灌进 DOM。这个过程听起来简单实际做起来每个人一天能产出四五个稳定用例已经算快的了而且写出来的代码带着大量个人习惯后续别人接手也费劲。更要命的是维护成本。前端同学只要把某个按钮的 class 重命名或者把表格列头从中文改成英文 key脚本第二天就红了。你拿到失败报告先得花时间判断是功能回归还是脚本定位失效运气不好还要逐条查 DOM。这些时间累积起来比最初写脚本的时间还要多。1.2 没有 MCP 之前和之后的区别没用 MCP 之前我也试过直接把需求丢给通用大模型让它生成脚本。模型确实能写出语法正确的 Playwright 代码但准确率非常看页面结构。它看不到真实页面只能靠我喂给的 HTML 片段或者凭经验猜测生成出来的选择器经常是 playwright 里那种长长的div.container div:nth-child(3) button脆弱得离谱页面稍微调整就完蛋。有了 MCP 之后整个工作流变成了“模型 真实浏览器”的协作。Claude 通过 MCP 协议调用浏览器里面的一组工具先把页面加载出来再读取当前页面可交互元素的快照然后像真人一样思考下一步该点什么、该填什么。因为它能直接看到页面结构生成的选择器就不会靠猜而是基于真实 DOM 去构造准确率和可维护性完全是两个层级。这个差异本质上和“看着代码改 bug”与“凭记忆改 bug”的差别是一样的。模型能力再强看不到现场也只能瞎蒙而 MCP 把现场信息实时喂给了模型。1.3 这套方案适合谁不是所有场景都适合这套组合。我个人的经验是如果项目里已经有成熟的 Playwright 用例集只是想在新增用例时提速那这套方案几乎是降维打击如果团队正准备从零引入 UI 自动化也可以用它先快速铺一批主流程用例再逐步人工优化。反过来如果被测系统还处于前端结构每天都在调的状态不管用不用 MCP脚本维护成本都会很高这套方案只能帮你缩短“写”的时间不能帮你解决“页面不稳定”本身。另外如果你是那种只想让工具完全替你思考的人那我建议先打消这个念头。Claude 生成脚本、定位元素、排查报错但测试策略、断言边界、数据准备这些还得人来定它更像一个手脚麻利的初级测试开发不是测试负责人。2. 开始前需要先搞明白的三件事2.1 环境要求与工具选型在配置之前先把环境理清楚。基础组合是 Claude 客户端加 Playwright MCP 服务端。Playwright MCP 是官方维护的 MCP 服务它会把浏览器能力封装成一组可供模型调用的工具核心能力包括打开指定 URL、读取页面快照、点击元素、输入文本、选择下拉选项、等待元素出现、执行 JavaScript以及把当前页面保存为 PDF 或截图。所有这些操作都会转换为结构化结果返回给 ClaudeClaude 再根据结果决定下一步动作。项目里目前最省事的启动方式是通过 npx 直接运行不需要单独安装仓库前提是本机有 Node.js 环境建议版本不低于 20。如果没有 npx 或者网络拉包不方便也可以把playwright/mcp安装到项目里以本地模块方式启动。两种方式最终效果一致我倾向后者因为锁版本更容易团队协作时不会出现某天某个人的 npx 拉到了不兼容的新版本。浏览器方面Playwright MCP 自带 Chromium 的下载和管理能力首次启动会自动拉取浏览器内核。如果团队已经统一在用某个浏览器也可以配置成使用已有的 Chrome 或 Edge这样能更好地贴近线上真实环境。2.2 把 Playwright MCP 接到 Claude 中我这里以 Claude Desktop 为例整个配置过程是写一个 JSON 文件声明要加载哪些 MCP 服务。不同客户端入口可能不同但核心都是同一段配置。{ mcpServers: { playwright: { command: npx, args: [playwright/mcplatest] } } }把这段配置放到客户端的 MCP 配置文件里重启客户端在工具列表里就能看到 playwright 相关的工具。如果配置不正常通常会在启动后立刻报错常见原因两个npx 不在系统 PATH 里或者首次下载 Playwright 内核时网络中断。前者需要把 Node.js 的 bin 目录加进 PATH后者直接重新执行一次启动命令让它续传即可。服务启动之后不需要写任何代码直接在对话里让 Claude“打开某个网址”它就会自动调用浏览器工具。第一次跑通这个流程你基本就能理解 MCP 带来的体验差异模型不再是纸上谈兵而是真的把页面打开给你看了。2.3 让 Claude 能连接浏览器的验证方式配置完成之后先不要急着生成完整测试脚本先做一轮简单的连通性测试。我会让 Claude 打开一个本地静态页面或者任意一个稳定的对外页面然后要求它描述当前页面结构和主要可交互元素。如果 Claude 能准确说出页面上有哪些按钮、输入框、导航链接说明浏览器工具链已经打通。这时候我习惯让它再执行一个小动作比如点击某个链接等待页面跳转后再次描述页面状态确认连续动作没有断。这一步虽然简单但能避免后面生成脚本时才暴露“模型根本没连上浏览器”的尴尬。很多时候模型一样会煞有介事地生成貌似合理的代码但它并没有真正观察页面全靠训练经验补全这种脚本看着不错跑起来全是坑。所以验证连接非常有必要不要跳过去。3. 从自然语言到可运行脚本的完整工作流3.1 把需求描述成“给测试员下任务”的方式很多人用大模型生成脚本效果不好第一个原因就是描述太模糊。你说“帮我测一下登录功能”模型能给你的只能是一个泛泛而谈的模板因为它不知道你的登录页面长什么样、登录成功后跳去哪、错误提示文案是什么。换个思路你不是在跟模型聊天而是在给一个不太熟悉项目的测试员下任务。任务描述至少要包含目标地址、前置条件、要执行的操作序列、每一步的预期结果。举个例子“打开 https://example.com/login在用户名输入框输入 test_user密码框输入 Test123点击登录按钮等待页面跳转到工作台验证页面标题包含‘工作台’然后点击左侧菜单‘订单管理’等待表格加载完成读取第一行订单编号。”这段描述一旦给到 Claude配合它已经打开的浏览器快照它能非常准确地把操作映射到具体元素上并生成可运行的脚本。如果你连页面上有什么都不确定就让模型先把页面快照展示出来再基于快照逐步表达你的意图。3.2 一个典型测试用例的完整对话拆解我以登录后查订单这个场景为例讲讲完整对话怎么推进。第一步我会先让 Claude 打开登录页并且把页面可交互控件列表给出来。它通常会返回类似“页面上有文本框标签为用户名文本框标签为密码按钮文本为登录”这类结构信息这时候就确认了元素定位依据。第二步我直接让它执行操作“在用户名字段输入 test_user在密码字段输入 Test123然后点击登录按钮。”它会逐项执行遇到 label 关联不上的情况会自动尝试相邻节点执行完还会把当前页面结果反馈回来。第三步等它确认跳转成功后我再追加指令“验证当前页面是否包含标题‘工作台’。如果包含点击左侧菜单里的‘订单管理’。”到这一步为止整个过程已经有点像真人在操作了。最后一步我跟它说“把刚才整个过程整理成一个 Playwright 测试脚本使用 expect 做断言等待使用自动等待定位方式优先 getByRole 和 getByLabel。”这时候它会把实际操作过的选择器和动作序列组合成一段标准测试代码。整个过程不需要我手动写一行脚本但我心里很清楚每一步在做什么。3.3 脚本生成之后的检查清单Claude 生成的脚本不是拿来就能直接跑的至少要做下面几项检查不然很容易出现误报或者漏报。第一断言是否符合业务预期。模型往往只能根据页面表现生成“标题正确”“元素可见”这类基础断言但业务上你可能更关心接口返回码、数据库状态或者某个数值范围这些信息是模型在浏览器里看不到的需要你手动补。第二数据是否需要隔离。自动化测试通常要在测试环境跑账号密码、订单号这些数据如果写死了哪天数据清理就得改脚本建议把数据抽到变量或者配置里。第三选择器是否聚焦。如果生成出来的选择器特别长考虑改成带>