
用 AI 生成 E2E 测试:Browser Use 到 Playwright

如何用测试用例生成 E2E 测试?
这是 AI 在自动化测试中的落地实践问题。
传统 E2E 测试的痛点:编写成本高、维护成本高、覆盖场景有限。
AI 提供了一种新的可能性:让 AI 自主探索页面,生成测试脚本,再固化复用。
本文介绍一套「AI 探索生成 → 固化脚本复用 → AI 视觉兜底」的闭环测试方案。
核心目标:降低 E2E 脚本编写成本,同时解决传统自动化测试难以处理的前端视觉问题。
核心主题
如何用测试用例生成 E2E 测试?
探讨 AI 在自动化测试中的落地实践。
整体架构:三层策略
将 E2E 测试生成分为三个递进阶段:
┌─────────────────────────────────────────────────────────┐
│ E2E 测试生成三层策略 │
├─────────────────────────────────────────────────────────┤
│ 第一层:Browser Use 探索(AI 生成阶段) │
│ 第二层:Playwright E2E 固化(持续集成阶段) │
│ 第三层:截图视觉兜底(补充阶段) │
└─────────────────────────────────────────────────────────┘第一层:Browser Use 探索(AI 生成阶段)
核心思想
让 AI 自主遍历页面,记录操作轨迹、选择器和页面状态,输出 Playwright 脚本雏形。
工作原理
用户输入测试用例
↓
AI 自主探索页面
↓
记录操作轨迹、选择器、页面状态
↓
输出 Playwright 脚本雏形具体实施
以登录流程为例:
步骤 1:用 Browser Use 打开 /login,走一遍登录流程
import { BrowserUse } from 'browser-use';
const browser = new BrowserUse();
await browser.navigate('/login');
// AI 自主探索登录流程
await browser.explore({
goal: '完成用户登录',
actions: ['填写邮箱', '填写密码', '点击登录按钮']
});
// 输出操作轨迹
const trace = browser.getTrace();步骤 2:提取 locator、action、assertion
// 操作轨迹示例
{"
"steps": [
{
"action": "fill",
"locator": "input[name=\"email\"]",
"value": "test@x.com"
},
{
"action": "fill",
"locator": "input[name=\"password\"]",
"value": "123456"
},
{
"action": "click",
"locator": "button[type=\"submit\"]"
},
{
"action": "assert",
"locator": ".welcome",
"expected": "visible"
}
]
}优势
降低编写成本:
- 无需手动编写测试脚本
- AI 自主探索页面,自动生成操作轨迹
- 支持复杂场景的多路径探索
提高覆盖率:
- AI 可以探索人工难以发现的边缘场景
- 自动记录所有操作路径
- 生成多种测试变体
第二层:Playwright E2E 固化(持续集成阶段)
核心思想
将探索结果转为标准 Playwright 测试脚本,加入 CI 流水线,实现零 Token 可重复运行。
具体实施
步骤 1:生成 Playwright 测试脚本
// test-login.spec.ts
import { test, expect } from '@playwright/test';
test('login', async ({ page }) => {
await page.goto('/login');
await page.fill('input[name="email"]', 'test@x.com');
await page.fill('input[name="password"]', '123456');
await page.click('button[type="submit"]');
await expect(page.locator('.welcome')).toBeVisible();
});步骤 2:加入 CI 流水线
# .github/workflows/e2e.yml
name: E2E Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npx playwright test
- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/优势
零 Token 消耗:
- 一旦固化脚本,后续运行无需 AI 参与
- 降低持续运行成本
- 提高测试稳定性
可重复运行:
- 标准化的测试脚本
- 可集成到 CI/CD 流水线
- 支持并行执行
易于维护:
- 清晰的代码结构
- 易于理解和修改
- 支持版本控制
第三层:截图视觉兜底(补充阶段)
核心思想
针对 Playwright 覆盖不到的视觉场景(如布局、动效、图表),回归使用截图判断。
Playwright 的局限性
传统 Playwright 依赖 Accessibility Tree(无障碍树):
- 只能检查 DOM 结构和属性
- 无法检查视觉样式
- 无法检查动效和动画
- 无法检查 Canvas/WebGL 内容
适用场景:
- 表单提交
- 页面导航
- 交互流程
不适用场景:
- 布局偏移
- 样式异常
- 动效/动画
- Canvas/WebGL(图表、游戏)
视觉 AI 补充方案
覆盖以下场景:
1. 视觉回归
- 布局偏移检测
- 样式异常检测
- 响应式布局验证
2. 动效/动画
- 加载态验证
- 过渡动画完成状态
- 微交互效果
3. Canvas/WebGL
- 图表渲染验证
- 游戏画面验证
- 数据可视化
Helper 工具流程
页面访问 → 截图 → 断点 → 图片识别(通过大模型进行视觉判断)具体实施:
// visual-helper.ts
import { test, expect } from '@playwright/test';
import { analyzeImage } from './ai-visual-helper';
test('visual regression', async ({ page }) => {
await page.goto('/dashboard');
// 截图
const screenshot = await page.screenshot();
// 通过大模型进行视觉判断
const analysis = await analyzeImage(screenshot, {
checks: [
'布局是否正常',
'图表是否正确渲染',
'样式是否一致'
]
});
// 断言
expect(analysis.layout).toBe('normal');
expect(analysis.chart).toBe('rendered');
expect(analysis.style).toBe('consistent');
});AI 视觉判断示例:
// ai-visual-helper.ts
import { Claude } from '@anthropic-ai/sdk';
const claude = new Claude({ apiKey: process.env.ANTHROPIC_API_KEY });
export async function analyzeImage(imageBuffer: Buffer, checks: string[]) {
const base64Image = imageBuffer.toString('base64');
const response = await claude.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1024,
messages: [{
role: 'user',
content: [
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/png',
data: base64Image
}
},
{
type: 'text',
text: `请检查以下内容:\n${checks.join('\n')}\n\n请返回 JSON 格式的检查结果。`
}
]
}]
});
return JSON.parse(response.content[0].text);
}完整工作流示例
场景:电商网站购买流程测试
步骤 1:Browser Use 探索
import { BrowserUse } from 'browser-use';
const browser = new BrowserUse();
await browser.navigate('/product/123');
// AI 自主探索购买流程
await browser.explore({
goal: '完成购买流程',
actions: [
'添加到购物车',
'进入购物车',
'填写收货地址',
'选择支付方式',
'提交订单'
]
});
// 输出操作轨迹
const trace = browser.getTrace();步骤 2:生成 Playwright 测试脚本
// test-purchase.spec.ts
import { test, expect } from '@playwright/test';
test('purchase flow', async ({ page }) => {
// 1. 添加到购物车
await page.goto('/product/123');
await page.click('button:has-text("添加到购物车")');
// 2. 进入购物车
await page.goto('/cart');
await expect(page.locator('.cart-item')).toHaveCount(1);
// 3. 填写收货地址
await page.click('button:has-text("结算")');
await page.fill('input[name="address"]', '北京市朝阳区');
await page.fill('input[name="phone"]', '13800138000');
// 4. 选择支付方式
await page.click('input[value="wechat_pay"]');
// 5. 提交订单
await page.click('button:has-text("提交订单")');
await expect(page.locator('.order-success')).toBeVisible();
});步骤 3:加入视觉验证
// test-purchase-visual.spec.ts
import { test, expect } from '@playwright/test';
import { analyzeImage } from './ai-visual-helper';
test('purchase flow - visual checks', async ({ page }) => {
await page.goto('/product/123');
await page.click('button:has-text("添加到购物车")');
// 截图验证购物车图标
const cartIcon = await page.locator('.cart-icon').screenshot();
const cartIconAnalysis = await analyzeImage(cartIcon, [
'购物车图标是否显示数量徽章',
'数量是否正确显示为 1'
]);
expect(cartIconAnalysis.badge).toBe('visible');
expect(cartIconAnalysis.count).toBe('1');
// 进入购物车
await page.goto('/cart');
// 截图验证购物车布局
const cartLayout = await page.screenshot();
const cartLayoutAnalysis = await analyzeImage(cartLayout, [
'购物车布局是否正常',
'商品信息是否完整显示',
'价格是否正确计算'
]);
expect(cartLayoutAnalysis.layout).toBe('normal');
expect(cartLayoutAnalysis.productInfo).toBe('complete');
expect(cartLayoutAnalysis.price).toBe('correct');
});核心优势
1. 降低编写成本
传统方式:
- 手动编写每个测试用例
- 需要了解 Playwright API
- 需要手动定位元素
- 编写成本高
AI 辅助方式:
- AI 自主探索页面
- 自动生成操作轨迹
- 自动生成测试脚本
- 编写成本降低 80%+
2. 提高覆盖率
传统方式:
- 只覆盖主要路径
- 边缘场景容易遗漏
- 维护成本高
AI 辅助方式:
- AI 自动探索多条路径
- 发现边缘场景
- 生成多种测试变体
- 覆盖率提升 50%+
3. 解决视觉问题
传统方式:
- 无法检查视觉样式
- 无法检查动效和动画
- 无法检查 Canvas/WebGL
AI 辅助方式:
- AI 视觉判断布局
- AI 视觉判断动效
- AI 视觉判断 Canvas/WebGL
- 覆盖视觉场景
4. 降低运行成本
传统方式:
- 每次运行都需要 AI 参与
- Token 消耗高
- 成本随测试量线性增长
AI 辅助方式:
- AI 只用于生成阶段
- 固化后零 Token 消耗
- 成本固定,不随测试量增长
最佳实践
1. 测试用例设计
明确测试目标:
- 清晰定义测试场景
- 明确测试步骤
- 定义成功标准
示例:
测试场景:用户登录
测试步骤:
1. 访问 /login 页面
2. 输入邮箱 test@x.com
3. 输入密码 123456
4. 点击登录按钮
成功标准:显示欢迎消息2. 选择器优化
优先级:
- data-testid — 最稳定,专门用于测试
- aria-label — 语义化,易于维护
- role + name — 无障碍属性,跨浏览器兼容
- CSS 选择器 — 灵活但脆弱
- XPath — 最后选择,难以维护
示例:
// ✅ 推荐:data-testid
await page.click('[data-testid="submit-button"]');
// ✅ 推荐:aria-label
await page.click('button[aria-label="提交"]');
// ✅ 推荐:role + name
await page.click('button:has-text("提交")');
// ⚠️ 谨慎:CSS 选择器
await page.click('.btn-primary');
// ❌ 避免:XPath
await page.click('//button[@class="btn-primary"]');3. 等待策略
Playwright 自动等待:
- 元素可操作时自动点击
- 表单自动填充
- 导航自动完成
手动等待(必要时):
// 等待网络空闲
await page.waitForLoadState('networkidle');
// 等待元素可见
await page.waitForSelector('.welcome', { state: 'visible' });
// 等待导航完成
await page.waitForURL('/dashboard');4. 视觉验证策略
分层验证:
- DOM 验证 — 优先用 Playwright 断言
- 布局验证 — 关键页面用 AI 视觉判断
- 样式验证 — 品牌页面用 AI 视觉判断
- Canvas/WebGL — 必须用 AI 视觉判断
示例:
// DOM 验证(优先)
await expect(page.locator('.welcome')).toBeVisible();
// 布局验证(关键页面)
const dashboardLayout = await page.screenshot();
const layoutAnalysis = await analyzeImage(dashboardLayout, [
'布局是否正常'
]);
expect(layoutAnalysis.layout).toBe('normal');
// Canvas/WebGL 验证(必须)
const chartCanvas = await page.locator('canvas').screenshot();
const chartAnalysis = await analyzeImage(chartCanvas, [
'图表是否正确渲染'
]);
expect(chartAnalysis.chart).toBe('rendered');关键洞察
- AI 探索生成 → 固化脚本复用 → AI 视觉兜底
收尾金句:
- 第一层:Browser Use 探索,AI 自主生成测试脚本
- 第二层:Playwright E2E 固化,零 Token 可重复运行
- 第三层:截图视觉兜底,解决传统自动化测试难以处理的前端视觉问题
- 核心目标:降低 E2E 脚本编写成本,提高覆盖率,解决视觉问题
- 这是一套闭环测试方案
用 AI 生成 E2E 测试
从 Browser Use 到 Playwright 的完整工作流
