# 学校管理模块 - 测试方案 --- | 文档信息 | 内容 | |---------|------| | **文档版本** | 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 测试结论 - [ ] 通过测试,可以发布 - [ ] 有待修复问题,暂不发布 - [ ] 建议: --- *文档结束*