E2E 命令¶
此命令会调用 e2e-runner 代理,使用 Playwright 生成、维护和运行端到端测试。
此命令的功能¶
- 生成测试旅程 - 创建用户流程的 Playwright 测试
- 运行 E2E 测试 - 在多个浏览器之间运行测试
- 捕获产物 - 失败时的截图、视频和跟踪
- 上传结果 - HTML 报告和 JUnit XML
- 识别不稳定测试 - 隔离不稳定测试
何时使用¶
在以下情况下使用 /e2e:
- 测试关键用户旅程(登录、交易、支付)
- 验证多步骤流程端到端正常工作
- 测试 UI 交互和导航
- 验证前端和后端之间的集成
- 为生产环境部署做准备
工作原理¶
e2e-runner 代理会:
- 分析用户流程以识别测试场景
- 使用页面对象模型模式生成 Playwright 测试
- 在多个浏览器之间(Chrome、Firefox、Safari)运行测试
- 捕获失败(包括截图、视频和跟踪)
- 生成包含结果和产物的报告
- 识别不稳定测试并推荐修复
使用示例¶
User: /e2e マーケット検索と表示フローをテスト
Agent (e2e-runner):
# E2Eテスト生成: マーケット検索と表示フロー
## 特定されたテストシナリオ
**ユーザージャーニー:** マーケット検索 → 結果表示 → マーケットクリック → 詳細表示
**テストカバレッジ:**
1. マーケットページに遷移
2. セマンティック検索を実行
3. 検索結果を検証
4. 最初の結果をクリック
5. マーケット詳細ページの読み込みを検証
6. チャートの描画を検証
## 生成されたテストコード
```typescript
// tests/e2e/markets/search-and-view.spec.ts
import { test, expect } from '@playwright/test'
import { MarketsPage } from '../../pages/MarketsPage'
import { MarketDetailsPage } from '../../pages/MarketDetailsPage'
test.describe('Market Search and View Flow', () => {
test('user can search markets and view details', async ({ page }) => {
// 1. Navigate to markets page
const marketsPage = new MarketsPage(page)
await marketsPage.goto()
// Verify page loaded
await expect(page).toHaveTitle(/Markets/)
await expect(page.locator('h1')).toContainText('Markets')
// 2. Perform semantic search
await marketsPage.searchMarkets('election')
// Wait for API response
await page.waitForResponse(resp =>
resp.url().includes('/api/markets/search') && resp.status() === 200
)
// 3. Verify search results
const marketCards = marketsPage.marketCards
await expect(marketCards.first()).toBeVisible()
const resultCount = await marketCards.count()
expect(resultCount).toBeGreaterThan(0)
// Take screenshot of search results
await page.screenshot({ path: 'artifacts/search-results.png' })
// 4. Click on first result
const firstMarketTitle = await marketCards.first().textContent()
await marketCards.first().click()
// 5. Verify market details page loads
await expect(page).toHaveURL(/\/markets\/[a-z0-9-]+/)
const detailsPage = new MarketDetailsPage(page)
await expect(detailsPage.marketName).toBeVisible()
await expect(detailsPage.marketDescription).toBeVisible()
// 6. Verify chart renders
await expect(detailsPage.priceChart).toBeVisible()
// Verify market name matches
const detailsTitle = await detailsPage.marketName.textContent()
expect(detailsTitle?.toLowerCase()).toContain(
firstMarketTitle?.toLowerCase().substring(0, 20) || ''
)
// Take screenshot of market details
await page.screenshot({ path: 'artifacts/market-details.png' })
})
test('search with no results shows empty state', async ({ page }) => {
const marketsPage = new MarketsPage(page)
await marketsPage.goto()
// Search for non-existent market
await marketsPage.searchMarkets('xyznonexistentmarket123456')
// Verify empty state
await expect(page.locator('[data-testid="no-results"]')).toBeVisible()
await expect(page.locator('[data-testid="no-results"]')).toContainText(
/no.*results|no.*markets/i
)
const marketCount = await marketsPage.marketCards.count()
expect(marketCount).toBe(0)
})
test('can clear search and see all markets again', async ({ page }) => {
const marketsPage = new MarketsPage(page)
await marketsPage.goto()
// Initial market count
const initialCount = await marketsPage.marketCards.count()
// Perform search
await marketsPage.searchMarkets('trump')
await page.waitForLoadState('networkidle')
// Verify filtered results
const filteredCount = await marketsPage.marketCards.count()
expect(filteredCount).toBeLessThan(initialCount)
// Clear search
await marketsPage.searchInput.clear()
await page.waitForLoadState('networkidle')
// Verify all markets shown again
const finalCount = await marketsPage.marketCards.count()
expect(finalCount).toBe(initialCount)
})
})
```
## テスト実行
```bash
# 生成されたテストを実行
npx playwright test tests/e2e/markets/search-and-view.spec.ts
Running 3 tests using 3 workers
✓ [chromium] › search-and-view.spec.ts:5:3 › user can search markets and view details (4.2s)
✓ [chromium] › search-and-view.spec.ts:52:3 › search with no results shows empty state (1.8s)
✓ [chromium] › search-and-view.spec.ts:67:3 › can clear search and see all markets again (2.9s)
3 passed (9.1s)
Artifacts generated:
- artifacts/search-results.png
- artifacts/market-details.png
- playwright-report/index.html
```
## テストレポート
```
╔══════════════════════════════════════════════════════════════╗
║ E2Eテスト結果 ║
╠══════════════════════════════════════════════════════════════╣
║ ステータス: PASS: 全テスト合格 ║
║ 合計: 3テスト ║
║ 合格: 3 (100%) ║
║ 失敗: 0 ║
║ 不安定: 0 ║
║ 所要時間: 9.1s ║
╚══════════════════════════════════════════════════════════════╝
アーティファクト:
スクリーンショット: 2ファイル
ビデオ: 0ファイル (失敗時のみ)
トレース: 0ファイル (失敗時のみ)
HTMLレポート: playwright-report/index.html
レポート表示: npx playwright show-report
```
PASS: E2E テストスイートは CI/CD 統合の準備ができました!
测试产物¶
运行测试时,会捕获以下产物:
所有测试通用: - 包含时间线和结果的 HTML 报告 - 用于 CI 集成的 JUnit XML
仅失败时: - 失败状态的截图 - 测试视频录制 - 调试跟踪文件(逐步回放) - 网络日志 - 控制台日志
查看产物¶
# ブラウザでHTMLレポートを表示
npx playwright show-report
# 特定のトレースファイルを表示
npx playwright show-trace artifacts/trace-abc123.zip
# スクリーンショットはartifacts/ディレクトリに保存
open artifacts/search-results.png
````
## 不稳定测试检测 {#flaky-test-detection}
当测试间歇性失败时:
テストは10回中7回合格 (合格率70%)
よくある失敗: "Timeout waiting for element '[data-testid="confirm-btn"]'"
推奨修正: 1. 明示的な待機を追加: await page.waitForSelector('[data-testid="confirm-btn"]') 2. タイムアウトを増加: { timeout: 10000 } 3. コンポーネントの競合状態を確認 4. 要素がアニメーションで隠れていないか確認
隔離推奨: 修正されるまでtest.fixme()としてマーク
## 浏览器配置 {#browser-configuration}
默认情况下,测试会在多个浏览器中运行:
* PASS: Chromium(桌面 Chrome)
* PASS: Firefox(桌面)
* PASS: WebKit(桌面 Safari)
* PASS: Mobile Chrome(可选)
在 `playwright.config.ts` 中配置以调整浏览器。
## CI/CD 集成 {#ci-cd-integration}
添加到 CI 流水线:
```yaml
# .github/workflows/e2e.yml
- name: Install Playwright
run: npx playwright install --with-deps
- name: Run E2E tests
run: npx playwright test
- name: Upload artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: playwright-report
path: playwright-report/
PMX 特定关键流程¶
对于 PMX,请优先以下 E2E 测试:
严重(必须始终成功):
- 用户可以连接钱包
- 用户可以浏览市场
- 用户可以搜索市场(语义搜索)
- 用户可以查看市场详情
- 用户可以提交交易订单(使用测试资金)
- 市场正确结算
- 用户可以提取资金
重要:
- 市场创建流程
- 用户资料更新
- 实时价格更新
- 图表渲染
- 市场筛选和排序
- 移动响应式布局
最佳实践¶
应该做:
- PASS: 使用页面对象模型以提高可维护性
- PASS: 使用 data-testid 属性作为选择器
- PASS: 等待 API 响应而不是任意超时
- PASS: 对关键用户旅程进行端到端测试
- PASS: 在合并到 main 之前运行测试
- PASS: 测试失败时审查工件
不应该做:
- FAIL: 使用不稳定的选择器(CSS 类可能会变化)
- FAIL: 测试实现细节
- FAIL: 针对生产环境运行测试
- FAIL: 忽略不稳定的测试
- FAIL: 失败时跳过工件审查
- FAIL: 在 E2E 测试中测试所有边缘情况(使用单元测试)
重要注意事项¶
对 PMX 至关重要:
- 涉及真实资金的 E2E 测试只能在测试网/预发布环境中运行
- 不要针对生产环境运行交易测试
- 为金融测试设置
test.skip(process.env.NODE_ENV === 'production') - 仅使用包含少量测试资金的测试钱包
与其他命令的集成¶
- 使用
/plan识别需要测试的关键旅程 - 将
/tdd用于单元测试(更快、更细粒度) - 将
/e2e用于集成和用户旅程测试 - 使用
/code-review验证测试质量
相关代理¶
此命令会调用 ~/.claude/agents/e2e-runner.md 中的 e2e-runner 代理。
快速命令¶
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC