2026-07-25-e2e-test-rearchitecture-design.md 25 KB

E2E 测试体系重构方案

版本: v1.0 日期: 2026-07-25 状态: 设计稿


一、现状分析

1.1 现有测试概览

维度 当前状态
测试文件数 40 个 spec 文件
覆盖角色 6 个 (parent/child/teacher/nutritionist/vendor/admin)
框架 Playwright
目标环境 http://cfc.iwintrue.com (通过 PW_BASE_URL 配置)
测试数据 无统一管理,依赖环境存量数据

1.2 现有问题

问题 严重程度 说明
重复的认证代码 🔴 高 6 个 admin 文件各有一套 ensureLoggedIn/login 函数副本
无认证的 mini-app 测试 🔴 高 parent/child/teacher 角色的 E2E 测试没有登录环节
无测试数据管理 🔴 高 每次运行依赖环境现有数据,无 reset/seed
质量不一致 🟡 中 10 个文件仅检查页面渲染,无真实断言
角色不清晰 🟡 中 文件按功能命名而非角色,跨角色文件归属混乱
无 API 断言 🟡 中 全部是 UI 可见性验证,无后端响应验证
无数据清理 🟡 中 测试创建的记录会遗留

1.3 需求范围

  • 重构目录为 角色维度 + 流程维度 双轴结构
  • 支持 8 类角色:parent / child / teacher / nutritionist / butler / admin / vendor
  • 覆盖全部 1357 个 API 端点中的核心场景
  • 基础设施:统一认证 helper、DB reset + seed、测试数据工厂
  • 跨角色流程测试(flows)

二、架构设计

2.1 双轴目录结构

tests/e2e/
│
├── playwright.config.js          # Playwright 配置(已存在,微调)
├── reset-db.sh                   # 🔧 数据库重置脚本(新增)
├── seed-data.sql                 # 🔧 种子数据(新增)
│
├── helpers/                      # 🔧 基础设施
│   ├── auth.js                   #    8 类角色登录 helper
│   ├── db.js                     #    reset + seed 统一入口
│   ├── fixtures.js               #    测试数据工厂
│   └── utils.js                  #    通用工具
│
├── roles/                        # 角色维度 —— 按操作用户分类
│   ├── parent/                   #    家长端
│   ├── child/                    #    孩子端
│   ├── teacher/                  #    成长规划师
│   ├── nutritionist/             #    健康营养师
│   ├── butler/                   #    管家
│   ├── admin/                    #    运营管理端
│   │   ├── article/              #      文章管理子模块
│   │   ├── activity/             #      活动管理子模块
│   │   ├── vendor/               #      供应商管理子模块
│   │   ├── audit/                #      统一审核中心
│   │   ├── product/              #      商品管理子模块
│   │   └── system/               #      系统配置子模块
│   └── vendor/                   #    供应商/服务商
│
└── flows/                        # 流程维度 —— 跨角色业务流
    ├── assessment-full-chain/    #    测评全链(家长→系统→测评师→家长)
    ├── task-lifecycle/           #    任务生命周期(家长创建→孩子完成→家长审核)
    ├── wish-fulfillment/         #    心愿流转(孩子创建→家长定价→兑换→审批)
    ├── family-invite-flow/       #    家庭邀请(家长邀请→加入)
    ├── planner-bind-flow/        #    规划师绑定(规划师邀请→家长接受)
    └── vendor-onboarding-flow/   #    供应商入驻(申请→审核→上架)

2.2 双轴关系

                    ┌─────────────────────────────────────┐
                    │             flows/                   │
                    │  跨角色业务流(串联多个角色操作)      │
                    └─────────────────────────────────────┘
                                     │
         ┌───────────────┬───────────┼───────────┬──────────────────┐
         ▼               ▼           ▼           ▼                  ▼
    roles/parent    roles/child   roles/teacher  roles/admin    roles/vendor
    ───────────    ───────────   ─────────────  ───────────    ────────────
    login          login         login          login          login
    family-mgmt    daily-checkin family-binding user-mgmt      onboarding
    task-mgmt      mini-games    task-assign    article/*      product-mgmt
    wish-mgmt      task-exec     package-mgmt   activity/*     order-process
    assessment     wish-create   assessment/*   vendor/*
    energy         energy-view   training-plan  system/*
    product                        family-list   audit/*
    growth-record                  dashboard     membership
    ───────────    ───────────   ─────────────  ───────────    ────────────
    nutritionist   butler
    ───────────    ───────────
    login          login
    profile-mgmt   ai-chat
    diet-record    task-reminder
    recipe-mgmt    health-track
    meal-recommend

原则

  • roles/ 下的测试:单一角色操作,验证该角色能做什么、不能做什么
  • flows/ 下的测试:跨角色协作,串联完整业务流,验证状态流转正确
  • flows/ 测试可以调用 roles/ 中的辅助函数(如 loginAs())但不能依赖 roles/ 中的测试用例

三、基础设施设计

3.1 统一认证 (helpers/auth.js)

// 支持 8 种角色,每个角色有独立登录入口和凭证
const ROLES = {
  parent:       { phone: '13701366188',  loginType: 'phone' },
  child:        { phone: '13701366189',  loginType: 'phone' },
  teacher:      { phone: '13800000001',  loginType: 'phone' },
  nutritionist: { phone: '13800000010',  loginType: 'phone' },
  butler:       { phone: '13800000020',  loginType: 'phone' },
  admin:        { phone: '13800138000',  loginType: 'password' },
  vendor:       { phone: '13800138001',  loginType: 'phone' },
  assessor:     { phone: '13800000030',  loginType: 'phone' },
};

// 入口函数
async function loginAs(page, role) {
  // admin → 走 admin 登录页面
  // 其他 → 走 mini-app 登录流程
  // 返回 { token, userId, role }
}

// 在每个测试文件头部调用
test.beforeAll(async ({ browser }) => {
  const context = await browser.newContext({ storageState: undefined });
  const page = await context.newPage();
  const auth = await loginAs(page, 'parent');
  await context.storageState({ path: STATE_PATH });
  // 保存 token 供 API 断言使用
});

3.2 数据库重置 (reset-db.sh + seed-data.sql)

#!/bin/bash
# reset-db.sh — 每次 E2E 运行前执行

MYSQL_HOST="192.168.16.251"
MYSQL_USER="cfc"
MYSQL_PASS="cfc@123"
MYSQL_DB="cfc"

echo "==> 重置数据库..."
mysql -h$MYSQL_HOST -u$MYSQL_USER -p$MYSQL_PASS $MYSQL_DB < seed-data.sql
echo "==> 完成"

种子数据需要包含:

数据 内容
测试用户 每个角色 1-2 个账号,包含家庭关系
测试家庭 1 个完整家庭(家长+2个孩子)
测试商品 3-5 个商品/套餐
测试文章 1 篇草稿 + 1 篇已发布
测试活动 1 个待审核 + 1 个已发布
测试订单 1 个已完成订单
系统配置 维度、能量规则、佣金配置

3.3 测试数据工厂 (helpers/fixtures.js)

// 生成测试数据的辅助函数
async function createTestUser(db, role, overrides) { /* ... */ }
async function createTestTask(db, userId, overrides) { /* ... */ }
async function createTestWish(db, childId, overrides) { /* ... */ }
// ...

3.4 API 断言辅助 (helpers/utils.js)

// 通用的 API 响应断言
async function assertApiSuccess(response, expectedStatus = 200) {
  expect(response.status()).toBe(expectedStatus);
  const body = await response.json();
  expect(body.code).toBe(200);
  return body.data;
}

async function assertApiError(response, expectedCode, expectedMessage) {
  const body = await response.json();
  expect(body.code).toBe(expectedCode);
  if (expectedMessage) expect(body.message).toContain(expectedMessage);
}

3.5 playwright.config.js 调整

// 增加全局 setup(DB reset)
globalSetup: require.resolve('./helpers/db.js'),
// 增加每个 spec 的超时
timeout: 120000,
// 增加 retry
retries: 1,

四、角色维度测试设计

4.1 家长 (parent)

文件 场景数 现有文件映射 优先级
login.spec.js 4 AuthControllerTest 反向 P0
family-management.spec.js 9 family-member-management.spec.js P0
task-management.spec.js 5 新增(补齐审批/历史) P1
wish-management.spec.js 5 wish-exchange-flow.spec.js 拆分 P0
assessment-order.spec.js 7 assessment-order-flow.spec.js P0
energy-dashboard.spec.js 6 energy-system.spec.js P0
product-purchase.spec.js 9 product-purchase.spec.js P0
growth-record.spec.js 5 growth-record-sync.spec.js P0
health-report.spec.js 4 新增 P1
nutrition-profile.spec.js 4 nutritionist-flow.spec.js 拆分 P1
subscription.spec.js 5 🔴 新增(当前零覆盖) P1
membership.spec.js 3 membership-system.spec.js P1
ai-chat.spec.js 4 ai-plan-task-flow.spec.js P1
points.spec.js 4 points-system.spec.js P0
consignee.spec.js 4 consignee-management.spec.js P1
contact.spec.js 4 contact-management.spec.js P1
family-earnings.spec.js 3 🔴 新增(当前零覆盖) P2
小计 85

4.2 孩子 (child)

文件 场景数 现有文件映射 优先级
login.spec.js 3 🔴 新增(当前无独立孩子登录测试) P0
daily-checkin.spec.js 8 daily-checkin-streak.spec.js P0
mini-games.spec.js 6 mini-games-*.spec.js (3 文件合并) P0
task-execution.spec.js 4 新增(完成任务/提交) P0
wish-create.spec.js 3 wish-exchange-flow.spec.js 拆分 P0
energy-view.spec.js 3 energy-system.spec.js P0
growth-record.spec.js 3 growth-record-sync.spec.js P1
小计 30

4.3 成长规划师 (teacher)

文件 场景数 现有文件映射 优先级
login.spec.js 4 TeacherLoginTest 反向 P0
family-binding.spec.js 7 planner-bind-invite.spec.js P0
package-management.spec.js 5 🔴 新增(当前零覆盖) P0
task-assignment.spec.js 6 🔴 新增(任务下发/批量审核) P0
family-list.spec.js 5 guide-family-list.spec.js P0
training-plan.spec.js 4 🔴 新增(当前零覆盖) P1
dashboard.spec.js 4 teacher-dashboard.spec.js P1
assessment/ (测评师子角色)
├── recording.spec.js 5 assessment-order-flow.spec.js 提取 P0
├── appointment.spec.js 4 🔴 新增(当前零覆盖) P0
└── report-view.spec.js 3 提取 P1
小计 47

4.4 健康营养师 (nutritionist) — 🆕

文件 场景数 现有文件映射 优先级
login.spec.js 2 🔴 新增 P0
profile-management.spec.js 3 nutritionist-flow.spec.js (拆分) P0
diet-record.spec.js 3 nutritionist-flow.spec.js (拆分) P0
recipe-management.spec.js 4 nutritionist-flow.spec.js (拆分) P1
meal-recommendation.spec.js 3 🔴 新增 P1
family-binding.spec.js 2 nutritionist-flow.spec.js (拆分) P0
小计 17

4.5 管家 (butler) — 🆕

文件 场景数 优先级
login.spec.js 2 P0
ai-chat.spec.js 4 P0
task-reminder.spec.js 3 P1
health-tracking.spec.js 3 P1
小计 12

4.6 管理员 (admin)

文件 场景数 现有文件映射 优先级
login.spec.js 2 提取统一 P0
user-management.spec.js 5 🔴 新增(当前零覆盖) P0
family-management.spec.js 4 🔴 新增(当前零覆盖) P1
article/workflow.spec.js 5 article-management.spec.js P0
article/category.spec.js 3 🔴 新增(当前零覆盖) P1
article/tag.spec.js 3 🔴 新增 P2
activity/approval.spec.js 4 activity-registration.spec.js P0
activity/config.spec.js 3 🔴 新增(当前零覆盖) P1
vendor/management.spec.js 4 vendor-onboarding.spec.js P0
audit/article-audit.spec.js 3 unified-audit-center.spec.js P0
audit/butler-audit.spec.js 3 admin-butler-review.spec.js P1
audit/vendor-audit.spec.js 3 🔴 新增 P1
product/approval.spec.js 4 admin-ecom-supplier.spec.js P1
product/category.spec.js 3 🔴 新增(当前零覆盖) P2
system/dimension-config.spec.js 4 🔴 新增(当前零覆盖) P1
system/energy-config.spec.js 4 energy-rules-config.spec.js P0
system/commission-config.spec.js 3 admin-commission-config.spec.js P1
system/promotion-config.spec.js 3 admin-promotion-config.spec.js P2
system/operation-log.spec.js 3 🔴 新增(当前零覆盖) P2
membership.spec.js 4 🔴 新增(当前零覆盖) P1
subscription.spec.js 3 🔴 新增(当前零覆盖) P1
data-migration.spec.js 3 🔴 新增(当前零覆盖) P2
小计 74

4.7 供应商/服务商 (vendor)

文件 场景数 现有文件映射 优先级
onboarding.spec.js 4 vendor-onboarding.spec.js 提取 P0
product-management.spec.js 5 vendor-product-manage.spec.js P0
order-processing.spec.js 4 🔴 新增(当前零覆盖) P1
dan-assessment-vendor.spec.js 4 dan-assessment-vendor-flow.spec.js P1
小计 17

五、流程维度测试设计

流程测试按 flows/ 下的独立目录组织,每个目录包含一个完整业务流的多个阶段。

5.1 测评全链 (assessment-full-chain)

flows/assessment-full-chain/
├── flow.spec.js                  # 主流程测试

业务流:家长购买测评 → 支付 → 系统分配规划师 → 规划师录入结果 → 家长查看报告

阶段 角色 验证点
1 家长 选择孩子+规划师 → 创建订单 → 订单状态=待支付
2 家长 完成支付 → 订单状态=已支付,预约自动创建
3 系统 预约状态=待确认
4 规划师 确认预约 → 查看孩子快照
5 规划师 录入测评结果 → 结果状态=已录入
6 家长 查看测评报告 → 结果可见
7 家长 取消未支付订单 → 订单状态=已取消

API 验证:

POST /api/dan-assessment/order/create       → code=200, orderId
POST /api/dan-assessment/order/pay          → code=200, status=paid
POST /api/dan-assessment/appointment/confirm → code=200, status=confirmed
POST /api/dan-assessment/result/create      → code=200, resultId
POST /api/dan-assessment/order/detail       → code=200, resultId != null

5.2 任务生命周期 (task-lifecycle)

业务流:家长创建任务 → 孩子查看/完成 → 家长审核 → 积分发放

阶段 角色 验证点
1 家长 创建任务(含小游戏任务)→ 任务状态=待完成
2 孩子 查看今日任务列表 → 新任务可见
3 孩子 完成小游戏/提交 → 任务状态=待审核
4 家长 审核通过/驳回 → 审核通过则发放积分
5 孩子 查看积分 → 积分增加

5.3 心愿流转 (wish-fulfillment)

业务流:孩子创建心愿 → 家长定价 → 孩子申请兑换 → 家长审批 → 扣减积分

阶段 角色 验证点
1 孩子 创建心愿 → 心愿状态=待定价
2 家长 定价 → 心愿有积分值
3 孩子 申请兑换 → 状态=待审批
4 家长 审批通过/拒绝 → 通过则扣减积分
5 孩子 查看积分 → 已扣减
6 家长 拒绝心愿 → 状态=已拒绝

5.4 家庭邀请流程 (family-invite-flow)

业务流:家长生成邀请码 → 新用户扫码 → 加入家庭

阶段 角色 验证点
1 家长 生成家庭邀请码 → 返回 token
2 新用户 输入邀请码 → 绑定到家庭
3 家长 查看家庭成员列表 → 新成员可见
4 家长 移除成员 → 成员列表更新

5.5 规划师绑定流程 (planner-bind-flow)

业务流:规划师生成邀请 → 家长接受绑定 → 规划师客户列表更新

阶段 角色 验证点
1 规划师 生成绑定邀请 → 返回凭证
2 家长 验证邀请 → 展示邀请详情
3 家长 确认绑定 → 绑定成功
4 规划师 查看客户列表 → 新家庭可见
5 规划师 解绑 → 关系终止

5.6 供应商入驻流程 (vendor-onboarding-flow)

业务流:供应商提交入驻 → 管理员审核 → 供应商上架商品 → 用户购买

阶段 角色 验证点
1 供应商 提交入驻申请 → 状态=pending
2 管理员 审核通过/驳回 → 通过则状态=approved
3 供应商 创建商品 → 商品状态=待审核
4 管理员 审核商品 → 上架
5 用户 浏览并购买商品 → 订单创建
6 供应商 查看订单 → 订单可见

六、质量规范

6.1 每个测试文件必须包含

const { test, expect } = require('@playwright/test');
const { loginAs } = require('../../helpers/auth');
const { assertApiSuccess } = require('../../helpers/utils');

test.describe('【角色】模块 - 场景描述', () => {
  let auth;

  test.beforeAll(async ({ browser }) => {
    auth = await loginAs(browser, 'parent');
  });

  test('[场景N] 用户故事描述 — 期望具体结果', async ({ page }) => {
    // Given:前置条件
    // When:操作
    // Then:验证(UI断言 + API断言)
  });
});

6.2 断言标准

等级 断言要求 示例
P0 UI 可见性 + API 响应码 + 关键数据验证 HTTP 200 + body.code === 200 + body.data.orderId 非空
P1 UI 可见性 + API 响应码 HTTP 200 + body.code === 200
P2 UI 可见性 .toBeVisible()

所有 P0/P1 场景必须包含 API 级断言。 P2 场景允许仅 UI 验证。

6.3 API 断言模式

// 方式一:通过 page.request 直接验证后端
const response = await page.request.post('/api/family/member/list', {
  data: { familyId: auth.familyId },
  headers: { Authorization: 'Bearer ' + auth.token },
});
const data = await assertApiSuccess(response);
expect(data.members.length).toBeGreaterThan(0);

// 方式二:混合 UI + API
await page.click('.submit-btn');
await expect(page.locator('.success-tip')).toBeVisible();
const orderResp = await assertApiSuccess(
  await page.request.post('/api/dan-assessment/order/detail', { /* ... */ })
);
expect(orderResp.order.status).toBe('paid');

6.4 数据隔离

  • 每个测试文件在 beforeAll 中登录
  • 每个场景(test())独立验证,不依赖其他场景的副作用
  • 数据清理统一在 seed-data.sql 层面解决(每次运行前全量恢复)

6.5 错误场景覆盖

每个 P0 场景必须包含 至少一个错误场景(异常分支):

场景1: 正常流程 — 期望成功
场景1b: 参数异常(空值/越界/不存在)— 期望合理错误提示
场景1c: 权限异常(无权限角色操作)— 期望 403/500

七、实施计划

Phase 1:基础设施 + 核心角色重构(2周)

任务 交付物 工时
1.1 编写 reset-db.sh + seed-data.sql 数据库重置脚本 1天
1.2 编写 helpers/auth.js 8 角色登录 helper 1.5天
1.3 编写 helpers/fixtures.js 测试数据工厂 1天
1.4 编写 helpers/utils.js 通用断言工具 0.5天
1.5 调整 playwright.config.js 全局配置 0.5天
1.6 重构 roles/parent/ (6个核心文件) login, family, wish, assessment, energy, points 3天
1.7 重构 roles/child/ (4个核心文件) login, checkin, games, wish-create 2天
1.8 重构 roles/teacher/ (4个核心文件) login, binding, task, family-list 2天
1.9 重构 roles/admin/ (4个核心文件) login, article, activity, audit 2天

Phase 2:新增角色 + 流程测试(2周)

任务 交付物 工时
2.1 新增 roles/nutritionist/ (3个文件) login, profile, diet-record 2天
2.2 新增 roles/butler/ (2个文件) login, ai-chat 2天
2.3 新增 roles/teacher/assessment/ (3个文件) recording, appointment, report 2天
2.4 新增 roles/admin/user-management 用户管理 1天
2.5 新增 flows/assessment-full-chain 测评全链流程 2天
2.6 新增 flows/task-lifecycle 任务生命周期 1.5天
2.7 新增 flows/wish-fulfillment 心愿流转 1.5天
2.8 新增 flows/planner-bind-flow 规划师绑定流程 1天

Phase 3:补齐剩余模块 + 错误场景(2周)

任务 交付物 工时
3.1 补齐 roles/parent/ 剩余文件 subscription, membership, ai-chat, growth, health 3天
3.2 补齐 roles/admin/ 剩余模块 system/, product/, vendor/, membership 3天
3.3 补齐 roles/vendor/ onboarding, product, order 2天
3.4 补齐 roles/teacher/ 剩余文件 package, training-plan, dashboard 2天
3.5 补齐 roles/nutritionist/ 剩余文件 recipe, meal-recommend, family-binding 1天
3.6 补齐 flows/ 剩余流程 family-invite, vendor-onboarding 2天
3.7 为所有 P0 场景补充错误场景 异常分支 2天
3.8 删除旧文件 清理旧目录 0.5天

八、运行方式

# 1. 重置数据库
bash tests/e2e/reset-db.sh

# 2. 运行全部测试
npx playwright test tests/e2e/

# 3. 按角色运行
npx playwright test tests/e2e/roles/parent/
npx playwright test tests/e2e/roles/admin/

# 4. 按流程运行
npx playwright test tests/e2e/flows/assessment-full-chain/

# 5. 单文件
npx playwright test tests/e2e/roles/parent/family-management.spec.js

# 6. 自定义环境
PW_BASE_URL=http://staging.cfc.iwintrue.com npx playwright test

九、文件变更清单

新增

文件 数量
tests/e2e/helpers/auth.js 1
tests/e2e/helpers/db.js 1
tests/e2e/helpers/fixtures.js 1
tests/e2e/helpers/utils.js 1
tests/e2e/reset-db.sh 1
tests/e2e/seed-data.sql 1
tests/e2e/roles/ 目录下 spec 文件 ~58
tests/e2e/flows/ 目录下 spec 文件 ~6
新增合计 ~70 文件

删除

文件 数量
旧的 tests/e2e/*.spec.js 文件 40

修改

文件 数量
tests/e2e/playwright.config.js 1

十、验收标准

标准 说明
所有测试可独立运行 npx playwright test tests/e2e/roles/parent/ 通过
每次运行前 DB 自动重置 全局 setup 脚本执行 reset-db.sh
无重复认证代码 所有认证走 helpers/auth.js
无纯占位测试 每个 test() 有至少一个 expect()
所有 P0 场景含错误路径 至少 1 个正常 + 1 个异常
流程测试验证跨角色状态流转 API 断言验证状态变更
旧文件全部移除 tests/e2e/*.spec.js 残留