pangu-user-platform/docs/05-模块技术方案/学校管理/学校管理模块_测试方案.md

609 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 学校管理模块 - 测试方案
---
| 文档信息 | 内容 |
|---------|------|
| **文档版本** | V1.0 |
| **模块名称** | 学校管理模块 |
| **编写团队** | pangu |
| **创建日期** | 2026-01-31 |
---
## 1. 测试概述
### 1.1 测试目标
- 验证学校管理模块所有功能按需求规格正确实现
- 验证业务规则正确执行
- 验证接口响应符合设计规范
- 验证数据权限控制有效
- 验证前端交互体验符合原型设计
### 1.2 测试范围
| 功能点 | 测试类型 | 优先级 |
|-------|---------|:------:|
| 学校树查询 | 接口测试、UI测试 | P0 |
| 学校列表查询 | 接口测试、UI测试 | P0 |
| 新增学校 | 接口测试、UI测试 | P0 |
| 编辑学校 | 接口测试、UI测试 | P0 |
| 删除学校 | 接口测试、UI测试 | P0 |
| 挂载年级 | 接口测试、UI测试 | P0 |
| 挂载班级 | 接口测试、UI测试 | P0 |
| 删除年级 | 接口测试、UI测试 | P1 |
| 删除班级 | 接口测试、UI测试 | P1 |
| 数据权限 | 接口测试 | P0 |
| 表单验证 | UI测试 | P0 |
### 1.3 测试环境
| 环境 | 说明 |
|-----|------|
| 前端 | Chrome 120+, Edge 120+ |
| 后端 | Java 17, Spring Boot 3.3.x |
| 数据库 | MySQL 8.0 |
| 测试工具 | Postman, JUnit 5 |
---
## 2. 接口测试用例
### 2.1 获取学校树
**接口地址**: `GET /api/school/tree`
| 用例编号 | 用例名称 | 请求参数 | 预期结果 |
|:------:|---------|---------|---------|
| API-SCH-001 | 查询全部学校树 | 无 | 返回所有学校树形结构 |
| API-SCH-002 | 按区域查询学校树 | regionId=111 | 返回武昌区下学校树 |
| API-SCH-003 | 查询无学校的区域 | regionId=999 | 返回空数组 |
**API-SCH-001 详细用例**
```
请求GET /api/school/tree
Header: Authorization: Bearer {token}
预期响应:
{
"code": 200,
"msg": "查询成功",
"data": [
{
"id": 1,
"type": "school",
"name": "武汉市第一中学",
"code": "SCH20260001",
"status": "0",
"regionPath": "湖北省-武汉市-武昌区",
"children": [
{
"id": 1,
"type": "grade",
"name": "七年级",
"schoolGradeId": 1,
"gradeId": 7,
"children": [
{
"id": 1,
"type": "class",
"name": "1班",
"schoolClassId": 1,
"classId": 1
}
]
}
]
}
]
}
验证点:
1. 返回code为200
2. data为数组格式
3. 学校节点包含type="school"
4. 年级节点包含type="grade"
5. 班级节点包含type="class"
6. 层级关系正确
```
---
### 2.2 新增学校
**接口地址**: `POST /api/school`
| 用例编号 | 用例名称 | 请求参数 | 预期结果 |
|:------:|---------|---------|---------|
| API-SCH-010 | 正常新增学校 | 必填项完整 | 成功,学校编码自动生成 |
| API-SCH-011 | 缺少学校名称 | schoolName为空 | 失败,返回验证错误 |
| API-SCH-012 | 缺少所属区域 | regionId为空 | 失败,返回验证错误 |
| API-SCH-013 | 缺少学校类型 | schoolType为空 | 失败,返回验证错误 |
| API-SCH-014 | 学校名称超长 | 101个字符 | 失败,返回验证错误 |
**API-SCH-010 详细用例**
```
请求POST /api/school
Header:
Authorization: Bearer {token}
Content-Type: application/json
Body:
{
"schoolName": "武汉市测试中学",
"schoolType": "02",
"regionId": 111,
"address": "武昌区测试路1号",
"contactPerson": "张老师",
"contactPhone": "13812345678",
"status": "0"
}
预期响应:
{
"code": 200,
"msg": "操作成功"
}
验证点:
1. 返回code为200
2. 数据库中新增一条学校记录
3. school_code格式为SCH2026xxxx
4. region_path自动填充为"湖北省-武汉市-武昌区"
5. del_flag为'0'
6. create_time和create_by已填充
```
**API-SCH-011 详细用例**
```
请求POST /api/school
Body:
{
"schoolName": "",
"schoolType": "02",
"regionId": 111
}
预期响应:
{
"code": 400,
"msg": "学校名称不能为空"
}
验证点:
1. 返回code为400
2. msg包含错误提示
3. 数据库未新增记录
```
---
### 2.3 修改学校
**接口地址**: `PUT /api/school`
| 用例编号 | 用例名称 | 请求参数 | 预期结果 |
|:------:|---------|---------|---------|
| API-SCH-020 | 正常修改学校 | 合法参数 | 成功 |
| API-SCH-021 | 修改不存在的学校 | schoolId=999 | 失败 |
| API-SCH-022 | 修改区域后更新路径 | regionId变更 | 成功region_path更新 |
**API-SCH-020 详细用例**
```
请求PUT /api/school
Body:
{
"schoolId": 1,
"schoolName": "武汉市第一中学(新)",
"schoolType": "02",
"regionId": 111,
"status": "0"
}
预期响应:
{
"code": 200,
"msg": "操作成功"
}
验证点:
1. 返回code为200
2. 数据库school_name已更新
3. update_time和update_by已更新
```
---
### 2.4 删除学校
**接口地址**: `DELETE /api/school/{schoolId}`
| 用例编号 | 用例名称 | 前置条件 | 预期结果 |
|:------:|---------|---------|---------|
| API-SCH-030 | 删除无子级的学校 | 学校无年级/班级 | 成功 |
| API-SCH-031 | 删除有年级的学校 | 学校下有年级 | 失败,提示有年级 |
| API-SCH-032 | 删除有学生的学校 | 学校被学生引用 | 失败,提示被引用 |
| API-SCH-033 | 删除不存在的学校 | schoolId=999 | 失败 |
**API-SCH-031 详细用例**
```
前置条件:
- 学校ID=1下有年级数据
请求DELETE /api/school/1
预期响应:
{
"code": 500,
"msg": "该学校下存在年级数据,请先删除年级"
}
验证点:
1. 返回code非200
2. msg包含错误提示
3. 数据库记录未删除
```
**API-SCH-032 详细用例**
```
前置条件:
- 学校ID=2无年级数据
- 学校ID=2被学生信息引用
请求DELETE /api/school/2
预期响应:
{
"code": 500,
"msg": "该学校已被学生信息引用,无法删除"
}
验证点:
1. 返回code非200
2. 数据库记录未删除
```
---
### 2.5 挂载年级
**接口地址**: `POST /api/school/bindGrades`
| 用例编号 | 用例名称 | 请求参数 | 预期结果 |
|:------:|---------|---------|---------|
| API-SCH-040 | 正常挂载年级 | schoolId + gradeIds | 成功 |
| API-SCH-041 | 重复挂载年级 | 已存在的gradeId | 成功,忽略重复 |
| API-SCH-042 | 空年级列表 | gradeIds为空数组 | 失败,验证错误 |
| API-SCH-043 | 挂载到不存在的学校 | schoolId=999 | 失败 |
**API-SCH-040 详细用例**
```
请求POST /api/school/bindGrades
Body:
{
"schoolId": 1,
"gradeIds": [1, 2, 3]
}
预期响应:
{
"code": 200,
"msg": "操作成功"
}
验证点:
1. 返回code为200
2. pg_school_grade表新增3条记录
3. school_id和grade_id关联正确
```
**API-SCH-041 详细用例**
```
前置条件:
- 学校ID=1已挂载年级ID=1
请求POST /api/school/bindGrades
Body:
{
"schoolId": 1,
"gradeIds": [1, 4, 5]
}
预期响应:
{
"code": 200,
"msg": "操作成功"
}
验证点:
1. 返回成功
2. 新增2条记录年级4、5
3. 年级1不重复插入
```
---
### 2.6 挂载班级
**接口地址**: `POST /api/school/bindClasses`
| 用例编号 | 用例名称 | 请求参数 | 预期结果 |
|:------:|---------|---------|---------|
| API-SCH-050 | 正常挂载班级 | schoolGradeId + classIds | 成功 |
| API-SCH-051 | 重复挂载班级 | 已存在的classId | 成功,忽略重复 |
| API-SCH-052 | 挂载到不存在的年级 | schoolGradeId=999 | 失败 |
---
### 2.7 删除学校年级
**接口地址**: `DELETE /api/school/grade/{schoolGradeId}`
| 用例编号 | 用例名称 | 前置条件 | 预期结果 |
|:------:|---------|---------|---------|
| API-SCH-060 | 删除无班级的年级 | 年级下无班级 | 成功 |
| API-SCH-061 | 删除有班级的年级 | 年级下有班级 | 失败,提示有班级 |
| API-SCH-062 | 删除被学生引用的年级 | 年级被学生引用 | 失败,提示被引用 |
---
### 2.8 删除学校班级
**接口地址**: `DELETE /api/school/class/{schoolClassId}`
| 用例编号 | 用例名称 | 前置条件 | 预期结果 |
|:------:|---------|---------|---------|
| API-SCH-070 | 删除未被引用的班级 | 班级未被学生引用 | 成功 |
| API-SCH-071 | 删除被学生引用的班级 | 班级被学生引用 | 失败,提示被引用 |
---
### 2.9 数据权限测试
| 用例编号 | 用例名称 | 测试账号 | 预期结果 |
|:------:|---------|---------|---------|
| API-SCH-080 | 超级管理员查看全部 | admin | 返回所有学校 |
| API-SCH-081 | 分公司用户查看所属区域 | 武汉分公司用户 | 只返回武汉区域学校 |
| API-SCH-082 | 分公司用户新增学校 | 武汉分公司用户 | 只能选择所属区域 |
| API-SCH-083 | 学校用户无权限 | 学校用户 | 菜单不显示或403 |
---
## 3. 功能测试用例
### 3.1 页面加载
| 用例编号 | 用例名称 | 测试步骤 | 预期结果 |
|:------:|---------|---------|---------|
| UI-SCH-001 | 页面正常加载 | 访问学校管理页面 | 页面正常显示 |
| UI-SCH-002 | 区域树加载 | 进入页面 | 左侧显示区域树 |
| UI-SCH-003 | 学校树加载 | 进入页面 | 右侧显示学校树 |
| UI-SCH-004 | 加载状态显示 | 刷新页面 | 显示加载中状态 |
---
### 3.2 区域树操作
| 用例编号 | 用例名称 | 测试步骤 | 预期结果 |
|:------:|---------|---------|---------|
| UI-SCH-010 | 区域树展开收起 | 点击父节点图标 | 子节点展开/收起 |
| UI-SCH-011 | 区域节点选中 | 点击区域节点 | 节点高亮,学校列表刷新 |
| UI-SCH-012 | 多次点击相同节点 | 重复点击同一节点 | 不重复请求 |
---
### 3.3 学校树操作
| 用例编号 | 用例名称 | 测试步骤 | 预期结果 |
|:------:|---------|---------|---------|
| UI-SCH-020 | 学校树展开 | 点击学校行展开图标 | 显示年级和班级 |
| UI-SCH-021 | 学校树收起 | 点击已展开学校的图标 | 年级班级收起 |
| UI-SCH-022 | 显示学校编码 | 查看学校行 | 学校行显示编码 |
| UI-SCH-023 | 年级班级无编码 | 查看年级/班级行 | 编码列显示"-" |
---
### 3.4 新增学校
| 用例编号 | 用例名称 | 测试步骤 | 预期结果 |
|:------:|---------|---------|---------|
| UI-SCH-030 | 打开新增弹窗 | 点击"新增学校"按钮 | 弹窗显示 |
| UI-SCH-031 | 区域默认值 | 先选择区域树节点,再点击新增 | 所属区域默认带入 |
| UI-SCH-032 | 表单验证-必填 | 留空必填项,点击确定 | 显示验证提示 |
| UI-SCH-033 | 表单验证-手机号 | 输入错误格式手机号 | 显示格式错误提示 |
| UI-SCH-034 | 正常新增 | 填写完整信息,点击确定 | 成功提示,列表刷新 |
| UI-SCH-035 | 取消新增 | 点击取消按钮 | 弹窗关闭,无数据变化 |
---
### 3.5 编辑学校
| 用例编号 | 用例名称 | 测试步骤 | 预期结果 |
|:------:|---------|---------|---------|
| UI-SCH-040 | 打开编辑弹窗 | 点击学校行"编辑"按钮 | 弹窗显示,数据回填 |
| UI-SCH-041 | 学校编码只读 | 查看编辑弹窗 | 学校编码不可修改 |
| UI-SCH-042 | 修改学校名称 | 修改名称,点击确定 | 成功,列表数据更新 |
| UI-SCH-043 | 修改所属区域 | 修改区域,点击确定 | 成功,区域路径更新 |
---
### 3.6 删除学校
| 用例编号 | 用例名称 | 测试步骤 | 预期结果 |
|:------:|---------|---------|---------|
| UI-SCH-050 | 删除确认弹窗 | 点击"删除"按钮 | 显示确认对话框 |
| UI-SCH-051 | 取消删除 | 确认框点击取消 | 对话框关闭,数据不变 |
| UI-SCH-052 | 确认删除成功 | 确认删除无关联学校 | 成功提示,列表刷新 |
| UI-SCH-053 | 删除失败提示 | 确认删除有关联学校 | 显示错误提示 |
---
### 3.7 挂载年级
| 用例编号 | 用例名称 | 测试步骤 | 预期结果 |
|:------:|---------|---------|---------|
| UI-SCH-060 | 打开年级选择弹窗 | 点击学校行"新增年级" | 弹窗显示年级列表 |
| UI-SCH-061 | 已挂载年级禁用 | 查看弹窗 | 已挂载的年级显示禁用 |
| UI-SCH-062 | 多选年级 | 勾选多个年级 | 支持多选 |
| UI-SCH-063 | 确认挂载 | 选择年级,点击确定 | 成功,学校树刷新 |
| UI-SCH-064 | 未选择年级确认 | 不选择年级,点击确定 | 提示请选择年级 |
---
### 3.8 挂载班级
| 用例编号 | 用例名称 | 测试步骤 | 预期结果 |
|:------:|---------|---------|---------|
| UI-SCH-070 | 打开班级选择弹窗 | 点击年级行"新增班级" | 弹窗显示班级列表 |
| UI-SCH-071 | 已挂载班级禁用 | 查看弹窗 | 已挂载的班级显示禁用 |
| UI-SCH-072 | 确认挂载班级 | 选择班级,点击确定 | 成功,学校树刷新 |
---
### 3.9 删除年级/班级
| 用例编号 | 用例名称 | 测试步骤 | 预期结果 |
|:------:|---------|---------|---------|
| UI-SCH-080 | 删除年级确认 | 点击年级行"删除" | 显示确认对话框 |
| UI-SCH-081 | 删除年级失败 | 确认删除有班级的年级 | 显示错误提示 |
| UI-SCH-082 | 删除年级成功 | 确认删除无班级的年级 | 成功,学校树刷新 |
| UI-SCH-083 | 删除班级 | 点击班级行"删除"并确认 | 成功,学校树刷新 |
---
### 3.10 搜索功能
| 用例编号 | 用例名称 | 测试步骤 | 预期结果 |
|:------:|---------|---------|---------|
| UI-SCH-090 | 按名称搜索 | 输入学校名称,点击搜索 | 列表过滤 |
| UI-SCH-091 | 按状态搜索 | 选择状态,点击搜索 | 列表过滤 |
| UI-SCH-092 | 组合搜索 | 输入名称+选择状态 | 列表过滤 |
| UI-SCH-093 | 重置搜索 | 点击重置按钮 | 清空条件,显示全部 |
| UI-SCH-094 | 无结果提示 | 搜索不存在的学校 | 显示"暂无数据" |
---
## 4. 边界测试
### 4.1 数据边界
| 用例编号 | 用例名称 | 测试数据 | 预期结果 |
|:------:|---------|---------|---------|
| BD-SCH-001 | 学校名称最大长度 | 100个中文字符 | 成功 |
| BD-SCH-002 | 学校名称超长 | 101个中文字符 | 验证失败 |
| BD-SCH-003 | 空学校列表 | 新区域无学校 | 显示空状态 |
| BD-SCH-004 | 大量学校 | 100所学校 | 正常显示,无卡顿 |
| BD-SCH-005 | 深层级结构 | 学校-12年级-10班级 | 正常展开显示 |
### 4.2 并发测试
| 用例编号 | 用例名称 | 测试场景 | 预期结果 |
|:------:|---------|---------|---------|
| CC-SCH-001 | 同时新增学校 | 2个用户同时新增 | 编码不冲突 |
| CC-SCH-002 | 同时挂载年级 | 2个用户同时挂载相同年级 | 不重复插入 |
---
## 5. 测试数据准备
### 5.1 测试账号
| 角色 | 账号 | 密码 | 权限 |
|-----|------|------|------|
| 超级管理员 | admin | admin123 | 全部权限 |
| 武汉分公司用户 | wuhan_user | 123456 | 武汉区域数据 |
| 学校用户 | school_user | 123456 | 本校数据 |
### 5.2 测试数据
```sql
-- 测试区域
INSERT INTO pg_region VALUES (1, 0, '湖北', 1, '0', 1, '0');
INSERT INTO pg_region VALUES (11, 1, '武汉', 2, '0,1', 1, '0');
INSERT INTO pg_region VALUES (111, 11, '武昌区', 3, '0,1,11', 1, '0');
-- 测试学校
INSERT INTO pg_school VALUES (1, 'SCH20260001', '测试学校A', '02', 111, '湖北省-武汉市-武昌区', '0', '0');
INSERT INTO pg_school VALUES (2, 'SCH20260002', '测试学校B', '02', 111, '湖北省-武汉市-武昌区', '0', '0');
-- 测试年级
INSERT INTO pg_grade VALUES (1, 'GRD001', '一年级', 1, '0', '0');
INSERT INTO pg_grade VALUES (7, 'GRD007', '七年级', 7, '0', '0');
-- 测试班级
INSERT INTO pg_class VALUES (1, 'CLS001', '1班', 1, '0', '0');
INSERT INTO pg_class VALUES (2, 'CLS002', '2班', 2, '0', '0');
-- 测试关联
INSERT INTO pg_school_grade VALUES (1, 1, 7, 1, '0', '0');
INSERT INTO pg_school_class VALUES (1, 1, 1, 1, '0', '0');
```
---
## 6. 缺陷管理
### 6.1 缺陷等级定义
| 等级 | 说明 | 处理时限 |
|:----:|------|---------|
| P0 | 阻塞性缺陷,功能完全不可用 | 立即修复 |
| P1 | 严重缺陷,核心功能受影响 | 1个工作日 |
| P2 | 一般缺陷,功能可用但有问题 | 3个工作日 |
| P3 | 轻微缺陷,体验问题 | 下个版本 |
### 6.2 缺陷跟踪
| 缺陷编号 | 标题 | 等级 | 发现人 | 发现日期 | 状态 | 修复人 | 验证人 |
|:------:|------|:----:|------|---------|:----:|------|------|
| | | | | | | | |
---
## 7. 测试报告模板
### 7.1 测试概要
| 项目 | 内容 |
|-----|------|
| 测试模块 | 学校管理 |
| 测试版本 | |
| 测试周期 | |
| 测试人员 | |
### 7.2 测试结果
| 测试类型 | 用例数 | 通过 | 失败 | 阻塞 | 通过率 |
|---------|:------:|:----:|:----:|:----:|:------:|
| 接口测试 | | | | | |
| 功能测试 | | | | | |
| 边界测试 | | | | | |
| **合计** | | | | | |
### 7.3 缺陷统计
| 等级 | 发现数 | 已修复 | 待修复 | 验证通过 |
|:----:|:------:|:------:|:------:|:--------:|
| P0 | | | | |
| P1 | | | | |
| P2 | | | | |
| P3 | | | | |
### 7.4 测试结论
- [ ] 通过测试,可以发布
- [ ] 有待修复问题,暂不发布
- [ ] 建议:
---
*文档结束*