很多时候, 当我们使用 AI 开发应用或者修复功能时, 光靠手动的方式进行测试,很难发现所有潜在问题, 自己写功能测试也可能会有遗漏的地方。要想让产品更稳定、更可靠,全面的自动化测试就很关键。
在这篇文章中,主要为大家介绍 Playwright MCP (Model Context Protocol) 这个自动化测试工具, 它不仅能帮你自动跑各种测试, 还能模拟真实用户的操作流程, 快速定位 bug 和异常, 最重要的是不需要自己手动编写脚本。
接下来, 我将通过一个实际的案例来展示如何针对一个 web 应用生成并运行测试,重点说明 MCP 如何发现边界情况、提升整体的测试覆盖率,发现可能遗漏的 bug。
Playwright MCP 实战体验
在这里我使用的是cursor IDE 环境,首先,需要在cursor的seting设置面板中进行playwright mcp的配置,如下所示:
{ "servers": { "playwright": { "command": "npx", "args": [ "@playwright/mcp@latest" ] } }}
接下来,我准备了一段用于自动化测试的提示词,在agent模式下先输入这段提示词:
- 你是一个 playwright 测试生成器。- 你会获得一个场景,需要为其生成 playwright 测试。- 不要仅根据场景生成测试代码。- 要使用 Playwright MCP 提供的工具一步步执行操作。- 当被要求探索网站时: 1. 访问指定的 URL 2. 探索网站的一个关键功能,完成后关闭浏览器。 3. 根据消息历史,基于 Playwright 最佳实践(包括基于角色的定位器、自动重试断言,除非必要不加额外超时,因为 Playwright 已内置重试和自动等待)实现 Playwright TypeScript 测试,使用 @playwright/test。- 将生成的测试文件保存在 tests 目录下- 执行测试文件并迭代直到测试通过- 包含适当的断言以验证预期行为- 结构化测试,使用描述性标题和注释
然后输入需要测试的URL地址,这时Agent Mode 会利用 Playwright MCP 像真实用户一样浏览网站并探索应用。
目标: 让 agent 自由浏览、发现功能,并根据交互自动生成测试。
agent 开始探索后,首先尝试了搜索功能。它在搜索栏输入“Star Wars”——立刻发现了一个 bug。
搜索结果显示了“Star Wars”,但返回的电影标题却是“Kill”。这显然不对。
这是我手动测试时没发现的边界情况。之前我手动搜索过其他的电影名称一切正常。但现在,多亏 agent 的自主行为,我发现了一个回归问题。
结果: agent 发现了一个我完全没注意到的搜索问题。
接着,agent 切换了应用的主题开关——在深色和浅色模式间切换。它验证了切换功能,点击了导航链接,并继续探索。
交互结束后,agent 总结了它的发现:
- 电影列表展示 - 显示热门电影,带评分搜索功能主题切换 (日/夜模式)电影详情页面分页功能登录功能菜单导航
从中选择了“搜索功能”作为要生成测试的重点。
🧾 测试生成与执行: 最后,agent 根据交互生成了完整的 Playwright 测试文件。它甚至在运行前自动修复了一个 lint 错误。 以下是它生成的测试代码:
import { test, expect } from '@playwright/test';test.describe('Movie search', () => { test('Search for a movie by title', async ({ page }) => { // 访问电影应用 await page.goto('https://debs-obrien.github.io/playwright-movies-app'); // 点击搜索按钮激活搜索输入框 await page.getByRole('search').click(); // 在搜索框输入 'Star Wars' 并回车 const searchTerm = 'Star Wars'; await page.getByRole('textbox', { name: 'Search Input' }).fill(searchTerm); await page.getByRole('textbox', { name: 'Search Input' }).press('Enter'); // 验证已进入正确标题的搜索结果页 await expect(page).toHaveTitle(`${searchTerm} - Search Results`); // 验证搜索结果标题包含搜索词 await expect(page.getByRole('heading', { level: 1 })).toHaveText(searchTerm); await expect(page.getByRole('heading', { name: 'search results', level: 2 })).toBeVisible(); // 验证搜索结果列表可见 await expect(page.getByRole('list', { name: 'movies' })).toBeVisible(); // 点击搜索结果中的一部电影 const firstMovie = page.getByRole('list', { name: 'movies' }).getByRole('link').first(); const movieTitleElement = firstMovie.getByRole('heading', { level: 2 }); const movieTitle = await movieTitleElement.textContent() || ''; await firstMovie.click(); // 验证电影详情页加载且标题正确 await expect(page.getByRole('heading', { level: 1 })).toHaveText(movieTitle); // 验证电影详情区块存在 await expect(page.getByText('The Synopsis')).toBeVisible(); await expect(page.getByText('The Cast')).toBeVisible(); // 验证推荐电影区块存在 await expect(page.getByRole('heading', { name: 'Recommended Movies' })).toBeVisible(); // 返回搜索结果页 await page.getByRole('button', { name: 'Back' }).click(); // 验证已返回搜索结果页 await expect(page.getByRole('heading', { level: 1 })).toHaveText(searchTerm); });});
生成后,它会打开终端并运行测试。测试通过 ✅。
我们可以在cursor的聊天面板中直观查看每一步:
以上就是一个playwright mcp 执行自动化测试的完整流程:探索 → 生成 → 执行 → 回顾。
最后, 我们可以在浏览器中查看完整的测试报告,如下所示:
💡 为什么自动化测试很重要
使用playwright mcp 自动化测试这种方式的强大之处在于:
- 它发现了我没注意到的真实 bug。节省了我编写测试模板代码的时间。提供了基于实际使用路径的测试覆盖思路。生成了可直接提交或扩展的可运行测试代码。
另外,你也可以不断地迭代、优化提示、增加测试数量,或让 agent 探索不同的功能区域, 就像和一个AI 测试工程师在结对编程。
写在最后
如果你也在基于vibe coding的模式开发应用或是优化已有的功能代码,同时你想要更全面的测试覆盖率,又不想手写所有测试,不妨尝试一下 Playwright MCP 。