
「漫说测试」· GitHub 实战课 · 第 1 课
面向测试工程师的热门开源项目手把手课:把「浏览器」变成 AI 能调用的工具,让 AI 真的会点、会填、会验。 全程真跑通,附完整可运行 demo + 各类客户端的 MCP 配置 + 指令执行层级 + 一份能直接抄的测试提示词。

【贴图1】
一、为什么第 1 课选它
如果要让测试工程师只挑一个 当下最该上手、又和 AI 沾边的开源项目,我的答案是它:Playwright MCP。
-
出身正
:微软官方出的 MCP server ,托管在
microsoft/playwright-mcp,是 GitHub 上最受关注的开源项目之一^1; -
正好踩中风口
:MCP(Model Context Protocol)是现在 AI 界最火的"给 AI 接工具"标准,而浏览器,是 AI 最想学会用的那个工具;
-
对测试人是"降维打击"
:它让 AI 真的去操作一个浏览器 ------点按钮、填表单、断言结果。这不就是端到端测试在做的事吗?
一句话:它把"AI 测试"从 PPT 里拽到了真实浏览器里。

【贴图2】
二、它到底是什么?
分两层理解,特别顺:
第一层,MCP :一个开放协议------让 AI 像"插 USB"一样接上各种工具(数据库、文件、CLI......还有浏览器)^2。
第二层,Playwright MCP :微软按这个协议写的浏览器服务器 ------AI 通过它,能拿到当前页面的状态 ,并调用一整套交互工具:打开页面、点击、输入、滚动、断言、截图......^3。
配置也简单到离谱(以 Claude Code 为例)^2:
bash
claude mcp add playwright npx @playwright/mcp@latest
就这一行,AI 就"长"出了一双手,能替你操作浏览器了。

【贴图3】
三、关键点:它靠"无障碍树",不靠截图
这是 Playwright MCP 最值得说的设计,也是它比一堆"看图点击"的 AI 浏览器方案更靠谱的原因。
很多 AI 操作浏览器,靠的是截屏 + 视觉识别 :"这一坨像素像是按钮,点它。"------慢、贵、还不稳。
Playwright MCP 走的是另一条路:它给 AI 的是页面的「无障碍树(accessibility tree)」 ------也就是结构化地告诉 AI"这页面上有哪些按钮、输入框、链接,它们叫什么、状态如何"^4。
好处很直接:
-
不用截图
→ 更快、更省 token;
-
语义化
→ AI 看到的是"Sign in button ",而不是一堆像素,点击更精准;
-
更稳
→ 页面样式变了,语义还在,不会一改 CSS 就全崩。
一句话:AI 不是"看图点",而是"读结构点"------这正是测试工程师熟悉的"用语义定位",只是这次操作者是 AI。

【贴图4】
四、三步跑通
第 0 步:准备环境与项目(进项目根)
bash
mkdir
pwmcp-demo &&
cd
pwmcp-demo
# 只需 Node/npm(用于 npx 拉起 MCP server)+ 任意 MCP 客户端(Claude Code / Cursor / VS Code...)
Playwright MCP 本身用
npx拉起,你不需要为它单独建 Node 工程;被测应用用一个 Python 静态站即可。
第 1 步:注册 MCP server(在项目根;命令随客户端不同)
bash
# Claude Code(推荐,一条命令)
claude mcp add playwright npx @playwright/mcp@latest
# Cursor:Settings → MCP → Add new MCP Server → type=command, command=npx @playwright/mcp@latest
# PyCharm(2025.1+):Settings → Tools → AI Assistant → Model Context Protocol (MCP) → Add → 粘贴 JSON
# 其它客户端:用标准配置(见 demo/ 里的 mcp.json)
标准配置长这样(Claude Desktop / VS Code / 通用客户端):
bash
{
"mcpServers"
:
{
"playwright"
:
{
"command"
:
"npx"
,
"args"
:
[
"@playwright/mcp@latest"
]
}
}
}
第 2 步:起一个被测应用 app/server.py(在项目根)
沿用最小站点:登录表单 + 加购按钮。
bash
# app/server.py
import
os
from
http.server
import
BaseHTTPRequestHandler, HTTPServer
PORT =
int
(os.environ.get(
"PORT"
,
"4173"
))
PAGE =
"""<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Acme Storefront</title></head><body> <h1>Acme Storefront</h1> <form id="signin"> <label for="email">Email</label> <input id="email" type="email"> <label for="password">Password</label> <input id="password" type="password"> <button type="submit">Sign in</button> </form> <div id="status" role="status"></div> <section class="row" hidden id="shop"> <span>Items in cart:</span> <span id="cart-count" data-testid="cart-count">0</span> <button type="button" id="add">Add to cart</button> </section> <script> const status = document.getElementById('status'); const shop = document.getElementById('shop'); const countEl = document.getElementById('cart-count'); let count = 0; document.getElementById('signin').addEventListener('submit', (e) => { e.preventDefault(); const email = document.getElementById('email').value.trim(); if (!email) { status.textContent = 'Email required'; return; } status.textContent = 'Signed in as ' + email; shop.hidden = false; }); document.getElementById('add').addEventListener('click', () => { count += 1; countEl.textContent = String(count); }); </script></body></html>"""
class
Handler
(
BaseHTTPRequestHandler
):
def
do_GET
(
self
):
if
self
.path ==
"/"
:
b = PAGE.encode(
"utf-8"
)
self
.send_response(
200
)
self
.send_header(
"content-type"
,
"text/html; charset=utf-8"
)
self
.end_headers();
self
.wfile.write(b)
else
:
self
.send_response(
404
);
self
.end_headers();
self
.wfile.write(
b"not found"
)
def
log_message
(
self, *a
):
pass
if
__name__ ==
"__main__"
:
print
(
f"app on {PORT}"
)
HTTPServer((
"127.0.0.1"
, PORT), Handler).serve_forever()
bash
python app/server.py
# 在项目根启动,访问 http://127.0.0.1:4173
第 3 步:让 AI 去"跑一遍"(在 MCP 客户端里说人话)
对配好 MCP 的 AI 说:
打开 http://127.0.0.1:4173 ,用邮箱
qa@example.test/ 密码hunter2-hunter2登录,然后点两次「Add to cart」,确认购物车数量变成 2,并告诉我结果。
它就会:打开页面 → 读无障碍树 → 找到 Email/Password/Sign in → 填 → 点 → 再点两次 → 读到 cart-count 是 2 → 回报^5。

【贴图5】

【贴图6】
五、先看清结构:文件放哪 + 指令在哪一层
bash
pwmcp-demo/ ← 「项目根」:命令都在这一层执行
├── app/
│ └── server.py ← 被测应用
├── mcp.json ← 各客户端的 MCP 配置模板
├── prompts/
│ └── smoke.md ← 给 AI 的测试提示词(冒烟)
└── README.md
指令在哪个层级执行:
|
指令
|
在哪个目录执行
|
说明
|
| --- | --- | --- |
| python app/server.py | 项目根 |
启动被测应用
|
| claude mcp add playwright npx @playwright/mcp@latest | 项目根 |
注册 MCP server(Claude Code)
|
|
编辑 mcp.json
|
放到客户端的配置位置
|
Cursor/VS Code/Desktop 用
|
| npx @playwright/mcp@latest --headless | 项目根 |
无头模式(CI 用,见进阶)
|
一句话:被测应用与
claude mcp add都在「项目根 pwmcp-demo/」执行;MCP 配置文件的"落脚点"取决于用哪个客户端。
【配图·fig-pwmcp-a:结构 + 指令层级】
六、用它来做测试:三个真实场景
Playwright MCP 不是"玩具",它能直接嵌进你的测试动作里^6:
① 自测 / 冒烟 :改动上线前,让 AI 打开关键页面走一遍主流程,几十秒给一份"红/绿"结论。
② 探索式测试 :把页面交给 AI:"帮我找找这个表单在异常输入 下有没有问题(空值、超长、特殊字符)。" 它 7×24 不喊累,帮你铺量。
③ 生成可用代码 :让它"边操作边产出"------很多方案能直接导出成 Playwright 用例代码 ,你审一遍就能进仓库(呼应我们第 8 期讲的:AI 补量,人定标准)。
注意分寸:AI 负责"点得又快又多",你负责"判得又准又稳"。

【贴图7】
七、进阶:几个必须知道的点
-
无头 / CI
:加
--headless让 AI 在无界面环境跑(CI 友好); -
登录态复用
:用
storageState(登录一次、后续复用),别每次重登; -
默认有头
:Playwright MCP 默认弹出真实浏览器 ,你能看着 AI 操作------调试期很爽;
-
安全红线
:AI 能真的操作浏览器 → 别把生产账号、真实凭据交给它 ;用测试账号 + 测试环境;
-
别神化
:它是"更强的执行手",不是"会思考的测试专家"------用例该覆盖什么,仍得你来定。

【贴图8】

【贴图9】
八、给测试工程师的 3 条落点
-
先"看它跑"
:配好 MCP,说人话让它操作一次浏览器,建立直觉;
-
再"用它跑"
:把冒烟主流程交给它,省下的时间用来设计更狠的用例;
-
守住红线
:测试环境 + 测试账号 + 人审产出,AI 的操作永远在人定的边界内。
一句话:Playwright MCP 不只是又一个工具------它是"AI 走进真实浏览器"的那扇门,而门里的规矩,得由测试人来定。

【贴图10】
🎁 加料包:完整可运行 demo + 各客户端配置,直接拿走
上面这套 demo 我已经打包好 ------pwmcp-demo/ 里是能直接跑的 :受测应用 app/server.py、各客户端的 MCP 配置模板 mcp.json 、给 AI 的冒烟测试提示词 prompts/smoke.md ,外加一份《Playwright MCP 快速上手手册 》:是什么/无障碍树原理/三种客户端配置/指令层级/进阶(无头·登录态·安全)/测试提示词模板。
附:一键复现清单
bash
pwmcp-demo/
├── app/server.py # 被测应用
├── mcp.json # 各客户端 MCP 配置模板
├── prompts/smoke.md # 给 AI 的冒烟测试提示词
└── README.md
bash
cd
pwmcp-demo
# ← 进项目根
python app/server.py
# 起被测应用(另开一个终端)
claude mcp add playwright npx @playwright/mcp@latest
# 注册 MCP
# 然后在 AI 客户端里说:打开 http://127.0.0.1:4173 并完成登录+加购冒烟
本文配置与命令以官方文档为准,demo 已在本地跑通。仓库:github.com/microsoft/playwright-mcp