# E2E 测试设计规格 — HMS 健康管理平台 > 日期: 2026-04-28 | 状态: 设计中 ## Context HMS 健康管理平台当前 E2E 测试仅有 10 个基础用例(登录/用户/插件/租户隔离),健康模块 ~27 个 Web 页面路由和微信小程序端完全无 E2E 覆盖。wiki 已将此标注为 P2 缺口。本设计旨在建立双端(Web + 小程序)的流程链路式 E2E 测试体系。 ## 大纲 1. 整体架构与目录结构 2. 关键业务链路定义 3. 测试数据策略与 API Client 4. Page Object 与 MCP Helper 设计 5. 执行策略与 CI-Ready 设计 --- ## §1 整体架构与目录结构 ### 设计决策 | 维度 | 选择 | 原因 | |------|------|------| | 覆盖范围 | Web 全量 + 小程序并行 | 双端同步覆盖,最大化业务保障 | | 测试深度 | 关键流程冒烟测试 | 务实覆盖最重要的用户路径 | | 小程序实现 | WeChat MCP 自动化 | 利用已有 MCP 联调能力 | | 测试架构 | 双端独立框架 | Web 用 Playwright,小程序用 Vitest + MCP | | 测试数据 | API 驱动自建自毁 | 每个测试独立创建/清理数据 | | CI 策略 | 本地优先,CI-ready 设计 | 环境变量驱动,未来可接入 GitHub Actions | ### 目录结构 ``` apps/web/e2e/ # Web 端 E2E(Playwright) ├── flows/ # 业务链路测试 │ ├── patient-journey.spec.ts # 患者全流程 │ ├── vital-signs-flow.spec.ts # 体征数据链路 │ ├── appointment-flow.spec.ts # 预约排班链路 │ ├── follow-up-flow.spec.ts # 随访管理链路 │ └── alert-flow.spec.ts # 告警处理链路 ├── smoke/ # 基础冒烟(迁移现有 4 个 spec) │ ├── login.spec.ts │ ├── users.spec.ts │ ├── plugins.spec.ts │ └── tenant-isolation.spec.ts ├── fixtures/ # 测试基础设施 │ ├── auth.fixture.ts # 认证 fixture(增强现有) │ ├── api-client.ts # API 数据准备/清理客户端 │ └── test-data.ts # 测试数据工厂函数 ├── pages/ # 轻量 Page Object(仅关键页面) │ ├── login.page.ts │ ├── patient-list.page.ts │ ├── patient-detail.page.ts │ ├── appointment.page.ts │ └── health-data.page.ts └── playwright.config.ts # 增强配置 apps/miniprogram/e2e/ # 小程序端 E2E(MCP 自动化) ├── flows/ # 业务链路测试 │ ├── patient-health-view.spec.ts # 患者查看健康数据 │ ├── vital-signs-input.spec.ts # 体征录入 │ ├── points-flow.spec.ts # 积分签到兑换 │ └── mall-flow.spec.ts # 积分商城 ├── helpers/ # MCP 封装 │ ├── mcp-client.ts # MCP 工具调用封装 │ ├── auth.helper.ts # 小程序登录/Token 注入 │ └── navigation.helper.ts # 页面导航封装 ├── check-readiness.ts # 环境就绪检查 └── vitest.config.ts # 测试运行器配置 ``` ### 关键原则 1. 现有 4 个 smoke test 原地迁移到 `smoke/` 目录,逻辑不变 2. Web 端保持 Playwright,小程序端用 Vitest + `miniprogram-automator`,各自独立运行 3. 两端 API client 逻辑保持一致但代码各自维护(Web 运行在 Node,小程序也运行在 Node,可考虑后续抽取共享包) 4. Page Object 只封装关键页面,随访/告警等简单页面直接在 spec 中操作 5. 每条链路自包含(API 准备所需数据),不依赖其他链路的执行顺序 6. 所有 Page Object 使用 Hash Router 路径格式(`/#/health/patients`) ## §2 关键业务链路定义 ### Web 端链路(5 条) **Flow 1: 患者全流程 `patient-journey.spec.ts`** ``` 登录 → 患者列表页 → 创建患者 → 查看患者详情 → 编辑患者信息 → 分配医生 → 添加家族成员 → 删除测试数据 ``` 验证点:患者 CRUD、详情页数据完整性、医生关联、家族成员管理 **Flow 2: 体征数据链路 `vital-signs-flow.spec.ts`** ``` 登录 → 选择患者 → 录入体征数据(血压/心率/血糖) → 查看体征列表 → 查看趋势图 → 录入化验报告 → 审核报告 → 清理数据 ``` 验证点:体征录入表单、列表展示、趋势图表渲染、化验报告上传与审核 **Flow 3: 预约排班链路 `appointment-flow.spec.ts`** ``` 登录 → 创建医生 → 设置排班 → 患者列表 → 创建预约 → 查看预约列表 → 更新预约状态 → 清理数据 ``` 验证点:排班日历交互、预约创建、状态流转(待确认→已确认→已完成) **Flow 4: 随访管理链路 `follow-up-flow.spec.ts`** ``` 登录 → 创建随访模板 → 批量创建随访任务 → 查看任务列表 → 完成随访(填写记录)→ 查看随访记录 → 清理数据 ``` 验证点:模板管理、批量操作、任务分配、随访记录填写 **Flow 5: 告警处理链路 `alert-flow.spec.ts`** ``` 登录(API) → 创建告警规则(低阈值,如心率 > 50) → 录入触发体征数据(API 创建心率为 110 的体征)→ 轮询等待告警生成(最多 10s) → 查看告警列表(UI)→ 确认告警 → 处理告警 → 查看告警规则 → 停用规则 → 清理数据(规则 + 体征 + 告警) ``` 验证点:告警规则配置、告警自动生成、列表/仪表盘展示、状态流转(待处理→已确认→已处理) **异步处理说明:** 告警由后台任务根据规则匹配体征数据自动生成。测试通过 API 创建低阈值规则 + 触发数据,然后轮询告警列表 API 等待告警出现(`await expect.poll(() => api.getAlerts(), { timeout: 10_000 })`)。 ### 小程序端链路(4 条) **Flow 6: 患者健康数据查看 `patient-health-view.spec.ts`** ``` MCP 登录 → 首页 → 查看今日体征摘要 → 查看体征趋势 → 查看随访任务列表 → 查看化验报告 ``` **Flow 7: 体征数据录入 `vital-signs-input.spec.ts`** ``` MCP 登录 → 进入录入页 → 填写血压/心率 → 提交 → 验证数据出现在列表 → 清理数据 ``` **Flow 8: 积分签到兑换 `points-flow.spec.ts`** ``` MCP 登录 → 每日签到 → 查看积分余额 → 浏览商品 → 兑换商品 → 查看订单列表 ``` **Flow 9: 积分商城 `mall-flow.spec.ts`** ``` MCP 登录 → 商城首页 → 浏览商品分类 → 查看商品详情 → 查看线下活动 → 活动报名 ``` ### 链路覆盖矩阵 | 业务模块 | Web 链路 | 小程序链路 | API 链路(已有) | |---------|---------|-----------|---------------| | 患者管理 | Flow 1 | — | Chain 1 | | 体征/健康数据 | Flow 2 | Flow 6, 7 | Chain 1, 2 | | 预约排班 | Flow 3 | — | Chain 1 | | 随访管理 | Flow 4 | Flow 6 | Chain 1 | | 告警系统 | Flow 5 | — | — | | 积分体系 | — | Flow 8 | Chain 4 | | 积分商城 | — | Flow 9 | Chain 4 | 未覆盖模块说明: - **咨询管理**(2 页面)— 有完整 API 链路,但实时消息交互难以用 E2E 验证,建议 API 集成测试覆盖 - **内容/文章管理**(4 页面)— CRUD 操作较标准,优先级低于核心医疗流程 - **AI 分析**(3 页面)— 依赖外部 AI 服务,不稳定,建议 mock 测试 - **统计仪表盘**(5 页面)— 数据聚合展示,E2E 价值有限,建议视觉回归测试 ## §3 测试数据策略与 API Client ### 核心原则 API 驱动自建自毁:每个测试通过 API 创建所需数据,测试结束后清理。不依赖数据库预置状态。 ### API Client 后端所有实体使用乐观锁(`version` 字段),更新/删除操作必须携带 version。API Client 的所有方法返回完整实体(含 version),清理操作使用返回的 version。 ```typescript // fixtures/api-client.ts interface VersionedEntity { id: string; version: number } class ApiClient { private token: string; private baseUrl: string; // 认证 async login(username: string, password: string): Promise async loginAsAdmin(): Promise // 患者数据工厂 — 返回含 version 的完整实体 async createPatient(overrides?: Partial): Promise async updatePatient(id: string, version: number, data: Partial): Promise async deletePatient(id: string, version: number): Promise // 医生数据工厂 async createDoctor(overrides?: Partial): Promise async deleteDoctor(id: string, version: number): Promise // 体征数据工厂 async createVitalSigns(patientId: string, overrides?: Partial): Promise async deleteVitalSigns(patientId: string, id: string, version: number): Promise // 预约数据工厂 async createAppointment(overrides?: Partial): Promise async updateAppointmentStatus(id: string, version: number, status: string): Promise async deleteAppointment(id: string, version: number): Promise // 随访数据工厂 async createFollowUpTemplate(overrides?: Partial): Promise