# User Journey 测试编写规范 ## 📋 目录 1. [测试架构](#测试架构) 2. [命名规范](#命名规范) 3. [Page Object 模式](#page-object-模式) 4. [测试数据管理](#测试数据管理) 5. [测试结构](#测试结构) 6. [最佳实践](#最佳实践) --- ## 测试架构 ### 目录结构 ``` e2e/ ├── fixtures/ # 测试数据和 fixtures │ └── test-data-factory.ts ├── journeys/ # User Journey 测试 │ ├── visitor/ # 访客旅程 │ ├── mobile/ # 移动端旅程 │ └── seo/ # SEO 验证旅程 ├── pages/ # Page Objects │ ├── frontend/ # 前端页面 │ └── admin/ # 后台管理页面 └── utils/ # 工具函数 └── test-reporter.ts ``` --- ## 命名规范 ### 测试文件 - **格式:** `{场景}-journey.spec.ts` - **示例:** `conversion-journey.spec.ts`, `mobile-user-journey.spec.ts` ### 测试用例 - **格式:** `{用户角色}{动作}{预期结果}` - **示例:** `访客从首页浏览到提交咨询的完整旅程` ### Page Object 类 - **格式:** `{Page}Page` - **示例:** `HomePage`, `ContactPage`, `AdminNewsPage` --- ## Page Object 模式 ### 原则 1. **单一职责:** 每个 Page Object 只负责一个页面 2. **封装实现:** 隐藏页面实现细节,暴露业务方法 3. **可复用:** 方法设计应考虑多个测试场景复用 ### 示例 ```typescript import { Page, expect } from '@playwright/test'; export class FrontendContactPage { readonly page: Page; constructor(page: Page) { this.page = page; } async goto() { await this.page.goto('/contact'); await this.page.waitForLoadState('domcontentloaded'); } async fillForm(data: ContactFormData) { await this.page.fill('input[name="name"]', data.name); await this.page.fill('input[name="email"]', data.email); await this.page.fill('textarea[name="message"]', data.message); } async submitForm() { await this.page.click('button[type="submit"]'); } async expectSubmitSuccess() { await expect( this.page.locator('text=提交成功') ).toBeVisible({ timeout: 10000 }); } } ``` --- ## 测试数据管理 ### 使用 TestDataFactory ```typescript import { TestDataFactory } from '../fixtures/test-data-factory'; // 创建默认测试数据 const contactData = TestDataFactory.createContactForm(); // 创建自定义测试数据 const customData = TestDataFactory.createContactForm({ name: '自定义用户', email: 'custom@example.com', }); ``` ### 数据隔离原则 1. **唯一性:** 使用时间戳确保数据唯一 2. **可追溯:** 数据命名包含测试场景标识 3. **清理机制:** 测试后清理创建的数据 --- ## 测试结构 ### 标准 Journey 测试结构 ```typescript import { test, expect } from '@playwright/test'; import { FrontendHomePage, FrontendContactPage } from '../pages/frontend'; import { TestDataFactory } from '../fixtures/test-data-factory'; test.describe('用户旅程描述 @journey @tag', () => { let homePage: FrontendHomePage; let contactPage: FrontendContactPage; test.beforeEach(async ({ page }) => { homePage = new FrontendHomePage(page); contactPage = new FrontendContactPage(page); }); test('完整旅程描述', async () => { const testData = TestDataFactory.createContactForm(); await test.step('步骤1: 初始状态', async () => { await homePage.goto(); await homePage.expectHeroVisible(); }); await test.step('步骤2: 用户行为', async () => { await homePage.clickCTAButton(); }); await test.step('步骤3: 验证结果', async () => { await contactPage.expectSubmitSuccess(); }); }); }); ``` --- ## 最佳实践 ### ✅ 应该做的 1. **使用 test.step 组织测试步骤** ```typescript await test.step('清晰的步骤描述', async () => { // 测试逻辑 }); ``` 2. **使用 Page Object 封装页面操作** ```typescript await homePage.goto(); await homePage.expectHeroVisible(); ``` 3. **使用 TestDataFactory 生成测试数据** ```typescript const data = TestDataFactory.createContactForm(); ``` 4. **添加清晰的断言** ```typescript await expect(page.locator('h1')).toBeVisible(); await expect(page).toHaveTitle(/关键词/); ``` 5. **使用标签分类测试** ```typescript test.describe('访客旅程 @journey @visitor @conversion', () => { // ... }); ``` ### ❌ 不应该做的 1. **不要直接操作 page 对象** ```typescript // ❌ 错误 await page.fill('input[name="name"]', 'test'); // ✅ 正确 await contactPage.fillForm(data); ``` 2. **不要硬编码测试数据** ```typescript // ❌ 错误 await page.fill('input[name="name"]', '测试用户'); // ✅ 正确 const data = TestDataFactory.createContactForm(); await contactPage.fillForm(data); ``` 3. **不要使用过长的等待** ```typescript // ❌ 错误 await page.waitForTimeout(5000); // ✅ 正确 await page.waitForLoadState('domcontentloaded'); await expect(element).toBeVisible({ timeout: 10000 }); ``` --- ## 测试标签体系 | 标签 | 用途 | 示例 | |------|------|------| | `@journey` | 所有 User Journey 测试 | `@journey` | | `@visitor` | 访客相关测试 | `@visitor` | | `@user` | 已登录用户测试 | `@user` | | `@admin` | 管理员测试 | `@admin` | | `@mobile` | 移动端测试 | `@mobile` | | `@seo` | SEO 相关测试 | `@seo` | | `@conversion` | 转化流程测试 | `@conversion` | ### 运行特定标签的测试 ```bash # 运行所有 journey 测试 npx playwright test --grep "@journey" # 运行移动端测试 npx playwright test --grep "@mobile" # 运行 SEO 测试 npx playwright test --grep "@seo" ``` --- ## 质量标准 ### 测试覆盖率目标 - **User Journey 覆盖率:** 100% - **Page Object 覆盖率:** 100% - **关键业务流程:** 必须覆盖 ### 测试质量指标 - **通过率:** ≥ 95% - **平均执行时间:** < 5秒/测试 - **Flaky 测试率:** < 2% --- ## 参考资源 - [Playwright 官方文档](https://playwright.dev/) - [Page Object 模式最佳实践](https://playwright.dev/docs/pom) - [测试覆盖率矩阵](./user-journey-coverage-matrix.md)