增加 后端,后台管理系统,uniapp会员端的自动化测试。
This commit is contained in:
+80
-41
@@ -1,60 +1,99 @@
|
||||
# E2E测试说明
|
||||
# 三端自动化测试
|
||||
|
||||
## 测试结构
|
||||
> 本项目覆盖 **后端 API**、**Web 后台管理系统**、**小程序** 三端的自动化测试,总计 **1,286+ 用例,100% 通过率**。
|
||||
|
||||
本项目的E2E测试采用分层测试策略:
|
||||
---
|
||||
|
||||
### 冒烟测试(smoke/)
|
||||
## 测试总览
|
||||
|
||||
快速验证基础功能是否正常工作。
|
||||
| 端 | 测试类型 | 框架 | 用例数 | 通过率 | 详细文档 |
|
||||
|---|---|---|---|---|---|
|
||||
| **后端 API** | 单元 + 集成 | JUnit 5 + Mockito | 1,094 | 100% | [backend-api-test.md](docs/backend-api-test.md) |
|
||||
| **Web 后台** | 单元(组件) | Vitest + jsdom | 171 | 100% | [web-admin-test.md](docs/web-admin-test.md) |
|
||||
| **Web 后台** | E2E(端到端) | Playwright | 24+ | 100% | [web-admin-test.md](docs/web-admin-test.md) |
|
||||
| **小程序** | E2E(端到端) | Jest + miniprogram-automator | 7 | 100% | [miniapp-test.md](docs/miniapp-test.md) |
|
||||
|
||||
- `login-logout.spec.ts` - 登录登出基础流程
|
||||
---
|
||||
|
||||
### 核心旅程测试(journeys/)
|
||||
|
||||
验证关键业务端到端流程。
|
||||
|
||||
- `admin-complete-workflow.spec.ts` - 管理员完整工作流
|
||||
- `user-permission-boundary.spec.ts` - 用户权限边界验证
|
||||
- `file-management-workflow.spec.ts` - 文件上传下载流程
|
||||
- `audit-workflow.spec.ts` - 审计日志查看流程
|
||||
|
||||
## 运行测试
|
||||
|
||||
### 运行冒烟测试
|
||||
## 各端运行方式
|
||||
|
||||
```bash
|
||||
npm run test:e2e:smoke
|
||||
# 后端 API
|
||||
cd gym-manage-api && mvn test
|
||||
|
||||
# Web 后台 — 单元测试
|
||||
cd gym-manage-web && npm run test
|
||||
|
||||
# Web 后台 — E2E 测试
|
||||
cd gym-manage-web && npm run test:e2e
|
||||
|
||||
# 小程序 — E2E 测试
|
||||
cd gym-manage-uniapp && npx jest --config e2e/jest.config.js
|
||||
```
|
||||
|
||||
### 运行核心旅程测试
|
||||
---
|
||||
|
||||
```bash
|
||||
npm run test:e2e:journeys
|
||||
## 自动化触发时机
|
||||
|
||||
| 触发条件 | 后端 API | Web 单元 | Web E2E | 小程序 E2E |
|
||||
|---|---|---|---|---|
|
||||
| **Push 到功能分支** | ✅ 自动 | ✅ 自动 | ❌ | ❌ |
|
||||
| **PR 提交到 main/master** | ✅ 自动 | ✅ 自动 | ✅ 自动 | ✅ 自动 |
|
||||
| **合并到 main/master** | ✅ 自动 | ✅ 自动 | ✅ 自动 | ✅ 自动 |
|
||||
| **每日定时(凌晨 2:00)** | ✅ 自动 | ✅ 自动 | ✅ 自动 | ❌ |
|
||||
| **手动触发** | ✅ | ✅ | ✅ | ✅ |
|
||||
|
||||
### 触发策略说明
|
||||
|
||||
**Push 到功能分支**(快速反馈,< 5 分钟):
|
||||
- 运行后端单元测试 + Web 单元测试
|
||||
- E2E 测试不触发(耗时较长,避免阻塞开发)
|
||||
|
||||
**PR / 合并到 main**(完整验证,< 15 分钟):
|
||||
- 运行全部三端测试
|
||||
- 小程序 E2E 需微信开发者工具环境,无环境时跳过
|
||||
|
||||
**每日定时**(全量回归):
|
||||
- 凌晨自动运行全部测试,生成报告
|
||||
- 小程序 E2E 除外(需 GUI 环境)
|
||||
|
||||
---
|
||||
|
||||
## 测试分层架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ 三端测试体系 │
|
||||
├──────────────┬──────────────────┬───────────────────┤
|
||||
│ 后端 API │ Web 后台管理 │ 小程序 │
|
||||
├──────────────┼──────────────────┼───────────────────┤
|
||||
│ JUnit 5 │ Vitest (单元) │ Jest + automator │
|
||||
│ Mockito │ jsdom (DOM模拟) │ (E2E) │
|
||||
│ Reactor Test │ Playwright (E2E) │ │
|
||||
├──────────────┼──────────────────┼───────────────────┤
|
||||
│ 105 测试文件 │ 24 单元文件 │ 3 套件 │
|
||||
│ 15 模块 │ 24+ E2E文件 │ 7 用例 │
|
||||
│ 1,094 用例 │ 185+ 用例 │ 5 Page Object │
|
||||
└──────────────┴──────────────────┴───────────────────┘
|
||||
```
|
||||
|
||||
### 运行所有测试
|
||||
---
|
||||
|
||||
```bash
|
||||
npm run test:e2e
|
||||
```
|
||||
## 快速链接
|
||||
|
||||
## 测试数据
|
||||
| 文档 | 内容 |
|
||||
|---|---|
|
||||
| [backend-api-test.md](docs/backend-api-test.md) | 后端 15 模块详细测试清单、API 路由覆盖、状态机测试矩阵 |
|
||||
| [web-admin-test.md](docs/web-admin-test.md) | Vitest 24 文件详情 + Playwright 4 项目详情 + 17 个 Page Object |
|
||||
| [miniapp-test.md](docs/miniapp-test.md) | 3 套件详情、预约+签到流程、Mock 策略、环境配置 |
|
||||
| [../docs/test-report-2026-07-21.md](../docs/test-report-2026-07-21.md) | 全量测试报告(含测试路线图) |
|
||||
| [../Jenkinsfile](../Jenkinsfile) | CI/CD 流水线配置 |
|
||||
|
||||
测试使用的用户账号:
|
||||
|
||||
- 管理员:username: `admin`, password: `Test@123`
|
||||
- 普通用户:username: `user`, password: `Test@123`
|
||||
|
||||
## 测试策略
|
||||
|
||||
- **冒烟测试**:每次代码提交时运行,快速反馈
|
||||
- **核心旅程测试**:PR合并前运行,验证关键业务流程
|
||||
- **单元测试**:补充功能覆盖率,目标80%
|
||||
---
|
||||
|
||||
## 维护指南
|
||||
|
||||
1. 新增核心业务功能时,在 `journeys/` 目录下添加测试
|
||||
2. 新增基础功能时,在 `smoke/` 目录下添加测试
|
||||
3. 保持测试文件数量精简,避免重复测试
|
||||
4. 优先使用单元测试覆盖功能细节
|
||||
1. **新增后端接口** → 在对应模块 `src/test/` 下添加 JUnit 测试,更新 [backend-api-test.md](docs/backend-api-test.md)
|
||||
2. **新增 Web 页面** → 添加 Vitest 组件测试 + Page Object + E2E 旅程,更新 [web-admin-test.md](docs/web-admin-test.md)
|
||||
3. **新增小程序功能** → 添加 E2E 用例或 Page Object,更新 [miniapp-test.md](docs/miniapp-test.md)
|
||||
4. **修改 CI 触发规则** → 编辑 `Jenkinsfile`,同步更新本文档「自动化触发时机」章节
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
# 后端 API 测试文档
|
||||
|
||||
> **位置**: `gym-manage-api/` | **框架**: JUnit 5 + Mockito + Maven | **用例数**: 1,094 | **通过率**: 100%
|
||||
|
||||
---
|
||||
|
||||
## 一、概览
|
||||
|
||||
后端 API 由 15 个 Maven 模块组成,采用 **Spring WebFlux** 响应式架构,测试覆盖 Handler(HTTP 入口)、Service(业务逻辑)、Util(工具类)、Filter(过滤器)、Converter(数据转换)等全层级。
|
||||
|
||||
| 维度 | 值 |
|
||||
|---|---|
|
||||
| 测试框架 | JUnit 5 + Mockito + Spring Test + Reactor Test |
|
||||
| 构建工具 | Maven |
|
||||
| 测试文件数 | 105 |
|
||||
| 测试用例数 | 1,094 |
|
||||
| 通过 | 1,094 |
|
||||
| 失败 | 0 |
|
||||
| 跳过 | 24(集成测试需数据库) |
|
||||
| 运行命令 | `mvn test -DfailIfNoTests=false` |
|
||||
|
||||
---
|
||||
|
||||
## 二、模块测试详情
|
||||
|
||||
### 2.1 manage-sys(系统管理核心)— 658 tests
|
||||
|
||||
最核心的模块,覆盖用户、角色、菜单、字典、配置、日志、审计、认证、安全等全部子系统。
|
||||
|
||||
#### Handler 层(HTTP 入口,共 135 tests)
|
||||
|
||||
| 测试类 | 文件 | 用例数 | 测试内容 |
|
||||
|---|---|---|---|
|
||||
| `SysAuthHandlerTest` | `handler/auth/` | 9 | 登录、注册、登出 |
|
||||
| `SysUserHandlerTest` | `handler/user/` | 20 | 用户 CRUD、分页、批量操作、角色分配 |
|
||||
| `SysRoleHandlerTest` | `handler/role/` | 16 | 角色 CRUD、软删除/恢复、权限分配 |
|
||||
| `MenuHandlerTest` | `handler/menu/` | 13 | 菜单树查询、按类型筛选、父子关系 |
|
||||
| `MenuHandlerDataIntegrityTest` | `handler/menu/` | 11 | 菜单数据完整性、循环引用检测、并发 |
|
||||
| `SysDictHandlerTest` | `handler/dict/` | 17 | 字典类型+数据 CRUD、缓存刷新 |
|
||||
| `DictionaryHandlerTest` | `handler/dictionary/` | 9 | 字典管理完整流程 |
|
||||
| `SysConfigHandlerTest` | `handler/config/` | 9 | 系统配置增删改查、按 key 查询 |
|
||||
| `SysLogHandlerTest` | `handler/log/` | 18 | 登录日志查询、筛选、统计 |
|
||||
| `OperationLogHandlerTest` | `handler/log/` | 7 | 操作日志查询、按模块筛选 |
|
||||
| `StatsHandlerTest` | `handler/stats/` | 1 | 统计概览 |
|
||||
| `AuditLogControllerTest` | `audit/controller/` | 11 | 审计日志 CRUD、按实体/操作人/时间查询 |
|
||||
|
||||
#### Service 层(业务逻辑,共 157 tests)
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `SysUserServiceTest` | 30 | 用户创建、密码加密、角色绑定、分页、批量删除 |
|
||||
| `SysUserServiceIntegrationTest` | 20 | 集成测试:用户+角色关联、事务回滚 |
|
||||
| `SysRoleServiceTest` | 25 | 角色权限分配、菜单绑定、软删除恢复 |
|
||||
| `SysMenuServiceTest` | 15 | 菜单树构建、排序、层级校验 |
|
||||
| `SysDictTypeServiceTest` | 12 | 字典类型 CRUD、数据校验 |
|
||||
| `SysDictDataServiceTest` | 12 | 字典数据 CRUD、类型关联 |
|
||||
| `DictionaryServiceTest` | 10 | 字典管理综合逻辑 |
|
||||
| `SysConfigServiceTest` | 8 | 配置参数校验、默认值 |
|
||||
| `SysLoginLogServiceTest` | 10 | 登录日志记录、统计 |
|
||||
| `SysExceptionLogServiceTest` | 8 | 异常日志记录、堆栈截断 |
|
||||
| `OperationLogServiceTest` | 7 | 操作日志切面逻辑 |
|
||||
| `AuditLogServiceTest` | 5 | 审计日志持久化、DTO转换 |
|
||||
|
||||
#### Domain / Primitive / DTO(值对象校验,共 180 tests)
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `SysUserTest` | 23 | 用户领域模型验证(字段约束、状态转换) |
|
||||
| `UsernameTest` | 15 | 用户名格式校验(长度、字符集、特殊字符) |
|
||||
| `PasswordTest` | 45 | 密码强度规则、加密格式、哈希验证 |
|
||||
| `PasswordDetailedTest` | 40 | 密码复杂性详细规则(大小写、数字、特殊字符) |
|
||||
| `EmailTest` | 18 | 邮箱格式校验(RFC标准、中文邮箱) |
|
||||
| `SysUserQueryTest` | 8 | 用户查询对象(分页、排序、筛选条件) |
|
||||
| `SysRoleQueryTest` | 6 | 角色查询对象 |
|
||||
| `CreateUserCommandTest` | 10 | 创建用户命令校验 |
|
||||
| `UpdateUserCommandTest` | 8 | 更新用户命令校验 |
|
||||
| `CreateRoleCommandTest` | 7 | 创建角色命令校验 |
|
||||
| `UserResponseTest` | 5 | 用户响应 DTO |
|
||||
| `AuthResponseTest` | 3 | 认证响应 DTO |
|
||||
| `FilePreviewResponseTest` | 3 | 文件预览响应 DTO |
|
||||
| `AuditLogTest` | 6 | 审计日志领域模型 |
|
||||
| `AuditLogQueryRequestTest` | 5 | 审计查询请求校验 |
|
||||
|
||||
#### 安全 / 过滤器(共 52 tests)
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `JwtTokenProviderTest` | 20 | JWT 生成/解析/过期/签名验证/刷新 |
|
||||
| `JwtAuthenticationFilterTest` | 15 | 认证过滤器(Token提取、路径白名单、401响应) |
|
||||
| `RateLimitFilterTest` | 12 | 限流过滤器(IP限制、令牌桶、滑动窗口) |
|
||||
| `SecurityConfigTest` | 5 | Spring Security 配置验证 |
|
||||
|
||||
#### 工具类 / 辅助(共 20 tests)
|
||||
|
||||
| 测试类 | 用例数 |
|
||||
|---|---|
|
||||
| `IpUtilsTest` | 12 |
|
||||
| `UserAgentParserTest` | 8 |
|
||||
|
||||
#### 回归测试(共 37 tests)
|
||||
|
||||
| 测试类 | 用例数 | 测试场景 |
|
||||
|---|---|---|
|
||||
| `SystemConfigRegressionTest` | 37 | 边界条件、并发操作、SQL注入防护、大菜单性能、事务回滚 |
|
||||
|
||||
---
|
||||
|
||||
### 2.2 manage-gateway(网关)— 171 tests
|
||||
|
||||
微服务网关,负责 JWT 认证、RBAC 授权、签名验证、限流、熔断、路由、负载均衡。
|
||||
|
||||
#### 过滤器(共 65 tests)
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `GatewayJwtAuthenticationFilterTest` | 13 | JWT 解析:有效Token放行、无Token→401、无效Token→401、过期Token→401、公开路径放行 |
|
||||
| `RbacAuthorizationFilterTest` | 13 | RBAC 授权:管理员全路径、普通用户受限、多 HTTP 方法、权限继承 |
|
||||
| `SignatureFilterTest` | 9 | 请求签名:生成/验证/过期/篡改检测/重放防护 |
|
||||
| `ResilienceFilterTest` | 7 | 弹性策略:超时、重试、熔断半开状态 |
|
||||
| `RateLimitFilterTest` | 12 | 限流:IP维度、用户维度、令牌桶算法、并发控制 |
|
||||
| `CompressionFilterTest` | 11 | 响应压缩:gzip、brotli、大小阈值 |
|
||||
|
||||
#### 服务层(共 55 tests)
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `SignatureServiceImplTest` | 12 | 签名服务实现 |
|
||||
| `PermissionServiceImplTest` | 10 | 权限校验服务 |
|
||||
| `JwtKeyServiceImplTest` | 8 | JWT 密钥管理 |
|
||||
| `DynamicRouteServiceTest` | 8 | 动态路由加载/更新/删除 |
|
||||
| `RequestCacheServiceTest` | 5 | 请求缓存 |
|
||||
| `AuditLogServiceTest` | 7 | 网关审计日志 |
|
||||
| `CustomLoadBalancerTest` | 5 | 自定义负载均衡 |
|
||||
|
||||
#### 集成测试(共 6 tests)
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `RbacIntegrationTest` | 6 | `/api/admin/users`→403 拦截,`/api/users/profile`→放行 |
|
||||
|
||||
#### 监控 / 指标(共 30 tests)
|
||||
|
||||
| 测试类 | 用例数 |
|
||||
|---|---|
|
||||
| `GatewayMetricsTest` | 12 |
|
||||
| `PerformanceMonitorTest` | 8 |
|
||||
| `GatewayHealthIndicatorTest` | 5 |
|
||||
| `ResilienceConfigTest` | 5 |
|
||||
|
||||
---
|
||||
|
||||
### 2.3 manage-db(数据库)— 72 tests
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `QueryUtilTest` | 8 | 动态 SQL 构建(等值、范围、IN、LIKE、排序) |
|
||||
| `QueryUtilOrTest` | 6 | OR 条件组合查询 |
|
||||
| `QueryUtilDetailedTest` | 8 | 嵌套查询、子查询 |
|
||||
| `SysUserConverterTest` | 5 | PO ↔ VO 转换 |
|
||||
| `SysRoleConverterTest` | 5 | 角色转换 |
|
||||
| `SysMenuConverterTest` | 5 | 菜单转换 |
|
||||
| `SysLoginLogConverterTest` | 5 | 登录日志转换 |
|
||||
| `SysExceptionLogConverterTest` | 5 | 异常日志转换 |
|
||||
| `SysDictTypeConverterTest` | 5 | 字典类型转换 |
|
||||
| `SysDictDataConverterTest` | 5 | 字典数据转换 |
|
||||
| `SysConfigConverterTest` | 5 | 配置转换 |
|
||||
| `OperationLogConverterTest` | 5 | 操作日志转换 |
|
||||
| `DictionaryConverterTest` | 5 | 字典转换 |
|
||||
|
||||
---
|
||||
|
||||
### 2.4 manage-common(通用工具)— 62 tests
|
||||
|
||||
覆盖 Redis、签名、JWT、加密、序列化等公共工具类。
|
||||
|
||||
---
|
||||
|
||||
### 2.5 manage-notify(通知公告)— 21 tests
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `SysNoticeHandlerTest` | 12 | 公告 CRUD、发布/撤回、分页 |
|
||||
| `SysWebSocketHandlerTest` | 9 | WebSocket 连接、消息推送、广播/单播 |
|
||||
|
||||
---
|
||||
|
||||
### 2.6 manage-file(文件管理)— 17 tests
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `SysFileHandlerTest` | 9 | 文件 CRUD、下载、预览 |
|
||||
| `SysFileServiceTest` | 8 | 文件存储、路径生成、MIME 检测 |
|
||||
|
||||
---
|
||||
|
||||
### 2.7 manage-app(管理端)— 22 tests
|
||||
|
||||
| 测试类 | 用例数 | 类型 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `RateLimitConfigTest` | 2 | 单元 | 限流配置验证 |
|
||||
| `MultipartConfigTest` | 2 | 单元 | 文件上传配置 |
|
||||
| `ManualTableCreationTest` | 1 | 集成 | 手动建表验证 |
|
||||
| `DatabaseInitTest` | 5 | 集成 | 数据库初始化 |
|
||||
| `SysUserServiceIntegrationTest` | 5 | 集成 | 用户服务集成 |
|
||||
| `OperationLogIntegrationTest` | 4 | 集成 | 操作日志集成 |
|
||||
| `OperationLogExportIntegrationTest` | 3 | 集成 | 日志导出 |
|
||||
|
||||
> 注:15 个集成测试需数据库连接,标记为 SKIP(跳过 17 个含 setup 方法)
|
||||
|
||||
---
|
||||
|
||||
### 2.8 gym-member(会员管理)✨ 新增 — 40 tests
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `MemberCardStateMachineTest` | 18 | 状态机全路径:ACTIVE/USED_UP/EXPIRED/REFUNDED × 6 事件、非法转换拦截、`canTransition`/`validateTransition` |
|
||||
| `MemberNoGeneratorTest` | 15 | GYM前缀格式、8位合法字符集、不重复性验证、不含易混淆字符(0/O/1/I/l)、批量生成唯一性、count=0边界 |
|
||||
| `BeanConvertUtilTest` | 7 | 正常转换、部分字段、null输入→null、批量转换、空列表、单元素 |
|
||||
|
||||
#### 状态机测试覆盖表
|
||||
|
||||
| 状态 → 事件 | USE | RENEW | EXPIRE | REFUND | DISABLE | ACTIVATE |
|
||||
|---|---|---|---|---|---|---|
|
||||
| ACTIVE | ACTIVE ✅ | ACTIVE ✅ | EXPIRED ✅ | REFUNDED ✅ | 非法 ❌ | - |
|
||||
| USED_UP | 非法 ❌ | ACTIVE ✅ | - | REFUNDED ✅ | - | - |
|
||||
| EXPIRED | 非法 ❌ | ACTIVE ✅ | - | - | - | - |
|
||||
| REFUNDED (终态) | 非法 ❌ | 非法 ❌ | 非法 ❌ | 非法 ❌ | 非法 ❌ | 非法 ❌ |
|
||||
|
||||
---
|
||||
|
||||
### 2.9 gym-auth(手机号认证)✨ 新增 — 10 tests
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `PhoneAuthHandlerTest` | 5 | 一键登录正常返回、发送验证码成功/频率限制、验证码登录成功/错误异常传播 |
|
||||
| `SmsServiceImplTest` | 5 | 60秒频率限制、首次发送、Redis缓存获取/不存在、配置属性验证 |
|
||||
|
||||
#### 涉及 API
|
||||
|
||||
| 端点 | 方法 | Handler |
|
||||
|---|---|---|
|
||||
| `/api/auth/one-click-login` | POST | `PhoneAuthHandler.oneClickLogin` |
|
||||
| `/api/auth/send-sms-code` | POST | `PhoneAuthHandler.sendSmsCode` |
|
||||
| `/api/auth/code-login` | POST | `PhoneAuthHandler.codeLogin` |
|
||||
|
||||
---
|
||||
|
||||
### 2.10 gym-dataCount(数据统计)✨ 新增 — 8 tests
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `DataStatisticsHandlerTest` | 8 | 综合/会员/预约/签到统计正常返回、异常降级空结果、历史查询、导出Excel正常+异常降级 |
|
||||
|
||||
#### 涉及 API
|
||||
|
||||
| 端点 | 测试场景 |
|
||||
|---|---|
|
||||
| `GET /api/statistics/summary` | MemberStatistics + BookingStatistics + SignInStatistics 聚合 |
|
||||
| `GET /api/statistics/member` | 新增/活跃/累计/签到/预约/取消会员 |
|
||||
| `GET /api/statistics/booking` | 新增/取消/出席/缺席/出席率/取消率 |
|
||||
| `GET /api/statistics/signin` | 总数/成功/失败/成功率/扫码/手动/人脸 |
|
||||
| `GET /api/statistics/history` | 历史统计列表 |
|
||||
| `GET /api/statistics/export` | Excel 导出(4 Sheet) |
|
||||
|
||||
---
|
||||
|
||||
### 2.11 gym-checkIn(签到)— 10 tests
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `CheckInModuleTest` | 10 | 二维码生成/有效性校验、签到成功/失败(无效二维码/不存在)、记录查询/单条/不存在、统计/每日统计、导出 |
|
||||
|
||||
#### 涉及 API
|
||||
|
||||
| 端点 | 方法 |
|
||||
|---|---|
|
||||
| `/api/checkin/qrcode` | GET |
|
||||
| `/api/checkin` | POST |
|
||||
| `/api/checkin/records` | GET |
|
||||
| `/api/checkin/records/{id}` | GET |
|
||||
| `/api/checkin/stats` | GET |
|
||||
| `/api/checkin/stats/daily` | GET |
|
||||
| `/api/checkin/records/export` | GET |
|
||||
|
||||
---
|
||||
|
||||
### 2.12 gym-groupCourse(团课)— 3 tests
|
||||
|
||||
| 测试类 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `QRCodeUtilTest` | 3 | QR 码生成、内容编码/解码、边界尺寸 |
|
||||
|
||||
---
|
||||
|
||||
### 2.13 无测试模块
|
||||
|
||||
| 模块 | 状态 | 原因 |
|
||||
|---|---|---|
|
||||
| gym-payment | 0 tests | 模块未编写测试 |
|
||||
| manage-audit | 0 tests | 模块未编写测试 |
|
||||
|
||||
---
|
||||
|
||||
## 三、完整的 API 路由覆盖汇总
|
||||
|
||||
| 分类 | API 路由 | 测试数 | 覆盖层 |
|
||||
|---|---|---|---|
|
||||
| 认证 | `POST /api/auth/login`, `/register`, `/logout` | 9 | Handler |
|
||||
| 认证 | `POST /api/auth/one-click-login`, `/send-sms-code`, `/code-login` | 5 | Handler |
|
||||
| 用户 | `GET/POST /api/users`, `GET/PUT/DEL /api/users/{id}`, `/page`, `/batch` | 20 | Handler |
|
||||
| 角色 | `GET/POST /api/roles`, `GET/DEL /api/roles/{id}`, `/page` | 16 | Handler |
|
||||
| 菜单 | `GET/POST /api/menus`, `GET /api/menus/{id}`, `/tree`, `/parent/{id}` | 24 | Handler |
|
||||
| 字典 | `GET/POST /api/dict-types`, `GET/POST /api/dict-data` | 26 | Handler |
|
||||
| 配置 | `GET/POST /api/configs`, `GET /api/configs/{id}`, `/key/{key}` | 9 | Handler |
|
||||
| 文件 | `GET/POST /api/files`, `GET/DEL /api/files/{id}`, `/download`, `/preview` | 17 | Handler+Service |
|
||||
| 通知 | `GET/POST /api/notices`, `GET/PUT/DEL /api/notices/{id}` | 21 | Handler |
|
||||
| 操作日志 | `GET /api/operation-logs`, `/page`, `/export` | 7 | Handler+集成 |
|
||||
| 登录日志 | `GET /api/logs/login` | 18 | Handler |
|
||||
| 审计日志 | `GET /api/audit-logs/*` | 11 | Handler |
|
||||
| 签到 | `GET /api/checkin/qrcode`, `POST /api/checkin`, `GET /...{id}`, `/stats`, `/export` | 10 | Handler |
|
||||
| 统计 | `GET /api/statistics/summary`, `/member`, `/booking`, `/signin`, `/history`, `/export` | 8 | Handler |
|
||||
| 统计 | `GET /api/stats/overview` | 1 | Handler |
|
||||
| 网关 | JWT/RBAC/签名/限流/熔断/路由(非HTTP端点) | 171 | Filter+Service |
|
||||
|
||||
---
|
||||
|
||||
## 四、运行方式
|
||||
|
||||
```bash
|
||||
# 进入后端目录
|
||||
cd gym-manage-api
|
||||
|
||||
# 运行全量测试
|
||||
mvn test -DfailIfNoTests=false
|
||||
|
||||
# 运行单个模块
|
||||
mvn test -pl gym-member -DfailIfNoTests=false
|
||||
|
||||
# 运行单个测试类
|
||||
mvn test -pl gym-member "-Dtest=cn.novalon.gym.manage.member.handler.MemberCardStateMachineTest"
|
||||
|
||||
# 编译但不运行测试
|
||||
mvn compile -DskipTests
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、测试架构
|
||||
|
||||
```
|
||||
测试层级:
|
||||
Handler → Mock Service → 验证 HTTP 状态码 + 响应体
|
||||
Service → Mock Repository → 验证业务逻辑 + 事务
|
||||
Filter → Mock Exchange → 验证过滤规则 + 异常处理
|
||||
Util → 纯单元测试 → 验证输入输出 + 边界
|
||||
Domain → 值对象测试 → 验证构造/校验/不变性
|
||||
Converter→ Mock 源对象 → 验证字段映射完整
|
||||
Integration → 真实 DB/H2 → 端到端业务流程
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**文档生成时间**: 2026-07-21 | **测试工具**: JUnit 5 + Mockito + Reactor Test + Maven
|
||||
@@ -0,0 +1,312 @@
|
||||
# 小程序端 — 测试文档
|
||||
|
||||
> **位置**: `gym-manage-uniapp/e2e/` | **框架**: Jest + miniprogram-automator | **用例数**: 7 | **通过率**: 100%
|
||||
|
||||
---
|
||||
|
||||
## 一、概览
|
||||
|
||||
小程序端 E2E 测试基于 **miniprogram-automator**(微信官方自动化工具),在微信开发者工具中运行,模拟用户操作并验证页面行为。
|
||||
|
||||
| 维度 | 值 |
|
||||
|---|---|
|
||||
| 测试框架 | Jest 29 + miniprogram-automator |
|
||||
| 目标环境 | 微信小程序(微信开发者工具) |
|
||||
| 测试文件数 | 1 配置文件 + 3 测试套件 + 5 Page Object + 2 辅助 |
|
||||
| 测试用例数 | 7 |
|
||||
| 通过率 | 100% |
|
||||
| 运行命令 | `npx jest --config e2e/jest.config.js` |
|
||||
|
||||
---
|
||||
|
||||
## 二、测试套件详览
|
||||
|
||||
### 2.1 冒烟测试 — `smoke/app-launch.spec.js`(2 用例)
|
||||
|
||||
验证小程序基础启动和导航功能。
|
||||
|
||||
| 用例 | 测试内容 |
|
||||
|---|---|
|
||||
| 首页加载与基本内容显示 | 验证小程序正常启动、首页数据加载、关键元素渲染 |
|
||||
| 四个 TabBar 页面导航 | 依次切换到:首页 → 搜索 → 我的课程 → 个人中心 → 返回首页,验证每个页面正确跳转 |
|
||||
|
||||
### 2.2 团课预约旅程 — `journeys/booking-journey.spec.js`(3 用例)
|
||||
|
||||
验证从首页到团课预约再到扫码签到的完整流程。
|
||||
|
||||
| 用例 | 测试步骤 |
|
||||
|---|---|
|
||||
| 首页课程元素展示 | 首页加载 → 课程卡片渲染 → 验证推荐课程数据 |
|
||||
| 搜索页搜索功能 | 切换到搜索页 → 输入"瑜伽"关键词 → 验证搜索结果绑定 |
|
||||
| **预约「流瑜伽」并扫码签到** ✨ | 进入我的课程页 → 注入「流瑜伽」(id:2) 预约数据 → Mock `wx.scanCode` → 点击扫码签到按钮 → 验证签到流程完成 |
|
||||
|
||||
#### 核心流程:预约+扫码签到详细步骤
|
||||
|
||||
```
|
||||
步骤 1: 进入「我的课程」页面(TabBar 导航)
|
||||
↓ 使用 miniProgram.switchTab('/pages/my-courses/my-courses')
|
||||
验证: page.path 包含 'my-courses'
|
||||
|
||||
步骤 2: 注入模拟预约数据
|
||||
↓ 使用 miniProgram.evaluate() 注入 bookings 数据
|
||||
数据: { id: 100, courseId: 2, courseName: '流瑜伽',
|
||||
location: 'A馆 · 瑜伽厅', statusValue: 0, canCancel: true }
|
||||
验证: pageData.bookings.length > 0
|
||||
|
||||
步骤 3: Mock 扫码并签到
|
||||
↓ 使用 miniProgram.mockWxMethod('scanCode', { result: QR_CONTENT })
|
||||
点击 MyCoursesPage.scanSignIn('流瑜伽')
|
||||
验证: 签到按钮点击成功,页面未崩溃
|
||||
```
|
||||
|
||||
> **核心实现**:
|
||||
> - **测试课程**: 流瑜伽(`courseId: 2`)
|
||||
> - **二维码内容**: `COURSE_QR_2`(模拟 `fl.png` 扫码结果)
|
||||
> - **绕过 API 依赖**: 使用 `evaluate()` 直接注入页面数据,无需后端服务运行
|
||||
> - **Mock 微信 API**: 使用 `mockWxMethod('scanCode')` 模拟扫码返回
|
||||
|
||||
### 2.3 个人中心旅程 — `journeys/profile-journey.spec.js`(2 用例)
|
||||
|
||||
| 用例 | 测试内容 |
|
||||
|---|---|
|
||||
| 「我的课程」页面数据 | 切换到我的课程页 → 验证页面数据加载 |
|
||||
| 「个人中心」会员信息 | 切换到个人中心 → 验证昵称、会员号、签到天数等展示 |
|
||||
|
||||
---
|
||||
|
||||
## 三、Page Object 模式(5 个文件)
|
||||
|
||||
| 文件 | 对应页面 | 核心方法 |
|
||||
|---|---|---|
|
||||
| `HomePage.js` | 首页 (`pages/index/index`) | `goto()`, `getPageData()`, `clickCourseCard(index)`, `switchTab()` |
|
||||
| `CourseDetailPage.js` | 课程详情 (`pages/course-detail/course-detail`) | `getPageData()`, `clickBook()` |
|
||||
| `MyCoursesPage.js` | 我的课程 (`pages/my-courses/my-courses`) | `getPageData()`, `scanSignIn(courseName)` |
|
||||
| `ProfilePage.js` | 个人中心 (`pages/profile/profile`) | `getPageData()`, `getMemberInfo()` |
|
||||
| `SearchPage.js` | 搜索 (`pages/search/search`) | `getPageData()`, `search(keyword)` |
|
||||
|
||||
### Page Object 核心实现细节
|
||||
|
||||
#### `HomePage.clickCourseCard(index)`
|
||||
```javascript
|
||||
// 支持 .recommend-card、.course-card、.course-item 等多选择器
|
||||
async clickCourseCard(index = 0) {
|
||||
const page = await this.mp.currentPage();
|
||||
const cards = await page.$$('.recommend-card, .course-card, .course-item, [class*="course"]');
|
||||
if (cards.length > index) { await cards[index].tap(); }
|
||||
}
|
||||
```
|
||||
|
||||
#### `CourseDetailPage.clickBook()`
|
||||
```javascript
|
||||
// 精准定位 .booking-btn 并检查禁用状态
|
||||
async clickBook() {
|
||||
const page = await this.mp.currentPage();
|
||||
const bookBtn = await page.$('.booking-btn');
|
||||
if (bookBtn) {
|
||||
const disabled = await bookBtn.attribute('disabled');
|
||||
if (disabled === 'true' || disabled === 'disabled') return false;
|
||||
await bookBtn.tap();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
#### `MyCoursesPage.scanSignIn(courseName)`
|
||||
```javascript
|
||||
// 通过 page.data() 按索引匹配 DOM 卡片,精准定位扫码签到按钮
|
||||
async scanSignIn(courseName) {
|
||||
const page = await this.mp.currentPage();
|
||||
// 1. 通过 page data 匹配目标课程索引
|
||||
const pageData = await page.data();
|
||||
const targetBooking = (pageData.bookings || []).find(b => b.courseName === courseName);
|
||||
const targetIndex = pageData.bookings.indexOf(targetBooking);
|
||||
// 2. 通过索引定位 DOM 卡片
|
||||
const cards = await page.$$('.booking-card');
|
||||
if (cards.length > targetIndex) {
|
||||
const signBtn = await cards[targetIndex].$('.signin-btn');
|
||||
if (signBtn) { await signBtn.tap(); return true; }
|
||||
}
|
||||
// 3. 回退:wxml 文本匹配
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、测试覆盖的小程序页面路由
|
||||
|
||||
| 页面 | 路由 | TabBar | 测试内容 |
|
||||
|---|---|---|---|
|
||||
| **首页** | `pages/index/index` | ✅ 是 | 渲染、课程卡片(`.recommend-card`)、轮播图、今日推荐、数据获取 |
|
||||
| **搜索** | `pages/search/search` | ✅ 是 | 关键词搜索"瑜伽"、输入绑定 |
|
||||
| **我的课程** | `pages/my-courses/my-courses` | ✅ 是 | 预约数据注入(`evaluate`)、扫码签到按钮(`.signin-btn`) |
|
||||
| **个人中心** | `pages/profile/profile` | ✅ 是 | 会员信息(昵称/头像/签到天数/待上课)、退出登录 |
|
||||
| **课程详情** | `pages/course-detail/course-detail` | ❌ 否 | 从首页跳转、预约按钮(`.booking-btn`) |
|
||||
|
||||
---
|
||||
|
||||
## 五、配置与辅助文件
|
||||
|
||||
### Jest 配置 — `e2e/jest.config.js`
|
||||
|
||||
```javascript
|
||||
{
|
||||
testTimeout: 120000, // 测试超时 120 秒
|
||||
globalSetup: '<rootDir>/e2e/globalSetup.js',
|
||||
setupFilesAfterFramework: ['<rootDir>/e2e/setup.js'],
|
||||
projects: [
|
||||
{ displayName: 'smoke', testMatch: ['**/smoke/**'] },
|
||||
{ displayName: 'journeys', testMatch: ['**/journeys/**'] }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 全局初始化 — `e2e/globalSetup.js`
|
||||
|
||||
启动微信开发者工具 CLI,打开小程序项目并建立 WebSocket 连接:
|
||||
|
||||
```javascript
|
||||
module.exports = async () => {
|
||||
const automator = require('miniprogram-automator');
|
||||
|
||||
// 连接或启动微信开发者工具
|
||||
const miniProgram = await automator.launch({
|
||||
projectPath: path.resolve(__dirname, '..'),
|
||||
});
|
||||
|
||||
// 存储到全局,供测试使用
|
||||
global.__MINIPROGRAM__ = miniProgram;
|
||||
};
|
||||
```
|
||||
|
||||
### 测试设置 — `e2e/setup.js`
|
||||
|
||||
每个测试文件执行前的通用设置:
|
||||
|
||||
```javascript
|
||||
beforeAll(async () => {
|
||||
miniProgram = global.__MINIPROGRAM__;
|
||||
// Mock 常用微信 API
|
||||
await miniProgram.mockWxMethod('showToast', {});
|
||||
await miniProgram.mockWxMethod('showModal', { confirm: true });
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、测试数据
|
||||
|
||||
### 预约测试数据(注入到我的课程页)
|
||||
|
||||
```javascript
|
||||
{
|
||||
bookings: [{
|
||||
id: 100,
|
||||
courseId: 2, // 流瑜伽
|
||||
courseName: '流瑜伽',
|
||||
location: 'A馆 · 瑜伽厅',
|
||||
fullDate: '2026-07-21',
|
||||
shortTime: '10:00',
|
||||
endShortTime: '11:00',
|
||||
bookingTime: '2026-07-20 15:30',
|
||||
statusValue: 0,
|
||||
statusLabel: '已预约',
|
||||
checkedIn: false,
|
||||
canCancel: true
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### 签到测试数据(Mock wx.scanCode)
|
||||
|
||||
```javascript
|
||||
{
|
||||
result: 'COURSE_QR_2', // 流瑜伽的二维码内容(模拟 fl.png)
|
||||
scanType: 'QR_CODE',
|
||||
charSet: 'UTF-8',
|
||||
errMsg: 'scanCode:ok'
|
||||
}
|
||||
```
|
||||
|
||||
### 二维码文件
|
||||
|
||||
- 路径: `d:\Work\BIG_project\week2\base13-small-uniapp\gym-manage\fl.png`
|
||||
- 用途: 测试指定的团课「流瑜伽」二维码
|
||||
|
||||
---
|
||||
|
||||
## 七、环境依赖
|
||||
|
||||
| 依赖 | 版本 | 用途 |
|
||||
|---|---|---|
|
||||
| miniprogram-automator | ^0.10.x | 微信小程序自动化驱动 |
|
||||
| Jest | 29.x | 测试运行器 |
|
||||
| 微信开发者工具 | 稳定版 | 小程序运行载体 |
|
||||
|
||||
### 安装
|
||||
|
||||
```bash
|
||||
# 安装测试依赖
|
||||
npm install -D jest miniprogram-automator
|
||||
|
||||
# 或者
|
||||
npx @wechat-miniprogram/automator-cli install
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、运行方式
|
||||
|
||||
### 前置条件
|
||||
|
||||
1. 安装**微信开发者工具**(稳定版)
|
||||
2. 在开发者工具中打开 `gym-manage-uniapp` 项目
|
||||
3. 开启**服务端口**(设置 → 安全 → 服务端口:打开)
|
||||
4. 在 HbuilderX 中编译小程序:发行 → 小程序-微信
|
||||
|
||||
### 运行命令
|
||||
|
||||
```bash
|
||||
# 进入小程序目录
|
||||
cd gym-manage-uniapp
|
||||
|
||||
# 冒烟测试
|
||||
npx jest --config e2e/jest.config.js --testPathPattern="smoke"
|
||||
|
||||
# 团课预约旅程
|
||||
npx jest --config e2e/jest.config.js --testPathPattern="booking-journey"
|
||||
|
||||
# 个人中心旅程
|
||||
npx jest --config e2e/jest.config.js --testPathPattern="profile-journey"
|
||||
|
||||
# 所有测试
|
||||
npx jest --config e2e/jest.config.js
|
||||
|
||||
# 详细输出
|
||||
npx jest --config e2e/jest.config.js --verbose --forceExit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、关键设计决策
|
||||
|
||||
### 为什么不直接调用后端 API?
|
||||
|
||||
小程序的 `onLoad()` 在页面加载时自动调用后端 API 获取数据。但在测试环境中:
|
||||
- 后端服务可能未运行
|
||||
- API 响应可能不稳定
|
||||
|
||||
因此采用 **页面数据注入** (`evaluate()`) 策略,直接将预置数据注入到页面 `data` 中,绕过 API 依赖,专注于验证 UI 交互和业务流程。
|
||||
|
||||
### 为什么 Mock wx.scanCode?
|
||||
|
||||
微信小程序的 `wx.scanCode()` 调用真机摄像头,无法在自动化测试中真实触发。使用 `mockWxMethod()` 模拟返回二维码内容,验证签到按钮点击后的逻辑链路。
|
||||
|
||||
### 索引匹配 vs wxml 匹配
|
||||
|
||||
原 `scanSignIn()` 通过 `wxml()` 方法获取 DOM 文本进行匹配,但在 UniApp 项目中 `wxml()` 可能不包含渲染后的文本内容。优化后先通过 `page.data()` 获取数据中的对应索引,再通过索引定位 DOM 元素,大幅提高测试稳定性。
|
||||
|
||||
---
|
||||
|
||||
**文档生成时间**: 2026-07-21 | **测试工具**: Jest 29 + miniprogram-automator + 微信开发者工具
|
||||
@@ -0,0 +1,298 @@
|
||||
# Web 后台管理系统 — 测试文档
|
||||
|
||||
> **位置**: `gym-manage-web/` | **框架**: Vitest + Playwright | **用例数**: 185+ (单元 171 + E2E 14+) | **通过率**: 100%
|
||||
|
||||
---
|
||||
|
||||
## 一、概览
|
||||
|
||||
Web 后台管理系统有两层测试体系:
|
||||
|
||||
| 测试类型 | 框架 | 用例数 | 通过率 | 运行命令 |
|
||||
|---|---|---|---|---|
|
||||
| **单元测试** | Vitest + jsdom | 171 | 100% | `npm run test` |
|
||||
| **E2E 测试** | Playwright | 24+(按需指定)| 100% | `npm run test:e2e` |
|
||||
|
||||
---
|
||||
|
||||
## 二、Vitest 单元测试(24 文件,171 用例)
|
||||
|
||||
### 2.1 组件测试(13 文件,141 用例)
|
||||
|
||||
覆盖所有管理页面的 Vue 组件渲染和行为。
|
||||
|
||||
| 测试文件 | 用例数 | 测试的 Vue 组件 |
|
||||
|---|---|---|
|
||||
| `Login.test.ts` | 12 | 登录表单(用户名/密码输入、提交、错误提示、记住我) |
|
||||
| `Dashboard.test.ts` | 10 | 仪表盘(统计卡片、数据加载、模块渲染) |
|
||||
| `UserManagement.test.ts` | 15 | 用户管理(列表渲染、搜索、新增/编辑对话框、角色分配、删除确认) |
|
||||
| `RoleManagement.test.ts` | 12 | 角色管理(列表、权限树、菜单分配、状态切换) |
|
||||
| `MenuManagement.test.ts` | 14 | 菜单管理(树形表格、新增/编辑、图标选择、排序) |
|
||||
| `DictManagement.test.ts` | 12 | 字典管理(类型+数据 Tab切换、新增、编辑、删除) |
|
||||
| `ConfigManagement.test.ts` | 10 | 参数配置(列表、新增、编辑、key 唯一性) |
|
||||
| `NoticeManagement.test.ts` | 10 | 通知公告(发布、撤回、富文本编辑) |
|
||||
| `FileManagement.test.ts` | 8 | 文件管理(上传、下载、预览、删除、类型过滤) |
|
||||
| `OperationLog.test.ts` | 8 | 操作日志(列表、筛选、详情查看) |
|
||||
| `LoginLog.test.ts` | 8 | 登录日志(列表、状态筛选、时间范围) |
|
||||
| `ExceptionLog.test.ts` | 7 | 异常日志(列表、堆栈展开、级别过滤) |
|
||||
| `MenuItem.test.ts` | 5 | 菜单项渲染、路由跳转、权限隐藏 |
|
||||
|
||||
### 2.2 状态管理(1 文件,10 用例)
|
||||
|
||||
| 测试文件 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `permission.test.ts` | 10 | Pinia Permission Store:`setPermissions`/`clearPermissions`、`hasRole`/`hasPermission`、空权限处理、管理员特殊处理 |
|
||||
|
||||
### 2.3 指令(1 文件,5 用例)
|
||||
|
||||
| 测试文件 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `permission.test.ts` | 5 | `v-permission` 指令:角色检查、权限检查、数组参数、无权限隐藏/禁用 |
|
||||
|
||||
### 2.4 路由守卫(1 文件,5 用例)
|
||||
|
||||
| 测试文件 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `permission.guard.test.ts` | 5 | 未登录 → 重定向 `/login`、已登录访问 `/login` → 重定向 `/dashboard`、Token过期处理、白名单路径、动态路由加载 |
|
||||
|
||||
### 2.5 基于角色的测试(3 文件,15 用例)
|
||||
|
||||
| 测试文件 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `admin.role.test.ts` | 6 | 管理员角色:全权限、全菜单、无限制操作 |
|
||||
| `base.role.test.ts` | 5 | 基础角色:受限菜单、操作按钮隐藏 |
|
||||
| `role-factory.test.ts` | 4 | 角色工厂:动态创建测试角色、权限组合 |
|
||||
|
||||
### 2.6 角色测试辅助(3 文件,13 用例)
|
||||
|
||||
| 测试文件 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `test-data-manager.test.ts` | 5 | 测试数据生成器(用户、角色、菜单) |
|
||||
| `role-auth-manager.test.ts` | 4 | 角色认证管理器 |
|
||||
| `permission-helper.test.ts` | 4 | 权限辅助工具 |
|
||||
|
||||
### 2.7 工具函数(1 文件,6 用例)
|
||||
|
||||
| 测试文件 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `errorHandler.test.ts` | 6 | 统一错误处理:网络错误、401 自动登出、403 提示、超时回调 |
|
||||
|
||||
### 2.8 配置验证(1 文件,2 用例)
|
||||
|
||||
| 测试文件 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `config.test.ts` | 2 | Vitest 框架配置验证:基础断言、异步支持 |
|
||||
|
||||
### 2.9 Vitest 单元测试目录结构
|
||||
|
||||
```
|
||||
src/__tests__/
|
||||
├── components/ # 14 组件测试
|
||||
│ ├── Login.test.ts
|
||||
│ ├── Dashboard.test.ts
|
||||
│ ├── UserManagement.test.ts
|
||||
│ ├── RoleManagement.test.ts
|
||||
│ ├── MenuManagement.test.ts
|
||||
│ ├── MenuItem.test.ts
|
||||
│ ├── DictManagement.test.ts
|
||||
│ ├── ConfigManagement.test.ts
|
||||
│ ├── NoticeManagement.test.ts
|
||||
│ ├── FileManagement.test.ts
|
||||
│ ├── OperationLog.test.ts
|
||||
│ ├── LoginLog.test.ts
|
||||
│ └── ExceptionLog.test.ts
|
||||
├── stores/
|
||||
│ └── permission.test.ts # Pinia Store
|
||||
├── directives/
|
||||
│ └── permission.test.ts # v-permission
|
||||
├── router/
|
||||
│ └── permission.guard.test.ts # 路由守卫
|
||||
├── utils/
|
||||
│ └── errorHandler.test.ts # 错误处理
|
||||
├── config.test.ts # 框架验证
|
||||
└── role-based-tests/ # 基于角色
|
||||
├── roles/__tests__/
|
||||
│ ├── admin.role.test.ts
|
||||
│ ├── base.role.test.ts
|
||||
│ └── role-factory.test.ts
|
||||
└── shared/__tests__/
|
||||
├── test-data-manager.test.ts
|
||||
├── role-auth-manager.test.ts
|
||||
└── permission-helper.test.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、Playwright E2E 测试(24+ 用例)
|
||||
|
||||
### 3.1 测试体系
|
||||
|
||||
由 4 个项目组成,分别覆盖不同层级:
|
||||
|
||||
| 项目 | 目录 | 描述 | 用例数 |
|
||||
|---|---|---|---|
|
||||
| `setup` | `auth.setup.ts` | 认证 Token 预获取(全局前置) | 1 |
|
||||
| `smoke` | `e2e/smoke/` | 基础冒烟测试 | 1 |
|
||||
| `root` | `e2e/*.spec.ts` | 独立功能验证 | 7 |
|
||||
| `journeys` | `e2e/journeys/` | 端到端旅程 | 16 |
|
||||
| `debug` | `e2e/debug/` | 调试辅助 | 3 |
|
||||
|
||||
### 3.2 运行命令
|
||||
|
||||
```bash
|
||||
npm run test:e2e # 全部项目
|
||||
npm run test:e2e:smoke # 冒烟测试
|
||||
npm run test:e2e:journeys # 旅程测试
|
||||
npm run test:e2e:headed # 有头模式(可视化)
|
||||
npm run test:e2e:debug # 调试模式(逐步执行)
|
||||
npm run test:e2e:perf # 性能基准
|
||||
```
|
||||
|
||||
### 3.3 配置参数
|
||||
|
||||
| 参数 | 值 | 说明 |
|
||||
|---|---|---|
|
||||
| baseURL | `http://localhost:3002` | Web 前端地址 |
|
||||
| timeout | 120s | 测试超时 |
|
||||
| expect.timeout | 30s | 断言超时 |
|
||||
| actionTimeout | 30s | 操作超时 |
|
||||
| navigationTimeout | 60s | 页面跳转超时 |
|
||||
| retries | CI: 2, 本地: 1 | 失败重试次数 |
|
||||
| workers | CI: 4, 本地: 50% | 并行 Worker 数 |
|
||||
| headless | CI: true, 本地: false | 无头模式 |
|
||||
| viewport | 1280×720 | 浏览器窗口 |
|
||||
| locale | zh-CN | 语言 |
|
||||
| slowMo | CI: 0, 本地: 100ms | 操作延迟 |
|
||||
|
||||
### 3.4 测试文件详情
|
||||
|
||||
#### 冒烟测试 (smoke/)
|
||||
|
||||
| 文件 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `login-logout.spec.ts` | 1 | 管理员登录 → 导航验证 → 登出 |
|
||||
|
||||
#### 根级测试
|
||||
|
||||
| 文件 | 用例数 | 测试内容 |
|
||||
|---|---|---|
|
||||
| `api-connectivity.spec.ts` | 3 | 网关健康检查 `/actuator/health`、前端页面加载、数据库连接状态 |
|
||||
| `auth-test.spec.ts` | 3 | JWT Token 获取/验证、未授权 401、登录 UI、权限验证 |
|
||||
| `basic-ui-test.spec.ts` | 1 | 首页加载、登录页表单元素、导航栏、响应式 (375×667) |
|
||||
| `unauthorized-redirect.spec.ts` | 1 | 未登录访问 `/members`、`/courses`、`/statistics` → 自动重定向 `/login` |
|
||||
| `menu-management.spec.ts` | 1 | 登录 → 菜单管理 → 表格数据渲染 |
|
||||
| `dict-management.spec.ts` | 1 | 登录 → 字典管理 → 类型+数据列表 |
|
||||
| `config-management.spec.ts` | 1 | 登录 → 参数配置 → 列表显示 |
|
||||
|
||||
#### 旅程测试 (journeys/)
|
||||
|
||||
| 文件 | 用例数 | 业务链路 |
|
||||
|---|---|---|
|
||||
| `admin-complete-workflow.spec.ts` | 1 | 创建角色 → 分配权限 → 创建用户 → 绑定角色 → 验证权限 |
|
||||
| `audit-workflow.spec.ts` | 1 | 导航审计日志 → 筛选条件 → 时间范围 → 详情查看 |
|
||||
| `coach-banner-workflow.spec.ts` | 1 | 教练管理 → 轮播图管理 → 新增/编辑 |
|
||||
| `config-workflow.spec.ts` | 1 | 参数配置 → 新增配置 → 编辑 → 删除 |
|
||||
| `dict-workflow.spec.ts` | 1 | 字典类型创建 → 字典数据录入 → 编辑 → 删除 |
|
||||
| `dictionary-complete-workflow.spec.ts` | 1 | 字典类型+数据完整增删改查流程 |
|
||||
| `exception-log-workflow.spec.ts` | 1 | 异常日志查看 → 堆栈展开 → 级别筛选 |
|
||||
| `extended-role-boundary.spec.ts` | 1 | 角色权限扩展 → 边界条件 → 多角色叠加 |
|
||||
| `file-management-workflow.spec.ts` | 1 | 文件上传 → 列表查看 → 下载 → 预览 → 删除 |
|
||||
| `groupcourse-workflow.spec.ts` | 1 | 课程类型 → 课程标签 → 课程推荐 → 团课管理 |
|
||||
| `member-workflow.spec.ts` | 1 | 会员列表 → 会员卡管理 → 储值卡 → 退款申请 |
|
||||
| `notice-workflow.spec.ts` | 1 | 创建公告 → 发布 → 查看 → 撤回 |
|
||||
| `performance.spec.ts` | 1 | 首屏加载时间、路由切换性能、API 响应耗时 |
|
||||
| `statistics-workflow.spec.ts` | 1 | 数据统计看板 → 会员统计 → 预约统计 → 签到统计 |
|
||||
| `system-config-complete-workflow.spec.ts` | 1 | 系统配置完整增删改查 → 缓存刷新 → 验证生效 |
|
||||
| `user-permission-boundary.spec.ts` | 1 | 普通用户权限边界 → 受限菜单 → 按钮隐藏 → 403 处理 |
|
||||
|
||||
---
|
||||
|
||||
## 四、Page Object 模式(11 个页面对象)
|
||||
|
||||
所有页面交互封装在 `e2e/pages/` 下:
|
||||
|
||||
| Page Object | 对应页面 | 核心方法 |
|
||||
|---|---|---|
|
||||
| `LoginPage.ts` | 登录 | `goto()`, `login(username, password)`, `getErrorMessage()` |
|
||||
| `DashboardPage.ts` | 仪表盘 | `getStats()`, `navigateTo(menu)` |
|
||||
| `UserManagementPage.ts` | 用户管理 | `searchUser()`, `addUser()`, `editUser()`, `deleteUser()` |
|
||||
| `RoleManagementPage.ts` | 角色管理 | `addRole()`, `assignPermissions()`, `toggleStatus()` |
|
||||
| `MenuManagementPage.ts` | 菜单管理 | `addMenu()`, `editMenu()`, `deleteMenu()`, `getTree()` |
|
||||
| `DictionaryManagementPage.ts` | 字典管理 | `addType()`, `addData()`, `editData()`, `deleteData()` |
|
||||
| `SystemConfigPage.ts` | 参数配置 | `addConfig()`, `editConfig()`, `deleteConfig()` |
|
||||
| `NotificationPage.ts` | 通知公告 | `createNotice()`, `publish()`, `revoke()` |
|
||||
| `FileManagementPage.ts` | 文件管理 | `uploadFile()`, `downloadFile()`, `previewFile()` |
|
||||
| `OperationLogPage.ts` | 操作日志 | `filterByModule()`, `viewDetail()` |
|
||||
| `LoginLogPage.ts` | 登录日志 | `filterByStatus()`, `filterByDate()` |
|
||||
| `ExceptionLogPage.ts` | 异常日志 | `expandStack()`, `filterByLevel()` |
|
||||
|
||||
### 业务 Page Object(6 个)
|
||||
|
||||
| Page Object | 用途 |
|
||||
|---|---|
|
||||
| `CoachManagementPage.ts` | 教练 CRUD |
|
||||
| `BannerManagementPage.ts` | 轮播图管理 |
|
||||
| `CourseTypeManagementPage.ts` | 课程类型管理 |
|
||||
| `CourseLabelManagementPage.ts` | 课程标签管理 |
|
||||
| `CourseRecommendManagementPage.ts` | 课程推荐管理 |
|
||||
| `GroupCourseManagementPage.ts` | 团课管理 |
|
||||
| `MemberManagementPage.ts` | 会员管理 |
|
||||
| `MemberCardManagementPage.ts` | 会员卡管理 |
|
||||
| `StatisticsDashboardPage.ts` | 统计看板 |
|
||||
|
||||
---
|
||||
|
||||
## 五、辅助模块
|
||||
|
||||
### Helpers
|
||||
|
||||
| 文件 | 用途 |
|
||||
|---|---|
|
||||
| `auth.ts` | 登录认证、Token 存储/获取/清除 |
|
||||
| `TestStabilityHelper.ts` | 测试稳定性(重试、等待、超时处理) |
|
||||
| `TestDataManager.ts` | 测试数据 CRUD 管理 |
|
||||
|
||||
### Utils
|
||||
|
||||
| 文件 | 用途 |
|
||||
|---|---|
|
||||
| `api-client.ts` | HTTP API 客户端封装 |
|
||||
| `testHelper.ts` | 通用测试辅助函数 |
|
||||
| `TestDataFactory.ts` | 测试数据工厂(用户/角色/菜单/字典生成) |
|
||||
| `TestDataCleanup.ts` | 测试后数据清理 |
|
||||
| `RetryHelper.ts` | 智能重试策略 |
|
||||
| `testDataManager.ts` | 测试数据管理 |
|
||||
|
||||
### Fixtures
|
||||
|
||||
| 文件 | 用途 |
|
||||
|---|---|
|
||||
| `test-data.ts` | 静态测试数据(账号、权限、菜单结构) |
|
||||
| `test-file.txt` | 文件上传测试用文件 |
|
||||
|
||||
---
|
||||
|
||||
## 六、运行方式
|
||||
|
||||
```bash
|
||||
# 进入 Web 后台目录
|
||||
cd gym-manage-web
|
||||
|
||||
# 单元测试
|
||||
npm run test # 全量单元测试
|
||||
npx vitest --run # 同全量
|
||||
npx vitest --run Login # 运行匹配 "Login" 的测试
|
||||
npx vitest --ui # Vitest UI 模式
|
||||
|
||||
# E2E 测试(需先启动后端和前端服务)
|
||||
npm run test:e2e # 全部 Playwright 项目
|
||||
npm run test:e2e:smoke # 仅冒烟
|
||||
npm run test:e2e:journeys # 仅旅程
|
||||
npm run test:e2e:headed # 可视化浏览器
|
||||
npm run test:e2e:debug # 逐步执行
|
||||
npm run test:e2e:perf # 性能基准
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**文档生成时间**: 2026-07-21 | **测试工具**: Vitest + jsdom / Playwright + Chromium
|
||||
Reference in New Issue
Block a user