我的QA工程师是一个LLM
Claude可以点击按钮。
这听起来很简单,但它改变了我构建UI的方式。使用Playwright MCP,Claude不仅仅是编写代码——它打开浏览器,导航到localhost,并验证事物实际运行。它捕获我在代码审查中会错过的bug。
设置
Playwright MCP为Claude提供浏览器自动化。我用无头Chromium运行它:
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@anthropic-ai/mcp-server-playwright", "--headless"]
}
}
}
现在Claude可以导航、点击、输入和截图。它看到用户看到的东西。
flowchart LR
Claude([Claude Code]) -->|browser_snapshot| PW[Playwright MCP]
PW --> Browser[Headless Chrome]
Browser --> App[localhost:1313]
Browser -.->|screenshot| Issue[(GitHub Issue)]
Issue -.->|visual history| PR[Pull Request]
flowchart TB
Claude([Claude Code]) -->|browser_snapshot| PW[Playwright MCP]
PW --> Browser[Headless Chrome]
Browser --> App[localhost:1313]
Browser -.->|screenshot| Issue[(GitHub Issue)]
Issue -.->|visual history| PR[Pull Request]
流程: Claude Code → Playwright MCP → 浏览器 → 截图 → GitHub Issues → PR
视口矩阵
每个UI更改都在三个断点处测试:
| 视口 | 尺寸 | 原因 |
|---|---|---|
| Desktop | 1440×900 | 标准笔记本电脑 |
| Tablet | 1024×768 | iPad竖屏 |
| Mobile | 390×844 | iPhone 14 |
Claude调整浏览器大小,截图,上传到GitHub Issue。每次状态更改三张截图。如果移动导航损坏,我会立即看到——而不是在部署后。
主题测试
浅色和深色模式的相同模式:
// Claude切换主题
await page.click('[data-testid="theme-toggle"]');
// 截取两种状态
CSS变量一致性很重要。在浅色模式下看起来不错的组件在深色模式下可能有不可见的文本。Claude通过实际查看两者来捕获这一点。
交互测试
这是有趣的地方。Claude不仅仅是截图——它使用UI:
- 点击每个导航链接,验证目的地
- 打开移动抽屉,检查它是否动画
- 填写表单,提交它们
- 悬停在交互元素上
- 通过点击背景关闭模态框
当它发现一个bug——比如,在外面点击时抽屉不关闭——它报告它,修复代码,并重新测试。反馈循环很紧密。
作为测试报告的GitHub Issue
每张截图都上传到GitHub Issue。Issue正文在每个里程碑重建:
## 当前状态
### Desktop (1440×900)

### Tablet (1024×768)

### Mobile (390×844)

## 测试清单
- [x] 导航链接工作
- [x] 移动抽屉打开/关闭
- [x] 主题切换保持
- [ ] 表单验证显示错误
Issue成为一个实时测试报告。任何审查PR的人都可以确切地看到测试了什么。
完整循环
典型功能经历这个循环:
- 创建Issue: “添加侧边栏导航”
- Claude实现: 编写组件
- 视觉验证: 所有视口的截图
- 交互测试: 点击UI
- 发现bug: 背景点击时抽屉不关闭
- 应用修复: 更新点击处理程序
- 重新测试: 新截图,全部通过
- 创建PR: 链接到具有完整视觉历史的Issue
没有手动QA步骤。没有在没有真正查看的情况下"看起来不错"。Claude验证自己的工作。
这捕获了什么
我看到Claude发现的真实bug:
- 移动导航隐藏在内容后面(z-index问题)
- 深色模式下按钮文本不可见(错误的CSS变量)
- 按Enter键时表单提交两次
- 下拉菜单被overflow:hidden父级裁剪
- 悬停状态在触摸设备上卡住
这些是在代码审查中漏掉的bug,因为它们只出现在浏览器中。Claude看到它们是因为它实际运行代码。
现在每个PR都附带它工作的证明。