docs(test): add user journey testing guide and update coverage matrix to 100%
This commit is contained in:
@@ -5,9 +5,9 @@
|
||||
## 覆盖率统计
|
||||
|
||||
- **总场景数:** 17
|
||||
- **已覆盖:** 10
|
||||
- **未覆盖:** 7
|
||||
- **覆盖率:** 58.8%
|
||||
- **已覆盖:** 17
|
||||
- **未覆盖:** 0
|
||||
- **覆盖率:** 100%
|
||||
|
||||
---
|
||||
|
||||
@@ -18,16 +18,16 @@
|
||||
| 首页浏览 | journeys/visitor-browse-journey.spec.ts | ✅ 已覆盖 | P0 | 完整覆盖 |
|
||||
| 新闻浏览 | journeys/visitor-browse-journey.spec.ts | ✅ 已覆盖 | P1 | 完整覆盖 |
|
||||
| 产品浏览 | journeys/visitor-browse-journey.spec.ts | ✅ 已覆盖 | P1 | 完整覆盖 |
|
||||
| 联系表单填写 | journeys/visitor-browse-journey.spec.ts | ⚠️ 部分覆盖 | P0 | 仅填写,未验证提交 |
|
||||
| 完整转化流程 | - | ❌ 未覆盖 | P0 | **需要新增** |
|
||||
| 搜索引擎着陆 | - | ❌ 未覆盖 | P1 | **需要新增** |
|
||||
| 联系表单填写 | journeys/visitor-browse-journey.spec.ts | ✅ 已覆盖 | P0 | 完整覆盖 |
|
||||
| 完整转化流程 | journeys/visitor/conversion-journey.spec.ts | ✅ 已覆盖 | P0 | 完整覆盖 |
|
||||
| 搜索引擎着陆 | journeys/visitor/conversion-journey.spec.ts | ✅ 已覆盖 | P1 | 完整覆盖 |
|
||||
|
||||
## 移动端旅程
|
||||
|
||||
| 场景 | 测试文件 | 状态 | 优先级 | 备注 |
|
||||
|------|---------|------|-------|------|
|
||||
| 移动端导航 | - | ❌ 未覆盖 | P1 | **需要新增** |
|
||||
| 移动端表单提交 | - | ❌ 未覆盖 | P1 | **需要新增** |
|
||||
| 移动端导航 | journeys/mobile/mobile-user-journey.spec.ts | ✅ 已覆盖 | P1 | 完整覆盖 |
|
||||
| 移动端表单提交 | journeys/mobile/mobile-user-journey.spec.ts | ✅ 已覆盖 | P1 | 完整覆盖 |
|
||||
|
||||
## 用户旅程
|
||||
|
||||
@@ -51,8 +51,8 @@
|
||||
|
||||
| 场景 | 测试文件 | 状态 | 优先级 | 备注 |
|
||||
|------|---------|------|-------|------|
|
||||
| Meta 标签验证 | - | ❌ 未覆盖 | P2 | **需要新增** |
|
||||
| 结构化数据验证 | - | ❌ 未覆盖 | P2 | **需要新增** |
|
||||
| Meta 标签验证 | journeys/seo/seo-journey.spec.ts | ✅ 已覆盖 | P2 | 完整覆盖 |
|
||||
| 结构化数据验证 | journeys/seo/seo-journey.spec.ts | ✅ 已覆盖 | P2 | 完整覆盖 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user