docs(test): add user journey testing guide and update coverage matrix to 100%

This commit is contained in:
2026-04-09 19:32:43 +08:00
parent ae0b8b7c96
commit 596b238824
2 changed files with 288 additions and 10 deletions
+278
View File
@@ -0,0 +1,278 @@
# 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)