Files
novalon-website/docs/testing/user-journey-testing-guide.md
T

6.3 KiB

User Journey 测试编写规范

📋 目录

  1. 测试架构
  2. 命名规范
  3. 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. 可复用: 方法设计应考虑多个测试场景复用

示例

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

import { TestDataFactory } from '../fixtures/test-data-factory';

// 创建默认测试数据
const contactData = TestDataFactory.createContactForm();

// 创建自定义测试数据
const customData = TestDataFactory.createContactForm({
  name: '自定义用户',
  email: 'custom@example.com',
});

数据隔离原则

  1. 唯一性: 使用时间戳确保数据唯一
  2. 可追溯: 数据命名包含测试场景标识
  3. 清理机制: 测试后清理创建的数据

测试结构

标准 Journey 测试结构

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 组织测试步骤

    await test.step('清晰的步骤描述', async () => {
      // 测试逻辑
    });
    
  2. 使用 Page Object 封装页面操作

    await homePage.goto();
    await homePage.expectHeroVisible();
    
  3. 使用 TestDataFactory 生成测试数据

    const data = TestDataFactory.createContactForm();
    
  4. 添加清晰的断言

    await expect(page.locator('h1')).toBeVisible();
    await expect(page).toHaveTitle(/关键词/);
    
  5. 使用标签分类测试

    test.describe('访客旅程 @journey @visitor @conversion', () => {
      // ...
    });
    

不应该做的

  1. 不要直接操作 page 对象

    // ❌ 错误
    await page.fill('input[name="name"]', 'test');
    
    // ✅ 正确
    await contactPage.fillForm(data);
    
  2. 不要硬编码测试数据

    // ❌ 错误
    await page.fill('input[name="name"]', '测试用户');
    
    // ✅ 正确
    const data = TestDataFactory.createContactForm();
    await contactPage.fillForm(data);
    
  3. 不要使用过长的等待

    // ❌ 错误
    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

运行特定标签的测试

# 运行所有 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%

参考资源