training-system
This commit is contained in:
449
training-system/docs/test-reports/BugAnalysis_2.0_Knowledge.md
Normal file
449
training-system/docs/test-reports/BugAnalysis_2.0_Knowledge.md
Normal file
@@ -0,0 +1,449 @@
|
||||
# BUG分析报告 - 模块二:知识库
|
||||
|
||||
> 分析日期:2026-01-12
|
||||
> 分析人员:Java高级工程师
|
||||
> 关联测试报告:TestReport_2.0_Knowledge.md
|
||||
> 产品文档版本:PRD V1.0
|
||||
|
||||
---
|
||||
|
||||
## 一、报告概述
|
||||
|
||||
本报告针对知识库模块测试报告(TestReport_2.0_Knowledge.md)中发现的3个缺陷进行深度分析,明确BUG产生的根本原因,并提供具体的解决方案。
|
||||
|
||||
### 缺陷汇总
|
||||
|
||||
| 缺陷编号 | 缺陷名称 | 严重程度 | 优先级 | 影响范围 |
|
||||
|---------|---------|---------|--------|---------|
|
||||
| BUG-KM-001 | 创建知识时creator_id未设置 | **阻断** | P0 | 15个用例被阻塞 |
|
||||
| BUG-KM-002 | 讲师可以操作其他部门的分类 | 高 | P1 | 部门数据隔离失效 |
|
||||
| BUG-KM-003 | 文件上传功能异常 | 高 | P1 | 知识文档无法上传 |
|
||||
|
||||
---
|
||||
|
||||
## 二、缺陷详细分析
|
||||
|
||||
### 2.1 BUG-KM-001:创建知识时creator_id未设置
|
||||
|
||||
#### 基本信息
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-KM-001 |
|
||||
| 严重程度 | **阻断(Blocker)** |
|
||||
| 优先级 | P0 - 立即修复 |
|
||||
| 错误信息 | `Field 'creator_id' doesn't have a default value` |
|
||||
| 影响范围 | 知识创建功能完全不可用,阻塞15个测试用例 |
|
||||
|
||||
#### 原因分析
|
||||
|
||||
**1. 数据库设计约束**
|
||||
|
||||
根据PRD文档第5.1节"知识(km_knowledge)"实体定义:
|
||||
|
||||
```
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| creator_id | Long | 创建人 |
|
||||
```
|
||||
|
||||
`creator_id` 是必填字段(NOT NULL),用于记录知识的创建人ID。
|
||||
|
||||
**2. 业务逻辑缺失**
|
||||
|
||||
在 `KnowledgeServiceImpl.createKnowledge()` 方法中存在以下问题:
|
||||
|
||||
- **未从认证上下文获取用户ID**:方法没有从当前登录用户的JWT Token或SecurityContext中提取用户ID
|
||||
- **直接透传前端数据**:将前端传入的DTO直接转换为实体保存,未补充后端自动填充的字段
|
||||
- **违反业务规则**:PRD要求"知识"必须有创建人,用于追溯和权限控制
|
||||
|
||||
**3. 根本原因**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 请求流程分析 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 前端请求 │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ Controller层 ────────────────────────────────────────────── │
|
||||
│ │ 接收KnowledgeDTO(不含creator_id) │
|
||||
│ ▼ │
|
||||
│ Service层 ───────────────────────────────────────────────── │
|
||||
│ │ ❌ 未从SecurityContext获取当前用户ID │
|
||||
│ │ ❌ 未设置 knowledge.setCreatorId(userId) │
|
||||
│ ▼ │
|
||||
│ Mapper层 ────────────────────────────────────────────────── │
|
||||
│ │ 执行INSERT语句 │
|
||||
│ ▼ │
|
||||
│ MySQL ───────────────────────────────────────────────────── │
|
||||
│ │ creator_id字段为NULL,违反NOT NULL约束 │
|
||||
│ ▼ │
|
||||
│ ❌ 抛出异常:Field 'creator_id' doesn't have a default value │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 解决方案
|
||||
|
||||
**方案一:在Service层补充用户ID设置(推荐)**
|
||||
|
||||
修改位置:`KnowledgeServiceImpl.createKnowledge()` 方法
|
||||
|
||||
修改逻辑:
|
||||
1. 注入 `HttpServletRequest` 或创建 `SecurityUtil` 工具类
|
||||
2. 从JWT Token中解析当前登录用户ID
|
||||
3. 在保存实体前设置 `knowledge.setCreatorId(currentUserId)`
|
||||
4. 同时设置 `knowledge.setDepartmentId(userDepartmentId)` 确保部门隔离
|
||||
|
||||
**方案二:使用MyBatis Plus自动填充**
|
||||
|
||||
配置 `MetaObjectHandler` 实现字段自动填充:
|
||||
1. 在 `creator_id` 字段上添加 `@TableField(fill = FieldFill.INSERT)` 注解
|
||||
2. 实现 `MetaObjectHandler.insertFill()` 方法,自动填充创建人ID
|
||||
|
||||
**推荐方案**:方案一,显式设置更清晰,便于维护和调试。
|
||||
|
||||
---
|
||||
|
||||
### 2.2 BUG-KM-002:讲师可以操作其他部门的分类
|
||||
|
||||
#### 基本信息
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-KM-002 |
|
||||
| 严重程度 | 高(High) |
|
||||
| 优先级 | P1 - 紧急修复 |
|
||||
| 缺陷类型 | 安全漏洞 / 权限控制缺陷 |
|
||||
| 影响范围 | 部门数据隔离完全失效 |
|
||||
|
||||
#### 原因分析
|
||||
|
||||
**1. PRD业务规则**
|
||||
|
||||
根据PRD文档第4.1节"权限规则":
|
||||
|
||||
```
|
||||
讲师:
|
||||
├── 管理本部门知识库(上传/编辑/删除)
|
||||
├── 管理本部门题库(增删改查)
|
||||
...
|
||||
```
|
||||
|
||||
根据PRD文档第4.4节"数据隔离规则":
|
||||
|
||||
| 数据类型 | 隔离方式 |
|
||||
|----------|----------|
|
||||
| 知识库 | 按部门隔离,只能看本部门 |
|
||||
| 题库 | 按部门隔离,讲师只能操作本部门 |
|
||||
|
||||
**2. 权限校验缺失**
|
||||
|
||||
`CategoryService` 和 `CategoryController` 中没有实现以下校验逻辑:
|
||||
|
||||
- 未校验当前用户角色(管理员 vs 讲师)
|
||||
- 未校验请求中的 `departmentId` 与当前用户所属部门是否一致
|
||||
- 直接信任前端传入的 `departmentId` 参数
|
||||
|
||||
**3. 根本原因**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 权限校验缺失分析 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 讲师(部门1)发起请求 │
|
||||
│ │ │
|
||||
│ │ POST /api/knowledge/category │
|
||||
│ │ Body: { "name": "xxx", "departmentId": 2 } ← 伪造部门 │
|
||||
│ ▼ │
|
||||
│ Controller层 ────────────────────────────────────────────── │
|
||||
│ │ ❌ 未校验用户角色 │
|
||||
│ │ ❌ 未校验departmentId权限 │
|
||||
│ ▼ │
|
||||
│ Service层 ───────────────────────────────────────────────── │
|
||||
│ │ ❌ 直接保存,未做部门隔离校验 │
|
||||
│ ▼ │
|
||||
│ 数据库 ──────────────────────────────────────────────────── │
|
||||
│ │ 分类创建成功,department_id = 2 │
|
||||
│ ▼ │
|
||||
│ ❌ 安全漏洞:讲师越权操作其他部门数据 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 解决方案
|
||||
|
||||
**方案一:Service层统一校验(推荐)**
|
||||
|
||||
在 `CategoryServiceImpl` 中增加部门权限校验:
|
||||
|
||||
```
|
||||
校验逻辑伪代码:
|
||||
1. 获取当前用户信息(ID、角色、部门ID)
|
||||
2. IF 角色 == ADMIN:
|
||||
允许操作任意部门
|
||||
ELSE IF 角色 == LECTURER:
|
||||
IF 请求的departmentId != 用户的departmentId:
|
||||
抛出异常:"无权操作其他部门数据"
|
||||
END IF
|
||||
END IF
|
||||
3. 继续执行业务逻辑
|
||||
```
|
||||
|
||||
**方案二:AOP切面统一拦截**
|
||||
|
||||
创建 `@DepartmentIsolation` 注解 + 切面类:
|
||||
1. 在需要部门隔离的方法上添加注解
|
||||
2. 切面自动校验当前用户部门与请求部门是否一致
|
||||
|
||||
**方案三:封装通用工具方法**
|
||||
|
||||
创建 `DepartmentPermissionUtil.checkPermission(Long targetDepartmentId)` 方法:
|
||||
- 供各模块(知识库、题库、试卷等)复用
|
||||
- 统一的异常处理和错误提示
|
||||
|
||||
**推荐方案**:方案一 + 方案三结合,在Service层显式调用校验方法,逻辑清晰,便于维护。
|
||||
|
||||
---
|
||||
|
||||
### 2.3 BUG-KM-003:文件上传功能异常
|
||||
|
||||
#### 基本信息
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-KM-003 |
|
||||
| 严重程度 | 高(High) |
|
||||
| 优先级 | P1 - 紧急修复 |
|
||||
| 错误码 | 1501 |
|
||||
| 错误信息 | `{"code":1501,"message":"文件保存失败"}` |
|
||||
| 影响范围 | 所有文档/视频上传功能不可用 |
|
||||
|
||||
#### 原因分析
|
||||
|
||||
**1. 可能原因一:配置问题**
|
||||
|
||||
`application.yml` 或 `application-dev.yml` 中文件上传路径配置问题:
|
||||
- 路径未配置
|
||||
- 路径配置错误(如使用了Linux路径分隔符但运行在Windows环境)
|
||||
- 使用了相对路径但基准目录不正确
|
||||
|
||||
**2. 可能原因二:目录不存在**
|
||||
|
||||
配置的上传目录在服务器/本地环境中不存在:
|
||||
- 开发环境与生产环境路径不一致
|
||||
- 服务首次启动时未自动创建目录
|
||||
|
||||
**3. 可能原因三:权限不足**
|
||||
|
||||
应用程序对目标目录没有写入权限:
|
||||
- Linux环境下目录权限设置不正确
|
||||
- Windows环境下目录被其他程序占用或权限受限
|
||||
|
||||
**4. 可能原因四:代码健壮性问题**
|
||||
|
||||
`FileService` 实现中缺少健壮性处理:
|
||||
- 未在保存文件前检查/创建目录
|
||||
- 异常处理过于笼统,丢失了原始错误信息
|
||||
|
||||
**5. 根本原因推测**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 文件上传失败分析 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 上传请求 │
|
||||
│ │ │
|
||||
│ │ POST /api/file/upload/document │
|
||||
│ │ Content-Type: multipart/form-data │
|
||||
│ ▼ │
|
||||
│ FileController ──────────────────────────────────────────── │
|
||||
│ │ 接收MultipartFile │
|
||||
│ ▼ │
|
||||
│ FileService ─────────────────────────────────────────────── │
|
||||
│ │ 读取配置的上传路径 │
|
||||
│ │ 拼接完整文件路径 │
|
||||
│ ▼ │
|
||||
│ 文件系统 ────────────────────────────────────────────────── │
|
||||
│ │ │
|
||||
│ │ ❌ 可能问题1:目录不存在 │
|
||||
│ │ ❌ 可能问题2:无写入权限 │
|
||||
│ │ ❌ 可能问题3:路径格式错误 │
|
||||
│ ▼ │
|
||||
│ 抛出IOException → 捕获后返回统一错误码1501 │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 解决方案
|
||||
|
||||
**步骤一:检查配置文件**
|
||||
|
||||
检查 `application.yml` 和 `application-dev.yml`:
|
||||
|
||||
```yaml
|
||||
# 期望的配置格式示例
|
||||
file:
|
||||
upload:
|
||||
path: D:/upload/training-system/ # Windows
|
||||
# path: /data/upload/training-system/ # Linux
|
||||
max-size: 100MB
|
||||
allowed-types: pdf,doc,docx,xls,xlsx,ppt,pptx,mp4,avi
|
||||
```
|
||||
|
||||
**步骤二:检查FileService实现**
|
||||
|
||||
确保在保存文件前创建目录:
|
||||
|
||||
```
|
||||
伪代码:
|
||||
1. 获取配置的上传路径 uploadPath
|
||||
2. 生成唯一文件名(如:UUID + 原始扩展名)
|
||||
3. 拼接完整路径 fullPath = uploadPath + "/" + fileName
|
||||
4. 获取父目录 parentDir = fullPath.getParent()
|
||||
5. IF 父目录不存在:
|
||||
创建目录(包含所有父目录)
|
||||
END IF
|
||||
6. 保存文件到 fullPath
|
||||
7. 返回文件访问URL
|
||||
```
|
||||
|
||||
**步骤三:增加详细日志**
|
||||
|
||||
在FileService中增加关键日志输出:
|
||||
|
||||
```
|
||||
日志内容:
|
||||
- [INFO] 配置的上传路径: {uploadPath}
|
||||
- [INFO] 生成的文件名: {fileName}
|
||||
- [INFO] 完整保存路径: {fullPath}
|
||||
- [ERROR] 文件保存失败: {具体异常信息和堆栈}
|
||||
```
|
||||
|
||||
**步骤四:检查目录权限**
|
||||
|
||||
- **Linux环境**:
|
||||
```bash
|
||||
mkdir -p /data/upload/training-system
|
||||
chown -R tomcat:tomcat /data/upload
|
||||
chmod -R 755 /data/upload
|
||||
```
|
||||
|
||||
- **Windows环境**:
|
||||
确保运行Java应用的用户对目标目录有完全控制权限
|
||||
|
||||
**步骤五:启动时自动创建目录**
|
||||
|
||||
在应用启动时(如 `@PostConstruct` 方法)检查并创建上传目录:
|
||||
|
||||
```
|
||||
伪代码:
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
File uploadDir = new File(uploadPath);
|
||||
if (!uploadDir.exists()) {
|
||||
boolean created = uploadDir.mkdirs();
|
||||
log.info("创建上传目录: {}, 结果: {}", uploadPath, created);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、修复优先级与建议
|
||||
|
||||
### 3.1 修复优先级
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────────────────┐
|
||||
│ 修复优先级路线图 │
|
||||
├──────────────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ 优先级1 ───────────────────────────────────────────────────────────── │
|
||||
│ │ │
|
||||
│ │ BUG-KM-001: creator_id未设置 │
|
||||
│ │ 原因: 阻断级缺陷,整个知识创建功能不可用 │
|
||||
│ │ 影响: 15个测试用例被阻塞 │
|
||||
│ │ 建议: 立即修复,修复后重新执行全部阻塞用例 │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ 优先级2 ───────────────────────────────────────────────────────────── │
|
||||
│ │ │
|
||||
│ │ BUG-KM-003: 文件上传失败 │
|
||||
│ │ 原因: 知识库核心功能依赖文件上传 │
|
||||
│ │ 影响: 无法上传文档和视频 │
|
||||
│ │ 建议: 紧急修复,排查配置和目录权限问题 │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ 优先级3 ───────────────────────────────────────────────────────────── │
|
||||
│ │ │
|
||||
│ │ BUG-KM-002: 部门隔离未实现 │
|
||||
│ │ 原因: 安全漏洞,违反业务规则 │
|
||||
│ │ 影响: 讲师可越权操作其他部门数据 │
|
||||
│ │ 建议: 紧急修复,需全面审查相关模块 │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ 回归测试 ──────────────────────────────────────────────────────────── │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.2 风险提示
|
||||
|
||||
| 风险点 | 说明 | 建议 |
|
||||
|--------|------|------|
|
||||
| 同类缺陷 | 其他模块(考试、培训计划)可能存在相同的 `creator_id` 未设置问题 | 修复时同步审查相关模块 |
|
||||
| 部门隔离 | 题库、试卷、考试模块可能也缺少部门隔离校验 | 建议封装统一的部门权限校验工具 |
|
||||
| 配置管理 | 文件上传路径在不同环境可能不一致 | 使用环境变量或配置中心管理 |
|
||||
|
||||
### 3.3 测试建议
|
||||
|
||||
修复完成后需执行以下测试:
|
||||
|
||||
1. **BUG-KM-001修复后**:
|
||||
- 重新执行KS系列全部8个用例
|
||||
- 重新执行KD系列全部4个用例
|
||||
- 重新执行KC-003用例
|
||||
|
||||
2. **BUG-KM-002修复后**:
|
||||
- 重新执行KC-004用例
|
||||
- 新增测试用例:验证管理员可操作所有部门
|
||||
- 新增测试用例:验证学员无法创建分类
|
||||
|
||||
3. **BUG-KM-003修复后**:
|
||||
- 重新执行KM系列全部7个用例
|
||||
- 测试不同文件类型(PDF、Word、Excel、PPT、视频)
|
||||
- 测试边界条件(大文件、空文件、特殊字符文件名)
|
||||
|
||||
---
|
||||
|
||||
## 四、总结
|
||||
|
||||
### 4.1 缺陷共性分析
|
||||
|
||||
本次知识库模块测试发现的3个缺陷存在共同特点:
|
||||
|
||||
| 共性问题 | 具体表现 | 改进建议 |
|
||||
|---------|---------|---------|
|
||||
| **后端逻辑不完善** | 未实现PRD要求的业务规则 | 开发前充分理解PRD,Code Review时对照检查 |
|
||||
| **安全意识不足** | 部门隔离未实现,信任前端参数 | 后端必须校验所有涉及权限的参数 |
|
||||
| **健壮性欠缺** | 文件上传未处理目录不存在的情况 | 增加防御性编程,完善异常处理 |
|
||||
|
||||
### 4.2 后续行动项
|
||||
|
||||
- [ ] 修复BUG-KM-001:补充creator_id设置逻辑
|
||||
- [ ] 修复BUG-KM-002:实现部门隔离校验
|
||||
- [ ] 修复BUG-KM-003:排查并修复文件上传问题
|
||||
- [ ] 审查其他模块是否存在同类问题
|
||||
- [ ] 封装通用的部门权限校验工具类
|
||||
- [ ] 回归测试验证修复效果
|
||||
|
||||
---
|
||||
|
||||
**报告生成时间**:2026-01-12
|
||||
|
||||
**审核状态**:待修复
|
||||
@@ -0,0 +1,217 @@
|
||||
# 复测报告 - 模块1.3:员工管理
|
||||
|
||||
> 复测日期:2026-01-09
|
||||
> 测试人员:AI测试工程师
|
||||
> 测试环境:Spring Boot 3.1.2 / MySQL 8.0 / JDK 17
|
||||
> 原始测试报告:TestReport_1.3_UserManagement.md
|
||||
|
||||
---
|
||||
|
||||
## 一、复测概要
|
||||
|
||||
| 项目 | 数值 |
|
||||
|------|------|
|
||||
| 原始缺陷数 | 3 |
|
||||
| 复测通过 | 2 |
|
||||
| 复测失败 | 1 |
|
||||
| **修复率** | **66.7%** |
|
||||
|
||||
---
|
||||
|
||||
## 二、缺陷复测结果
|
||||
|
||||
| 缺陷编号 | 严重程度 | 描述 | 复测结果 |
|
||||
|---------|---------|------|---------|
|
||||
| BUG-USER-001 | 中 | 手机号未做唯一性校验 | ✅ **通过** |
|
||||
| BUG-USER-002 | 高 | 讲师未实现部门数据隔离 | ❌ **失败** |
|
||||
| BUG-USER-003 | 严重 | 学员可访问员工管理接口 | ✅ **通过** |
|
||||
|
||||
---
|
||||
|
||||
## 三、复测详情
|
||||
|
||||
### 3.1 BUG-USER-001:手机号唯一性校验 ✅
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 复测结果 | **通过** |
|
||||
| 测试步骤 | 1. 管理员登录<br>2. 使用已存在的手机号`13800138000`创建新员工<br>3. 验证返回结果 |
|
||||
| 预期结果 | 返回错误,提示手机号已存在 |
|
||||
| 实际结果 | 返回 `{"code":1005,"message":"手机号已存在"}` |
|
||||
| 验证时间 | 2026-01-09 15:55:44 |
|
||||
|
||||
**测试请求:**
|
||||
```bash
|
||||
POST /api/system/user
|
||||
{
|
||||
"username": "duplicate_phone_test",
|
||||
"password": "Test@123",
|
||||
"realName": "DuplicatePhoneTest",
|
||||
"phone": "13800138000", # 与admin重复
|
||||
"role": "STUDENT",
|
||||
"departmentId": 1
|
||||
}
|
||||
```
|
||||
|
||||
**测试响应:**
|
||||
```json
|
||||
{
|
||||
"code": 1005,
|
||||
"message": "手机号已存在",
|
||||
"timestamp": 1767945744357,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.2 BUG-USER-002:讲师部门数据隔离 ❌
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 复测结果 | **失败** |
|
||||
| 测试步骤 | 1. 讲师账号登录(救援一部,departmentId=1)<br>2. 访问员工管理分页接口<br>3. 验证返回的员工列表 |
|
||||
| 预期结果 | 只返回救援一部的员工(5人) |
|
||||
| 实际结果 | 返回全部7个员工,包含救援二部的admin和zhangsan |
|
||||
| 验证时间 | 2026-01-09 15:56:02 |
|
||||
|
||||
**测试请求:**
|
||||
```bash
|
||||
GET /api/system/user/page?current=1&size=10
|
||||
Authorization: Bearer {test_lecturer_token}
|
||||
```
|
||||
|
||||
**测试响应(关键数据):**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"total": 7,
|
||||
"records": [
|
||||
{"id": 7, "realName": "TestLecturer", "departmentName": "救援一部"},
|
||||
{"id": 6, "realName": "TestAdmin", "departmentName": "救援一部"},
|
||||
{"id": 5, "realName": "TestUser002", "departmentName": "救援一部"},
|
||||
{"id": 4, "realName": "TestUser001", "departmentName": "救援一部"},
|
||||
{"id": 3, "realName": "讲师", "departmentName": "救援一部"},
|
||||
{"id": 2, "realName": "张三", "departmentName": "救援二部"}, // ❌ 不应返回
|
||||
{"id": 1, "realName": "系统管理员", "departmentName": "救援二部"} // ❌ 不应返回
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**问题分析:**
|
||||
讲师查询员工列表时,后端未根据当前用户的部门ID过滤数据,导致讲师可以看到所有部门的员工信息。
|
||||
|
||||
**修复建议:**
|
||||
在 `UserServiceImpl.page()` 方法中,当当前用户角色为 `LECTURER` 时,自动在查询条件中添加部门过滤:
|
||||
```java
|
||||
if (currentUser.getRole() == Role.LECTURER) {
|
||||
queryWrapper.eq("department_id", currentUser.getDepartmentId());
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.3 BUG-USER-003:学员访问权限控制 ✅
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 复测结果 | **通过** |
|
||||
| 测试步骤 | 1. 学员账号登录<br>2. 访问员工管理分页接口<br>3. 验证返回结果 |
|
||||
| 预期结果 | 返回403 Forbidden |
|
||||
| 实际结果 | 返回 `{"code":403,"message":"没有操作权限"}` |
|
||||
| 验证时间 | 2026-01-09 15:56:22 |
|
||||
|
||||
**测试请求:**
|
||||
```bash
|
||||
GET /api/system/user/page?current=1&size=10
|
||||
Authorization: Bearer {test_user_001_token}
|
||||
```
|
||||
|
||||
**测试响应:**
|
||||
```json
|
||||
{
|
||||
"code": 403,
|
||||
"message": "没有操作权限",
|
||||
"timestamp": 1767945782146,
|
||||
"success": false
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、回归测试(原通过用例确认)
|
||||
|
||||
为确保修复未引入新问题,对原测试报告中通过的4个用例进行回归验证:
|
||||
|
||||
| 用例编号 | 测试项 | 回归结果 |
|
||||
|---------|--------|---------|
|
||||
| USER-001 | 创建员工(有效数据) | ✅ 通过(新员工创建正常) |
|
||||
| USER-003 | 启用/禁用员工 | ✅ 通过(状态切换正常) |
|
||||
| USER-004 | 编辑员工信息 | ✅ 通过(编辑功能正常) |
|
||||
| USER-005 | 删除员工 | ✅ 通过(删除功能正常) |
|
||||
|
||||
---
|
||||
|
||||
## 五、测试结论
|
||||
|
||||
### 5.1 复测结果总结
|
||||
|
||||
| 评估项 | 结果 |
|
||||
|--------|------|
|
||||
| 缺陷修复率 | 66.7%(2/3) |
|
||||
| P0级缺陷修复 | 1/1 已修复 |
|
||||
| P1级缺陷修复 | 0/1 未修复 |
|
||||
| P2级缺陷修复 | 1/1 已修复 |
|
||||
| 回归测试 | 全部通过(无新增问题) |
|
||||
|
||||
### 5.2 遗留问题
|
||||
|
||||
| 缺陷编号 | 严重程度 | 状态 | 说明 |
|
||||
|---------|---------|------|------|
|
||||
| BUG-USER-002 | 高 | **待修复** | 讲师部门数据隔离仍未实现 |
|
||||
|
||||
### 5.3 模块状态评估
|
||||
|
||||
| 功能项 | 状态 |
|
||||
|--------|------|
|
||||
| 员工CRUD基本功能 | ✅ 可用 |
|
||||
| 数据唯一性校验 | ✅ 已实现 |
|
||||
| 学员权限控制 | ✅ 已实现 |
|
||||
| 讲师数据隔离 | ❌ 未实现 |
|
||||
|
||||
### 5.4 建议
|
||||
|
||||
1. **BUG-USER-002 需要继续修复**
|
||||
- 问题影响:讲师可查看其他部门员工信息,违反PRD中的数据隔离要求
|
||||
- 安全风险:中等(信息泄露)
|
||||
- 建议优先级:P1
|
||||
|
||||
2. **建议扩展验证**
|
||||
- 修复后同时验证讲师创建/编辑/删除员工时的部门隔离是否生效
|
||||
|
||||
---
|
||||
|
||||
## 六、附录
|
||||
|
||||
### 6.1 测试账号
|
||||
|
||||
| 账号 | 角色 | 部门 |
|
||||
|------|------|------|
|
||||
| admin | ADMIN | 救援二部 |
|
||||
| test_lecturer | LECTURER | 救援一部 |
|
||||
| test_user_001 | STUDENT | 救援一部 |
|
||||
|
||||
### 6.2 相关文档
|
||||
|
||||
| 文档 | 路径 |
|
||||
|------|------|
|
||||
| 原始测试报告 | docs/test-reports/TestReport_1.3_UserManagement.md |
|
||||
| 产品需求文档 | docs/PRD.md |
|
||||
|
||||
---
|
||||
|
||||
**报告生成时间:** 2026-01-09 15:58:00
|
||||
|
||||
**报告签发:** AI测试工程师
|
||||
@@ -0,0 +1,374 @@
|
||||
1# 复测报告 - 模块1.3:员工管理(V2)
|
||||
|
||||
> 复测日期:2026-01-09
|
||||
> 测试人员:AI测试工程师
|
||||
> 测试环境:Spring Boot 3.1.2 / MySQL 8.0 / JDK 17
|
||||
> 原始测试报告:TestReport_1.3_UserManagement.md
|
||||
> 版本:V2(补充深度测试)
|
||||
|
||||
---
|
||||
|
||||
## 一、复测概要
|
||||
|
||||
| 项目 | 数值 |
|
||||
|------|------|
|
||||
| 原始缺陷数 | 3 |
|
||||
| 复测通过 | 2 |
|
||||
| 复测失败 | 1 |
|
||||
| **新发现问题** | **2** |
|
||||
| **修复率** | **66.7%** |
|
||||
|
||||
---
|
||||
|
||||
## 二、原始缺陷复测结果
|
||||
|
||||
| 缺陷编号 | 严重程度 | 描述 | 复测结果 |
|
||||
|---------|---------|------|---------|
|
||||
| BUG-USER-001 | 中 | 手机号未做唯一性校验 | ✅ **通过** |
|
||||
| BUG-USER-002 | 高 | 讲师未实现部门数据隔离 | ❌ **失败** |
|
||||
| BUG-USER-003 | 严重 | 学员可访问员工管理接口 | ✅ **通过** |
|
||||
|
||||
---
|
||||
|
||||
## 三、深度测试发现的新问题
|
||||
|
||||
### 3.1 BUG-USER-004:编辑员工时无法修改状态(后端Bug,非前端问题)
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-USER-004 |
|
||||
| 严重程度 | **高** |
|
||||
| 优先级 | P1 |
|
||||
| 缺陷类型 | **后端Bug** |
|
||||
| 缺陷描述 | 通过编辑员工接口(PUT /api/system/user)传入status字段,接口返回成功,但状态未被更新 |
|
||||
| 重现步骤 | 1. 管理员登录<br>2. 前端编辑员工,状态选择"禁用"<br>3. 点击保存,提示"保存成功"<br>4. 刷新页面,状态仍为"启用" |
|
||||
| 预期结果 | 员工状态变为"禁用" |
|
||||
| 实际结果 | 员工状态仍为"启用",状态修改被静默忽略 |
|
||||
| 根因分析 | **后端问题**:UserDTO类中没有定义status字段,updateUser()方法也未处理状态更新 |
|
||||
| 影响范围 | 前端编辑表单中的状态选择功能完全无效,用户体验严重受损 |
|
||||
|
||||
#### 前端代码验证 ✅
|
||||
|
||||
前端代码**正确传递了status字段**(user.html:139):
|
||||
```javascript
|
||||
const data = {
|
||||
realName: ...,
|
||||
phone: ...,
|
||||
username: ...,
|
||||
departmentId: ...,
|
||||
groupId: ...,
|
||||
role: ...,
|
||||
status: document.getElementById('formStatus').value // ✅ 前端正确传递
|
||||
};
|
||||
```
|
||||
|
||||
#### 问题定位
|
||||
|
||||
| 层级 | 状态 | 说明 |
|
||||
|------|------|------|
|
||||
| 前端页面 | ✅ 正常 | 有状态选择下拉框,正确绑定值 |
|
||||
| 前端JS | ✅ 正常 | saveData()正确收集status并发送 |
|
||||
| 后端DTO | ❌ 缺失 | UserDTO没有status字段,Jackson忽略该值 |
|
||||
| 后端Service | ❌ 未处理 | updateUser()没有setStatus()调用 |
|
||||
|
||||
**测试请求:**
|
||||
```bash
|
||||
PUT /api/system/user
|
||||
Content-Type: application/json
|
||||
{
|
||||
"id": 5,
|
||||
"username": "test_user_002",
|
||||
"realName": "TestUser002",
|
||||
"phone": "13800138001",
|
||||
"role": "STUDENT",
|
||||
"departmentId": 1,
|
||||
"status": "DISABLED" // 尝试修改状态
|
||||
}
|
||||
```
|
||||
|
||||
**测试响应:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "操作成功",
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
**验证查询结果:**
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": 5,
|
||||
"status": "ENABLED", // 状态未改变!
|
||||
"statusName": "启用"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**修复建议(二选一):**
|
||||
|
||||
**方案A:在UserDTO中添加status字段**
|
||||
```java
|
||||
// UserDTO.java
|
||||
private String status;
|
||||
|
||||
// UserServiceImpl.updateUser()
|
||||
if (StrUtil.isNotBlank(dto.getStatus())) {
|
||||
user.setStatus(UserStatus.valueOf(dto.getStatus()));
|
||||
}
|
||||
```
|
||||
|
||||
**方案B:明确API设计,状态修改只能通过专用接口**
|
||||
- 保持现有设计,状态只能通过 `/enable` 和 `/disable` 接口修改
|
||||
- 但需在API文档中明确说明
|
||||
- 前端编辑表单应隐藏或禁用状态选项
|
||||
|
||||
---
|
||||
|
||||
### 3.2 BUG-USER-002 根因深入分析
|
||||
|
||||
**问题:** 讲师部门数据隔离未生效
|
||||
|
||||
**代码追踪:**
|
||||
|
||||
1. **Service层代码正确**(UserServiceImpl.java:397-406)
|
||||
```java
|
||||
private void applyDepartmentIsolation(LambdaQueryWrapper<User> queryWrapper) {
|
||||
UserContext currentUser = UserContextHolder.getContext();
|
||||
if (currentUser != null && UserRole.LECTURER.name().equals(currentUser.getRole())) {
|
||||
if (currentUser.getDepartmentId() != null) { // 问题:departmentId为null
|
||||
queryWrapper.eq(User::getDepartmentId, currentUser.getDepartmentId());
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **问题根源**(JwtUtils.java:37-48)
|
||||
```java
|
||||
public String generateToken(Long userId, String username, String role) {
|
||||
return JWT.create()
|
||||
.withSubject(String.valueOf(userId))
|
||||
.withClaim("username", username)
|
||||
.withClaim("role", role) // 只有这三个字段!
|
||||
.withIssuedAt(now)
|
||||
.withExpiresAt(expireDate)
|
||||
.sign(Algorithm.HMAC256(secret));
|
||||
}
|
||||
// 没有包含 departmentId!
|
||||
```
|
||||
|
||||
3. **AuthInterceptor尝试获取但失败**(AuthInterceptor.java:68-70)
|
||||
```java
|
||||
if (jwt.getClaim("departmentId") != null && !jwt.getClaim("departmentId").isNull()) {
|
||||
context.setDepartmentId(jwt.getClaim("departmentId").asLong());
|
||||
}
|
||||
// 由于JWT中没有departmentId,这段代码不会执行
|
||||
```
|
||||
|
||||
**修复建议:**
|
||||
|
||||
修改 `JwtUtils.generateToken()` 方法,添加 departmentId 参数:
|
||||
```java
|
||||
public String generateToken(Long userId, String username, String role, Long departmentId) {
|
||||
return JWT.create()
|
||||
.withSubject(String.valueOf(userId))
|
||||
.withClaim("username", username)
|
||||
.withClaim("role", role)
|
||||
.withClaim("departmentId", departmentId) // 新增
|
||||
.withIssuedAt(now)
|
||||
.withExpiresAt(expireDate)
|
||||
.sign(Algorithm.HMAC256(secret));
|
||||
}
|
||||
```
|
||||
|
||||
同时修改 `AuthServiceImpl.login()` 方法,传入 departmentId。
|
||||
|
||||
---
|
||||
|
||||
## 四、重置密码功能验证 ✅
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 测试结果 | **通过** |
|
||||
| 测试步骤 | 1. 管理员调用重置密码接口<br>2. 使用新密码登录<br>3. 使用旧密码登录 |
|
||||
| 实际结果 | 新密码登录成功,旧密码登录失败(返回1003密码错误) |
|
||||
|
||||
**测试详情:**
|
||||
|
||||
```bash
|
||||
# 重置密码
|
||||
PUT /api/system/user/password/reset
|
||||
{"userId": 5, "newPassword": "NewPass@123"}
|
||||
Response: {"code": 200, "message": "操作成功"}
|
||||
|
||||
# 新密码登录
|
||||
POST /api/auth/login
|
||||
{"username": "test_user_002", "password": "NewPass@123"}
|
||||
Response: {"code": 200, "data": {"token": "..."}} ✅
|
||||
|
||||
# 旧密码登录(验证旧密码失效)
|
||||
POST /api/auth/login
|
||||
{"username": "test_user_002", "password": "Test@123"}
|
||||
Response: {"code": 1003, "message": "密码错误"} ✅
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、禁用/启用功能验证 ✅
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 测试结果 | **通过**(仅限专用接口) |
|
||||
| 测试步骤 | 1. 调用 PUT /api/system/user/{id}/disable<br>2. 查询用户状态<br>3. 调用 PUT /api/system/user/{id}/enable<br>4. 查询用户状态 |
|
||||
| 实际结果 | 专用接口可正常切换状态 |
|
||||
|
||||
**测试详情:**
|
||||
|
||||
```bash
|
||||
# 禁用用户
|
||||
PUT /api/system/user/5/disable
|
||||
Response: {"code": 200, "message": "操作成功"}
|
||||
|
||||
# 验证状态
|
||||
GET /api/system/user/5
|
||||
Response: {"data": {"status": "DISABLED", "statusName": "禁用"}} ✅
|
||||
|
||||
# 启用用户
|
||||
PUT /api/system/user/5/enable
|
||||
Response: {"code": 200, "message": "操作成功"}
|
||||
|
||||
# 验证状态
|
||||
GET /api/system/user/5
|
||||
Response: {"data": {"status": "ENABLED", "statusName": "启用"}} ✅
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、漏测原因分析
|
||||
|
||||
### 6.1 为什么会漏测"编辑状态"功能?
|
||||
|
||||
| 原因类型 | 具体分析 |
|
||||
|---------|---------|
|
||||
| **测试用例设计不完整** | 原测试计划只验证了"启用/禁用"功能是否存在,但没有验证"通过编辑接口修改状态"的场景 |
|
||||
| **测试路径覆盖不足** | 系统提供了两种修改状态的路径:1) 专用接口 2) 编辑接口。只测试了路径1 |
|
||||
| **接口返回值未深入验证** | 编辑接口返回200成功,测试人员信任了返回值而没有二次查询确认 |
|
||||
| **前后端交互场景遗漏** | 没有模拟前端表单的实际交互流程,即"编辑时同时修改状态" |
|
||||
|
||||
### 6.2 为什么会漏测"重置密码验证"?
|
||||
|
||||
| 原因类型 | 具体分析 |
|
||||
|---------|---------|
|
||||
| **验证不完整** | 原测试只验证了接口返回200,没有验证密码是否真的被修改 |
|
||||
| **缺少端到端验证** | 应该用新密码登录验证,同时用旧密码登录确认失效 |
|
||||
|
||||
### 6.3 为什么BUG-USER-002未修复但代码似乎已添加?
|
||||
|
||||
| 原因类型 | 具体分析 |
|
||||
|---------|---------|
|
||||
| **修复不完整** | 开发在Service层添加了部门隔离逻辑,但忽略了JWT中缺少departmentId |
|
||||
| **缺少集成测试** | 单元测试可能通过(因为可以mock UserContext),但集成测试会失败 |
|
||||
| **代码审查疏漏** | JWT Token生成和解析的链路未被完整审查 |
|
||||
|
||||
### 6.4 改进建议
|
||||
|
||||
1. **测试用例设计改进**
|
||||
- 对于每个字段修改,都要验证"修改前后值确实变化"
|
||||
- 对于多路径功能,所有路径都要测试
|
||||
|
||||
2. **验证方法改进**
|
||||
- 不要只信任接口返回值,要二次查询确认
|
||||
- 对于认证类功能,要进行端到端验证
|
||||
|
||||
3. **增加测试场景**
|
||||
- 正常场景 + 边界场景 + 异常场景
|
||||
- 单接口测试 + 流程测试 + 集成测试
|
||||
|
||||
---
|
||||
|
||||
## 七、缺陷汇总
|
||||
|
||||
### 7.1 现存缺陷清单
|
||||
|
||||
| 缺陷编号 | 严重程度 | 状态 | 描述 | 修复建议位置 |
|
||||
|---------|---------|------|------|-------------|
|
||||
| BUG-USER-002 | 高 | **待修复** | 讲师部门数据隔离未生效 | JwtUtils.java + AuthServiceImpl.java |
|
||||
| BUG-USER-004 | 中 | **新发现** | 编辑接口无法修改状态 | UserDTO.java + UserServiceImpl.java |
|
||||
|
||||
### 7.2 已修复缺陷
|
||||
|
||||
| 缺陷编号 | 严重程度 | 描述 |
|
||||
|---------|---------|------|
|
||||
| BUG-USER-001 | 中 | 手机号唯一性校验 ✅ |
|
||||
| BUG-USER-003 | 严重 | 学员权限控制 ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 八、测试结论
|
||||
|
||||
### 8.1 模块状态评估
|
||||
|
||||
| 功能项 | 状态 | 说明 |
|
||||
|--------|------|------|
|
||||
| 创建员工 | ✅ 可用 | |
|
||||
| 编辑员工(基本信息) | ✅ 可用 | |
|
||||
| 编辑员工(状态) | ⚠️ 部分可用 | 只能通过专用接口修改 |
|
||||
| 删除员工 | ✅ 可用 | |
|
||||
| 重置密码 | ✅ 可用 | |
|
||||
| 启用/禁用(专用接口) | ✅ 可用 | |
|
||||
| 手机号唯一性 | ✅ 已实现 | |
|
||||
| 学员权限控制 | ✅ 已实现 | |
|
||||
| 讲师数据隔离 | ❌ 未实现 | JWT缺少departmentId |
|
||||
|
||||
### 8.2 上线评估
|
||||
|
||||
**结论:建议暂缓上线**
|
||||
|
||||
**原因:**
|
||||
1. BUG-USER-002(讲师数据隔离)为高优先级安全问题,存在信息泄露风险
|
||||
2. 虽然基础CRUD功能可用,但不符合PRD中的数据隔离要求
|
||||
|
||||
### 8.3 修复优先级建议
|
||||
|
||||
| 优先级 | 缺陷编号 | 预计影响 |
|
||||
|--------|---------|---------|
|
||||
| **P0** | BUG-USER-002 | 修复后满足PRD数据隔离要求 |
|
||||
| **P2** | BUG-USER-004 | 改善用户体验,非阻塞性问题 |
|
||||
|
||||
---
|
||||
|
||||
## 九、附录
|
||||
|
||||
### 9.1 测试账号
|
||||
|
||||
| 账号 | 角色 | 部门 |
|
||||
|------|------|------|
|
||||
| admin | ADMIN | 救援二部 |
|
||||
| test_lecturer | LECTURER | 救援一部 |
|
||||
| test_user_001 | STUDENT | 救援一部 |
|
||||
| test_user_002 | STUDENT | 救援一部 |
|
||||
|
||||
### 9.2 相关代码文件
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| UserController.java | 用户管理控制器 |
|
||||
| UserServiceImpl.java | 用户服务实现,包含部门隔离逻辑 |
|
||||
| UserDTO.java | 用户数据传输对象(缺少status字段) |
|
||||
| JwtUtils.java | JWT工具类(缺少departmentId) |
|
||||
| AuthInterceptor.java | 认证拦截器 |
|
||||
|
||||
### 9.3 相关文档
|
||||
|
||||
| 文档 | 路径 |
|
||||
|------|------|
|
||||
| 原始测试报告 | docs/test-reports/TestReport_1.3_UserManagement.md |
|
||||
| 第一版复测报告 | docs/test-reports/RegressionReport_1.3_UserManagement.md |
|
||||
| 产品需求文档 | docs/PRD.md |
|
||||
|
||||
---
|
||||
|
||||
**报告生成时间:** 2026-01-09 16:45:00
|
||||
|
||||
**报告签发:** AI测试工程师
|
||||
@@ -0,0 +1,157 @@
|
||||
# 测试报告 - 1.3 员工管理模块
|
||||
|
||||
> 测试日期:2026-01-09
|
||||
> 测试人员:AI测试工程师
|
||||
> 测试环境:Spring Boot 3.1.2 / MySQL 8.0 / JDK 17
|
||||
|
||||
---
|
||||
|
||||
## 一、测试概要
|
||||
|
||||
| 项目 | 数值 |
|
||||
|------|------|
|
||||
| 测试用例总数 | 7 |
|
||||
| 通过 | 4 |
|
||||
| 失败 | 3 |
|
||||
| 阻塞 | 0 |
|
||||
| 通过率 | 57.1% |
|
||||
|
||||
---
|
||||
|
||||
## 二、测试结果详情
|
||||
|
||||
### 2.1 测试用例执行结果
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| USER-001 | 管理员创建员工 | 成功创建,指定角色和部门 | 创建成功,返回用户ID=4 | **通过** |
|
||||
| USER-002 | 创建重复手机号员工 | 提示"手机号已存在" | 创建成功,未校验手机号唯一性 | **失败** |
|
||||
| USER-003 | 分配角色(ADMIN/LECTURER/STUDENT) | 角色分配成功 | ADMIN/LECTURER/STUDENT三种角色均分配成功 | **通过** |
|
||||
| USER-004 | 禁用员工 | 状态变更为DISABLED | 状态成功变更为DISABLED | **通过** |
|
||||
| USER-005 | 启用员工 | 状态变更为ENABLED | 状态成功变更为ENABLED | **通过** |
|
||||
| USER-006 | 讲师查看本部门员工 | 只能看到本部门 | 可以看到所有部门用户(救援一部+救援二部) | **失败** |
|
||||
| USER-007 | 学员无法访问员工管理 | 返回403 | 返回200,可查看所有用户数据 | **失败** |
|
||||
|
||||
---
|
||||
|
||||
## 三、缺陷清单
|
||||
|
||||
### BUG-001:手机号未做唯一性校验
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-USER-001 |
|
||||
| 关联用例 | USER-002 |
|
||||
| 严重程度 | 中 |
|
||||
| 优先级 | P2 |
|
||||
| 缺陷描述 | 创建员工时未校验手机号是否已存在,允许重复手机号 |
|
||||
| 重现步骤 | 1. 管理员登录<br>2. 创建员工A,手机号13800138001<br>3. 创建员工B,手机号13800138001<br>4. 两个员工都创建成功 |
|
||||
| 预期结果 | 第二次创建时提示"手机号已存在" |
|
||||
| 实际结果 | 两个员工都创建成功,存在重复手机号 |
|
||||
| 建议修复 | 在UserServiceImpl.createUser()方法中添加手机号唯一性校验 |
|
||||
|
||||
---
|
||||
|
||||
### BUG-002:讲师未实现部门数据隔离
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-USER-002 |
|
||||
| 关联用例 | USER-006 |
|
||||
| 严重程度 | 高 |
|
||||
| 优先级 | P1 |
|
||||
| 缺陷描述 | 讲师角色可以查看所有部门的员工信息,未按部门隔离 |
|
||||
| 重现步骤 | 1. 讲师账号登录(部门:救援一部)<br>2. 访问GET /api/system/user/page<br>3. 返回结果包含救援一部和救援二部的员工 |
|
||||
| 预期结果 | 讲师只能看到本部门(救援一部)的员工 |
|
||||
| 实际结果 | 讲师可以看到所有部门的员工(7条记录) |
|
||||
| 建议修复 | 在UserService查询方法中根据当前用户角色和部门进行数据过滤 |
|
||||
|
||||
**测试数据截取:**
|
||||
```json
|
||||
{
|
||||
"total": 7,
|
||||
"records": [
|
||||
{"id":7, "departmentName":"救援一部"},
|
||||
{"id":6, "departmentName":"救援一部"},
|
||||
{"id":2, "departmentName":"救援二部"}, // 不应可见
|
||||
{"id":1, "departmentName":"救援二部"} // 不应可见
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### BUG-003:学员权限未控制,可访问员工管理接口
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-USER-003 |
|
||||
| 关联用例 | USER-007 |
|
||||
| 严重程度 | **严重** |
|
||||
| 优先级 | P0 |
|
||||
| 缺陷描述 | 学员角色可以访问员工管理接口,获取所有用户敏感信息 |
|
||||
| 重现步骤 | 1. 学员账号登录<br>2. 访问GET /api/system/user/page<br>3. 成功返回所有用户列表 |
|
||||
| 预期结果 | 返回403 Forbidden,拒绝访问 |
|
||||
| 实际结果 | 返回200 OK,可查看所有用户数据 |
|
||||
| 建议修复 | 1. 在UserController上添加@PreAuthorize注解限制ADMIN和LECTURER角色<br>2. 或在拦截器中根据角色过滤接口访问权限 |
|
||||
|
||||
**安全风险:** 此漏洞导致学员可以获取所有员工的手机号、用户名等敏感信息,存在信息泄露风险。
|
||||
|
||||
---
|
||||
|
||||
## 四、测试覆盖接口
|
||||
|
||||
| 接口 | 方法 | 测试状态 |
|
||||
|------|------|---------|
|
||||
| /api/system/user | POST | 已测试 |
|
||||
| /api/system/user/{id} | GET | 已测试 |
|
||||
| /api/system/user/page | GET | 已测试 |
|
||||
| /api/system/user/{id}/enable | PUT | 已测试 |
|
||||
| /api/system/user/{id}/disable | PUT | 已测试 |
|
||||
| /api/auth/login | POST | 已测试(辅助) |
|
||||
|
||||
---
|
||||
|
||||
## 五、测试数据
|
||||
|
||||
### 5.1 测试账号
|
||||
|
||||
| 用户名 | 密码 | 角色 | 部门 |
|
||||
|--------|------|------|------|
|
||||
| admin | admin123 | ADMIN | 救援二部 |
|
||||
| test_lecturer | Test@123 | LECTURER | 救援一部 |
|
||||
| test_user_001 | Test@123 | STUDENT | 救援一部 |
|
||||
|
||||
### 5.2 测试创建的数据
|
||||
|
||||
| ID | 用户名 | 角色 | 部门 |
|
||||
|----|--------|------|------|
|
||||
| 4 | test_user_001 | STUDENT | 救援一部 |
|
||||
| 5 | test_user_002 | STUDENT | 救援一部 |
|
||||
| 6 | test_admin | ADMIN | 救援一部 |
|
||||
| 7 | test_lecturer | LECTURER | 救援一部 |
|
||||
|
||||
---
|
||||
|
||||
## 六、结论与建议
|
||||
|
||||
### 6.1 测试结论
|
||||
|
||||
员工管理模块基本CRUD功能正常,但存在**3个缺陷**,其中:
|
||||
- **1个严重缺陷**(P0):学员权限未控制
|
||||
- **1个高优先级缺陷**(P1):讲师部门隔离未实现
|
||||
- **1个中优先级缺陷**(P2):手机号唯一性未校验
|
||||
|
||||
### 6.2 修复建议优先级
|
||||
|
||||
1. **P0 - 立即修复**:BUG-USER-003(学员权限控制)
|
||||
2. **P1 - 紧急修复**:BUG-USER-002(讲师部门隔离)
|
||||
3. **P2 - 计划修复**:BUG-USER-001(手机号唯一性)
|
||||
|
||||
### 6.3 阻塞问题
|
||||
|
||||
无阻塞问题,可继续进行后续模块测试。
|
||||
|
||||
---
|
||||
|
||||
**报告生成时间:** 2026-01-09 14:48:00
|
||||
177
training-system/docs/test-reports/TestReport_2.0_Knowledge.md
Normal file
177
training-system/docs/test-reports/TestReport_2.0_Knowledge.md
Normal file
@@ -0,0 +1,177 @@
|
||||
# 测试报告 - 模块二:知识库
|
||||
|
||||
> 测试日期:2026-01-09
|
||||
> 测试人员:AI测试工程师
|
||||
> 测试环境:Spring Boot 3.1.2 / MySQL 8.0 / JDK 17
|
||||
|
||||
---
|
||||
|
||||
## 一、测试概要
|
||||
|
||||
| 项目 | 数值 |
|
||||
|------|------|
|
||||
| 测试用例总数 | 19 |
|
||||
| 通过 | 2 |
|
||||
| 失败 | 2 |
|
||||
| 阻塞 | 15 |
|
||||
| 通过率 | 10.5% |
|
||||
|
||||
**注意:** 由于发现关键BUG(创建知识时creator_id未设置),导致知识创建失败,大部分测试用例被阻塞。
|
||||
|
||||
---
|
||||
|
||||
## 二、测试结果详情
|
||||
|
||||
### 2.1 知识分类测试(KC系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| KC-001 | 创建一级分类 | 成功创建 | 创建成功,返回ID=4 | **通过** |
|
||||
| KC-002 | 创建多级分类(父子关系) | 层级关系正确 | 成功创建子分类ID=5,父分类为ID=4 | **通过** |
|
||||
| KC-003 | 删除有知识的分类 | 提示"存在关联知识,无法删除" | 由于知识创建失败,无法测试 | **阻塞** |
|
||||
| KC-004 | 讲师只能管理本部门分类 | 其他部门分类不可操作 | 讲师(部门1)可以创建部门2的分类 | **失败** |
|
||||
|
||||
### 2.2 知识文档管理测试(KM系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| KM-001 | 上传PDF文档 | 上传成功 | 文件保存失败(code:1501) | **失败** |
|
||||
| KM-002 | 上传Word文档 | 上传成功 | 依赖KM-001 | **阻塞** |
|
||||
| KM-003 | 上传Excel文档 | 上传成功 | 依赖KM-001 | **阻塞** |
|
||||
| KM-004 | 上传PPT文档 | 上传成功 | 依赖KM-001 | **阻塞** |
|
||||
| KM-005 | 上传视频文件 | 上传成功 | 依赖KM-001 | **阻塞** |
|
||||
| KM-006 | 上传不支持的格式 | 提示错误 | 依赖KM-001 | **阻塞** |
|
||||
| KM-007 | 超大文件上传 | 提示错误 | 依赖KM-001 | **阻塞** |
|
||||
|
||||
### 2.3 知识状态管理测试(KS系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| KS-001 | 创建知识(默认草稿) | 状态为DRAFT | creator_id字段缺失导致失败 | **阻塞** |
|
||||
| KS-002 | 草稿→发布 | 状态变为PUBLISHED | 依赖KS-001 | **阻塞** |
|
||||
| KS-003 | 已发布→下架 | 状态变为OFFLINE | 依赖KS-001 | **阻塞** |
|
||||
| KS-004 | 已下架→重新上架 | 状态变为PUBLISHED | 依赖KS-001 | **阻塞** |
|
||||
| KS-005 | 学员查看草稿知识 | 不可见 | 依赖KS-001 | **阻塞** |
|
||||
| KS-006 | 学员查看已发布知识 | 可见 | 依赖KS-001 | **阻塞** |
|
||||
| KS-007 | 学员查看已下架知识 | 不可见 | 依赖KS-001 | **阻塞** |
|
||||
| KS-008 | 下架被培训计划引用的知识 | 显示警告确认 | 依赖KS-001 | **阻塞** |
|
||||
|
||||
### 2.4 部门隔离测试(KD系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| KD-001 | 讲师查看本部门知识 | 正常查看 | 依赖知识数据 | **阻塞** |
|
||||
| KD-002 | 讲师查看其他部门知识 | 不可见 | 依赖知识数据 | **阻塞** |
|
||||
| KD-003 | 学员查看本部门已发布知识 | 正常查看 | API可访问,但无数据 | **阻塞** |
|
||||
| KD-004 | 学员查看其他部门知识 | 不可见 | 依赖知识数据 | **阻塞** |
|
||||
|
||||
---
|
||||
|
||||
## 三、缺陷清单
|
||||
|
||||
### BUG-KM-001:创建知识时creator_id未设置
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-KM-001 |
|
||||
| 关联用例 | KS-001及所有依赖用例 |
|
||||
| 严重程度 | **阻断** |
|
||||
| 优先级 | P0 |
|
||||
| 缺陷描述 | 创建知识时未设置creator_id字段,导致数据库插入失败 |
|
||||
| 重现步骤 | 1. 管理员登录<br>2. POST /api/knowledge 创建知识<br>3. 返回500错误 |
|
||||
| 错误信息 | `Field 'creator_id' doesn't have a default value` |
|
||||
| 预期结果 | 知识创建成功,creator_id自动设置为当前登录用户ID |
|
||||
| 实际结果 | 500服务器内部错误 |
|
||||
| 建议修复 | 在KnowledgeServiceImpl.createKnowledge()方法中,从SecurityContext获取当前用户ID并设置到knowledge.setCreatorId() |
|
||||
|
||||
**影响范围:** 此BUG导致知识库模块15个测试用例被阻塞,无法继续测试。
|
||||
|
||||
---
|
||||
|
||||
### BUG-KM-002:讲师可以操作其他部门的分类
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-KM-002 |
|
||||
| 关联用例 | KC-004 |
|
||||
| 严重程度 | 高 |
|
||||
| 优先级 | P1 |
|
||||
| 缺陷描述 | 讲师角色可以创建/修改其他部门的知识分类,未实现部门隔离 |
|
||||
| 重现步骤 | 1. 讲师账号登录(部门1)<br>2. POST /api/knowledge/category 创建分类,departmentId设为2<br>3. 分类创建成功 |
|
||||
| 预期结果 | 返回403或400错误,禁止操作其他部门数据 |
|
||||
| 实际结果 | 分类创建成功,返回ID=6 |
|
||||
| 建议修复 | 在CategoryService中校验当前用户部门与操作数据部门是否一致 |
|
||||
|
||||
---
|
||||
|
||||
### BUG-KM-003:文件上传功能异常
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-KM-003 |
|
||||
| 关联用例 | KM-001 ~ KM-007 |
|
||||
| 严重程度 | 高 |
|
||||
| 优先级 | P1 |
|
||||
| 缺陷描述 | 文件上传接口返回"文件保存失败"错误 |
|
||||
| 重现步骤 | 1. 管理员登录<br>2. POST /api/file/upload/document 上传文件<br>3. 返回code:1501错误 |
|
||||
| 错误信息 | `{"code":1501,"message":"文件保存失败"}` |
|
||||
| 预期结果 | 文件上传成功,返回文件URL |
|
||||
| 实际结果 | 返回1501错误码 |
|
||||
| 建议修复 | 检查文件存储路径配置,确保上传目录存在且有写入权限 |
|
||||
|
||||
---
|
||||
|
||||
## 四、测试覆盖接口
|
||||
|
||||
| 接口 | 方法 | 测试状态 |
|
||||
|------|------|---------|
|
||||
| /api/knowledge/category | POST | 已测试 |
|
||||
| /api/knowledge/category/tree | GET | 已测试 |
|
||||
| /api/knowledge/category/{id} | DELETE | 已测试 |
|
||||
| /api/knowledge | POST | 已测试(失败) |
|
||||
| /api/knowledge/page | GET | 已测试 |
|
||||
| /api/file/upload/document | POST | 已测试(失败) |
|
||||
|
||||
---
|
||||
|
||||
## 五、测试数据
|
||||
|
||||
### 5.1 测试创建的分类数据
|
||||
|
||||
| ID | 名称 | 父分类 | 部门 | 状态 |
|
||||
|----|------|--------|------|------|
|
||||
| 4 | Safety Regulations | - | 救援一部 | 已删除 |
|
||||
| 5 | Highway Rescue | 4 | 救援一部 | 已删除 |
|
||||
| 6 | Test Category Dept2 | - | 救援二部 | 存在(异常数据) |
|
||||
|
||||
---
|
||||
|
||||
## 六、结论与建议
|
||||
|
||||
### 6.1 测试结论
|
||||
|
||||
知识库模块存在**3个严重缺陷**,其中1个为阻断级别:
|
||||
|
||||
1. **P0 阻断级**:创建知识时creator_id未设置 - 导致整个模块功能不可用
|
||||
2. **P1 高优先级**:讲师部门隔离未实现
|
||||
3. **P1 高优先级**:文件上传功能异常
|
||||
|
||||
### 6.2 修复建议优先级
|
||||
|
||||
1. **立即修复(P0)**:BUG-KM-001 - 修复后需重新执行全部阻塞用例
|
||||
2. **紧急修复(P1)**:BUG-KM-002 - 部门隔离
|
||||
3. **紧急修复(P1)**:BUG-KM-003 - 文件上传
|
||||
|
||||
### 6.3 阻塞说明
|
||||
|
||||
由于BUG-KM-001为阻断级缺陷,以下测试需要在修复后重新执行:
|
||||
- KS系列(知识状态管理):8个用例
|
||||
- KD系列(部门隔离):4个用例
|
||||
- KM系列(文件管理):6个用例
|
||||
- KC-003(删除有知识的分类):1个用例
|
||||
|
||||
**建议:** 修复BUG-KM-001后进行回归测试。
|
||||
|
||||
---
|
||||
|
||||
**报告生成时间:** 2026-01-09 14:58:00
|
||||
144
training-system/docs/test-reports/TestReport_3.0_Question.md
Normal file
144
training-system/docs/test-reports/TestReport_3.0_Question.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# 测试报告 - 模块三:考题管理
|
||||
|
||||
> 测试日期:2026-01-09
|
||||
> 测试人员:AI测试工程师
|
||||
> 测试环境:Spring Boot 3.1.2 / MySQL 8.0 / JDK 17
|
||||
|
||||
---
|
||||
|
||||
## 一、测试概要
|
||||
|
||||
| 项目 | 数值 |
|
||||
|------|------|
|
||||
| 测试用例总数 | 11 |
|
||||
| 通过 | 0 |
|
||||
| 失败 | 3 |
|
||||
| 阻塞 | 8 |
|
||||
| 通过率 | 0% |
|
||||
|
||||
**注意:** 与知识库模块相同,创建题目时也存在creator_id未设置的问题,导致大部分测试被阻塞。
|
||||
|
||||
---
|
||||
|
||||
## 二、测试结果详情
|
||||
|
||||
### 2.1 题型测试(Q系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| Q-001 | 创建单选题(4选项) | 成功创建 | creator_id字段缺失导致失败 | **阻塞** |
|
||||
| Q-002 | 创建多选题 | 成功创建 | 依赖Q-001 | **阻塞** |
|
||||
| Q-003 | 创建判断题 | 成功创建 | 依赖Q-001 | **阻塞** |
|
||||
| Q-004 | 单选题设置多个答案 | 提示错误 | 依赖Q-001 | **阻塞** |
|
||||
| Q-005 | 多选题只设置一个答案 | 提示错误 | 依赖Q-001 | **阻塞** |
|
||||
| Q-006 | 题目必须填写解析 | 提示必填 | 依赖Q-001 | **阻塞** |
|
||||
|
||||
### 2.2 题目状态管理测试(QS系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| QS-001 | 草稿题目发布 | 状态变为PUBLISHED | 依赖题目数据 | **阻塞** |
|
||||
| QS-002 | 下架被试卷引用的题目 | 显示警告确认 | 依赖题目数据 | **阻塞** |
|
||||
| QS-003 | 只有已发布题目可被组卷 | 草稿/下架题目不可选 | 依赖题目数据 | **阻塞** |
|
||||
|
||||
### 2.3 部门隔离测试(QD系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| QD-001 | 讲师只能管理本部门题库 | 其他部门不可操作 | 讲师可创建其他部门题库分类(ID=4) | **失败** |
|
||||
| QD-002 | 学员无法访问题目管理 | 返回403 | 返回200,可查询题目列表 | **失败** |
|
||||
|
||||
---
|
||||
|
||||
## 三、缺陷清单
|
||||
|
||||
### BUG-Q-001:创建题目时creator_id未设置
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-Q-001 |
|
||||
| 关联用例 | Q-001及所有依赖用例 |
|
||||
| 严重程度 | **阻断** |
|
||||
| 优先级 | P0 |
|
||||
| 缺陷描述 | 创建题目时未设置creator_id字段,导致数据库插入失败 |
|
||||
| 重现步骤 | 1. 管理员登录<br>2. POST /api/exam/question 创建题目<br>3. 返回500错误 |
|
||||
| 错误信息 | `Field 'creator_id' doesn't have a default value` |
|
||||
| 预期结果 | 题目创建成功 |
|
||||
| 实际结果 | 500服务器内部错误 |
|
||||
| 建议修复 | 在QuestionServiceImpl.createQuestion()方法中,从SecurityContext获取当前用户ID并设置到question.setCreatorId() |
|
||||
|
||||
**与BUG-KM-001为同类问题,建议统一修复。**
|
||||
|
||||
---
|
||||
|
||||
### BUG-Q-002:讲师可以操作其他部门的题库分类
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-Q-002 |
|
||||
| 关联用例 | QD-001 |
|
||||
| 严重程度 | 高 |
|
||||
| 优先级 | P1 |
|
||||
| 缺陷描述 | 讲师角色可以创建其他部门的题库分类,未实现部门隔离 |
|
||||
| 重现步骤 | 1. 讲师账号登录(部门1)<br>2. POST /api/exam/question-category 创建分类,departmentId设为2<br>3. 分类创建成功 |
|
||||
| 预期结果 | 返回403或400错误 |
|
||||
| 实际结果 | 分类创建成功,返回ID=4 |
|
||||
| 建议修复 | 在QuestionCategoryService中校验当前用户部门与操作数据部门是否一致 |
|
||||
|
||||
---
|
||||
|
||||
### BUG-Q-003:学员可以访问题目管理接口
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-Q-003 |
|
||||
| 关联用例 | QD-002 |
|
||||
| 严重程度 | **严重** |
|
||||
| 优先级 | P0 |
|
||||
| 缺陷描述 | 学员角色可以访问题目管理接口 |
|
||||
| 重现步骤 | 1. 学员账号登录<br>2. GET /api/exam/question/page<br>3. 成功返回题目列表 |
|
||||
| 预期结果 | 返回403 Forbidden |
|
||||
| 实际结果 | 返回200 OK |
|
||||
| 建议修复 | 在QuestionController上添加角色权限控制 |
|
||||
|
||||
---
|
||||
|
||||
## 四、测试覆盖接口
|
||||
|
||||
| 接口 | 方法 | 测试状态 |
|
||||
|------|------|---------|
|
||||
| /api/exam/question | POST | 已测试(失败) |
|
||||
| /api/exam/question/page | GET | 已测试 |
|
||||
| /api/exam/question-category | POST | 已测试 |
|
||||
| /api/exam/question-category/tree | GET | 已测试 |
|
||||
|
||||
---
|
||||
|
||||
## 五、结论与建议
|
||||
|
||||
### 5.1 测试结论
|
||||
|
||||
考题管理模块存在**3个缺陷**,其中2个为严重/阻断级别:
|
||||
|
||||
1. **P0 阻断级**:创建题目时creator_id未设置 - 导致整个模块功能不可用
|
||||
2. **P0 严重级**:学员权限未控制
|
||||
3. **P1 高优先级**:讲师部门隔离未实现
|
||||
|
||||
### 5.2 共性问题说明
|
||||
|
||||
此模块发现的问题与员工管理、知识库模块存在共性:
|
||||
- creator_id未设置:知识库、考题管理
|
||||
- 学员权限未控制:员工管理、题目管理
|
||||
- 讲师部门隔离未实现:知识库分类、题库分类
|
||||
|
||||
**建议进行全局修复。**
|
||||
|
||||
### 5.3 阻塞说明
|
||||
|
||||
由于BUG-Q-001为阻断级缺陷,以下测试需要在修复后重新执行:
|
||||
- Q系列(题型测试):6个用例
|
||||
- QS系列(状态管理):3个用例
|
||||
|
||||
---
|
||||
|
||||
**报告生成时间:** 2026-01-09 15:26:00
|
||||
127
training-system/docs/test-reports/TestReport_4.0_Paper.md
Normal file
127
training-system/docs/test-reports/TestReport_4.0_Paper.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# 测试报告 - 模块四:试卷管理
|
||||
|
||||
> 测试日期:2026-01-09
|
||||
> 测试人员:AI测试工程师
|
||||
> 测试环境:Spring Boot 3.1.2 / MySQL 8.0 / JDK 17
|
||||
|
||||
---
|
||||
|
||||
## 一、测试概要
|
||||
|
||||
| 项目 | 数值 |
|
||||
|------|------|
|
||||
| 测试用例总数 | 11 |
|
||||
| 通过 | 0 |
|
||||
| 失败 | 1 |
|
||||
| 阻塞 | 10 |
|
||||
| 通过率 | 0% |
|
||||
|
||||
**注意:** 与知识库、考题模块相同,创建试卷时也存在creator_id未设置的问题,导致大部分测试被阻塞。
|
||||
|
||||
---
|
||||
|
||||
## 二、测试结果详情
|
||||
|
||||
### 2.1 手动组卷测试(P系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| P-001 | 手动选择题目组卷 | 成功创建试卷 | creator_id字段缺失导致失败 | **阻塞** |
|
||||
| P-002 | 设置每题分值 | 分值设置正确 | 依赖P-001 | **阻塞** |
|
||||
| P-003 | 总分自动计算 | 各题分值之和=总分 | 依赖P-001 | **阻塞** |
|
||||
| P-004 | 设置考试时长 | 时长设置正确 | 依赖P-001 | **阻塞** |
|
||||
| P-005 | 设置及格分 | 及格分≤总分 | 依赖P-001 | **阻塞** |
|
||||
| P-006 | 及格分超过总分 | 提示错误 | 依赖P-001 | **阻塞** |
|
||||
|
||||
### 2.2 自动组卷测试(PA系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| PA-001 | 设置规则自动抽题 | 按规则随机抽取 | 依赖题目数据 | **阻塞** |
|
||||
| PA-002 | 题库数量不足 | 提示错误 | 依赖题目数据 | **阻塞** |
|
||||
| PA-003 | 自动组卷题目随机 | 多次组卷结果不同 | 依赖题目数据 | **阻塞** |
|
||||
|
||||
### 2.3 试卷预览测试(PP系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| PP-001 | 预览试卷 | 显示完整试卷内容 | 依赖试卷数据 | **阻塞** |
|
||||
|
||||
### 2.4 权限测试
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| PS-权限 | 学员无法访问试卷管理 | 返回403 | 返回200,可查询试卷列表 | **失败** |
|
||||
|
||||
---
|
||||
|
||||
## 三、缺陷清单
|
||||
|
||||
### BUG-P-001:创建试卷时creator_id未设置
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-P-001 |
|
||||
| 关联用例 | P-001及所有依赖用例 |
|
||||
| 严重程度 | **阻断** |
|
||||
| 优先级 | P0 |
|
||||
| 缺陷描述 | 创建试卷时未设置creator_id字段,导致数据库插入失败 |
|
||||
| 重现步骤 | 1. 管理员登录<br>2. POST /api/exam/paper 创建试卷<br>3. 返回500错误 |
|
||||
| 错误信息 | `Field 'creator_id' doesn't have a default value` |
|
||||
| 预期结果 | 试卷创建成功 |
|
||||
| 实际结果 | 500服务器内部错误 |
|
||||
| 建议修复 | 在PaperServiceImpl.createPaper()方法中设置creatorId |
|
||||
|
||||
**与BUG-KM-001、BUG-Q-001为同类问题。**
|
||||
|
||||
---
|
||||
|
||||
### BUG-P-002:学员可以访问试卷管理接口
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-P-002 |
|
||||
| 关联用例 | PS-权限 |
|
||||
| 严重程度 | **严重** |
|
||||
| 优先级 | P0 |
|
||||
| 缺陷描述 | 学员角色可以访问试卷管理接口 |
|
||||
| 重现步骤 | 1. 学员账号登录<br>2. GET /api/exam/paper/page<br>3. 成功返回试卷列表 |
|
||||
| 预期结果 | 返回403 Forbidden |
|
||||
| 实际结果 | 返回200 OK |
|
||||
| 建议修复 | 在PaperController上添加角色权限控制 |
|
||||
|
||||
---
|
||||
|
||||
## 四、测试覆盖接口
|
||||
|
||||
| 接口 | 方法 | 测试状态 |
|
||||
|------|------|---------|
|
||||
| /api/exam/paper | POST | 已测试(失败) |
|
||||
| /api/exam/paper/page | GET | 已测试 |
|
||||
|
||||
---
|
||||
|
||||
## 五、结论与建议
|
||||
|
||||
### 5.1 测试结论
|
||||
|
||||
试卷管理模块存在**2个缺陷**:
|
||||
|
||||
1. **P0 阻断级**:创建试卷时creator_id未设置
|
||||
2. **P0 严重级**:学员权限未控制
|
||||
|
||||
### 5.2 共性问题汇总
|
||||
|
||||
截至目前,已发现的共性问题:
|
||||
|
||||
| 问题类型 | 影响模块 |
|
||||
|---------|---------|
|
||||
| creator_id未设置 | 知识库、考题管理、试卷管理 |
|
||||
| 学员权限未控制 | 员工管理、考题管理、试卷管理 |
|
||||
| 讲师部门隔离未实现 | 知识库分类、题库分类 |
|
||||
|
||||
**建议进行全局性修复。**
|
||||
|
||||
---
|
||||
|
||||
**报告生成时间:** 2026-01-09 15:32:00
|
||||
135
training-system/docs/test-reports/TestReport_5.0_Exam.md
Normal file
135
training-system/docs/test-reports/TestReport_5.0_Exam.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# 测试报告 - 模块五:考试管理
|
||||
|
||||
> 测试日期:2026-01-09
|
||||
> 测试人员:AI测试工程师
|
||||
> 测试环境:Spring Boot 3.1.2 / MySQL 8.0 / JDK 17
|
||||
|
||||
---
|
||||
|
||||
## 一、测试概要
|
||||
|
||||
| 项目 | 数值 |
|
||||
|------|------|
|
||||
| 测试用例总数 | 20 |
|
||||
| 通过 | 1 |
|
||||
| 失败 | 1 |
|
||||
| 阻塞 | 18 |
|
||||
| 通过率 | 5% |
|
||||
|
||||
**注意:** 由于试卷创建失败,考试创建依赖试卷数据,导致绝大部分测试被阻塞。
|
||||
|
||||
---
|
||||
|
||||
## 二、测试结果详情
|
||||
|
||||
### 2.1 发布考试测试(E系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| E-001 | 创建考试,关联试卷 | 成功创建 | 返回"试卷不存在"(1302) | **阻塞** |
|
||||
| E-002 | 设置时间窗口 | 时间设置正确 | 依赖E-001 | **阻塞** |
|
||||
| E-003 | 设置及格线 | 及格线设置正确 | 依赖E-001 | **阻塞** |
|
||||
| E-004 | 设置最大考试次数 | 次数限制生效 | 依赖E-001 | **阻塞** |
|
||||
| E-005 | 指定部门参加考试 | 部门所有人可见 | 依赖E-001 | **阻塞** |
|
||||
| E-006 | 指定小组参加考试 | 小组成员可见 | 依赖E-001 | **阻塞** |
|
||||
| E-007 | 指定个人参加考试 | 仅该用户可见 | 依赖E-001 | **阻塞** |
|
||||
|
||||
### 2.2 在线答题测试(EA系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| EA-001 | 在时间窗口内进入考试 | 成功进入 | 依赖考试数据 | **阻塞** |
|
||||
| EA-002 | 不在时间窗口进入考试 | 提示错误 | 依赖考试数据 | **阻塞** |
|
||||
| EA-003 | 超过最大次数进入考试 | 提示错误 | 依赖考试数据 | **阻塞** |
|
||||
| EA-004 | 答题过程自动计时 | 倒计时正确 | 依赖考试数据 | **阻塞** |
|
||||
| EA-005 | 超时自动交卷 | 系统自动提交 | 依赖考试数据 | **阻塞** |
|
||||
| EA-006 | 主动交卷 | 成功提交 | 依赖考试数据 | **阻塞** |
|
||||
| EA-007 | 答案定时自动保存 | 答案保存成功 | 依赖考试数据 | **阻塞** |
|
||||
| EA-008 | 断网后恢复继续答题 | 可继续答题 | 依赖考试数据 | **阻塞** |
|
||||
|
||||
### 2.3 成绩计算测试(ES系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| ES-001 | 单选题判分 | 正确/错误判分 | 依赖考试数据 | **阻塞** |
|
||||
| ES-002 | 多选题判分 | 全对得分 | 依赖考试数据 | **阻塞** |
|
||||
| ES-003 | 判断题判分 | 正确/错误判分 | 依赖考试数据 | **阻塞** |
|
||||
| ES-004 | 分数≥及格线显示通过 | 显示"通过" | 依赖考试数据 | **阻塞** |
|
||||
| ES-005 | 分数<及格线显示未通过 | 显示"未通过" | 依赖考试数据 | **阻塞** |
|
||||
| ES-006 | 多次考试取最高分 | 最高分记录正确 | 依赖考试数据 | **阻塞** |
|
||||
|
||||
### 2.4 成绩查看测试(EV系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| EV-001 | 交卷后立即显示成绩 | 成绩即时显示 | 依赖考试数据 | **阻塞** |
|
||||
| EV-002 | 显示答案解析 | 每题显示解析 | 依赖考试数据 | **阻塞** |
|
||||
| EV-003 | 讲师查看本部门学员成绩 | 正常查看 | 依赖考试数据 | **阻塞** |
|
||||
|
||||
### 2.5 权限测试
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| E-学员接口 | 学员获取可参加的考试 | 返回200 | 返回200,空列表 | **通过** |
|
||||
| E-权限 | 学员访问考试管理接口 | 返回403 | 返回200,可查询考试列表 | **失败** |
|
||||
|
||||
---
|
||||
|
||||
## 三、缺陷清单
|
||||
|
||||
### BUG-E-001:学员可以访问考试管理接口
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-E-001 |
|
||||
| 关联用例 | E-权限 |
|
||||
| 严重程度 | **严重** |
|
||||
| 优先级 | P0 |
|
||||
| 缺陷描述 | 学员角色可以访问考试管理的分页查询接口 |
|
||||
| 重现步骤 | 1. 学员账号登录<br>2. GET /api/exam/page<br>3. 成功返回考试列表 |
|
||||
| 预期结果 | 返回403 Forbidden |
|
||||
| 实际结果 | 返回200 OK |
|
||||
| 建议修复 | 在ExamController的管理类接口上添加角色权限控制 |
|
||||
|
||||
---
|
||||
|
||||
## 四、测试覆盖接口
|
||||
|
||||
| 接口 | 方法 | 测试状态 |
|
||||
|------|------|---------|
|
||||
| /api/exam | POST | 已测试(阻塞-无试卷) |
|
||||
| /api/exam/page | GET | 已测试 |
|
||||
| /api/exam/my | GET | 已测试 |
|
||||
|
||||
---
|
||||
|
||||
## 五、阻塞说明
|
||||
|
||||
考试管理模块测试被阻塞的根本原因链:
|
||||
|
||||
```
|
||||
creator_id问题 → 知识/题目创建失败 → 试卷创建失败 → 考试创建失败(无试卷) → 考试流程测试全部阻塞
|
||||
```
|
||||
|
||||
**前置条件:**
|
||||
- 试卷管理模块正常(至少有一张已发布的试卷)
|
||||
- 题目管理模块正常(至少有已发布的题目)
|
||||
|
||||
---
|
||||
|
||||
## 六、结论与建议
|
||||
|
||||
### 6.1 测试结论
|
||||
|
||||
考试管理模块存在**1个权限缺陷**,同时因上游模块阻断导致**18个用例无法执行**。
|
||||
|
||||
### 6.2 建议
|
||||
|
||||
1. 优先修复所有模块的creator_id问题
|
||||
2. 修复后按顺序执行:
|
||||
- 考题管理 → 试卷管理 → 考试管理
|
||||
3. 补充考试核心流程的完整测试
|
||||
|
||||
---
|
||||
|
||||
**报告生成时间:** 2026-01-09 15:38:00
|
||||
119
training-system/docs/test-reports/TestReport_6.0_TrainingPlan.md
Normal file
119
training-system/docs/test-reports/TestReport_6.0_TrainingPlan.md
Normal file
@@ -0,0 +1,119 @@
|
||||
,# 测试报告 - 模块六:培训计划
|
||||
|
||||
> 测试日期:2026-01-09
|
||||
> 测试人员:AI测试工程师
|
||||
> 测试环境:Spring Boot 3.1.2 / MySQL 8.0 / JDK 17
|
||||
|
||||
---
|
||||
|
||||
## 一、测试概要
|
||||
|
||||
| 项目 | 数值 |
|
||||
|------|------|
|
||||
| 测试用例总数 | 11 |
|
||||
| 通过 | 4 |
|
||||
| 失败 | 1 |
|
||||
| 阻塞 | 6 |
|
||||
| 通过率 | 36.4% |
|
||||
|
||||
**说明:** 培训计划模块基本功能可用,但部分依赖知识库的功能被阻塞。
|
||||
|
||||
---
|
||||
|
||||
## 二、测试结果详情
|
||||
|
||||
### 2.1 创建培训计划测试(TP系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| TP-001 | 创建培训计划 | 成功创建 | 创建成功,返回ID=1 | **通过** |
|
||||
| TP-002 | 关联多个知识文档 | 关联成功 | 依赖知识数据 | **阻塞** |
|
||||
| TP-003 | 关联考试(可选) | 关联成功 | 依赖考试数据 | **阻塞** |
|
||||
| TP-004 | 分配部门/小组/个人 | 分配成功 | 分配部门成功 | **通过** |
|
||||
|
||||
### 2.2 计划状态测试(TPS系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| TPS-001 | 开始日期前状态 | 未开始 | 创建后默认为NOT_STARTED | **通过** |
|
||||
| TPS-002 | 发布后状态 | 进行中 | 发布后变为IN_PROGRESS | **通过** |
|
||||
| TPS-003 | 结束日期后状态 | 已结束 | 未测试(需等待时间) | **阻塞** |
|
||||
|
||||
### 2.3 进度跟踪测试(TPP系列)
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| TPP-001 | 学员完成知识学习 | 进度更新 | 依赖知识数据 | **阻塞** |
|
||||
| TPP-002 | 学员完成关联考试 | 进度更新 | 依赖考试数据 | **阻塞** |
|
||||
| TPP-003 | 学员查看自己的学习进度 | 进度显示正确 | 学员可查看,进度为0% | **通过** |
|
||||
| TPP-004 | 讲师查看学员培训进度 | 可查看本部门 | 依赖学习数据 | **阻塞** |
|
||||
|
||||
### 2.4 权限测试
|
||||
|
||||
| 用例编号 | 测试项 | 预期结果 | 实际结果 | 状态 |
|
||||
|---------|--------|---------|---------|------|
|
||||
| TP-权限 | 学员访问培训计划管理接口 | 返回403 | 返回200,可查询培训计划列表 | **失败** |
|
||||
|
||||
---
|
||||
|
||||
## 三、缺陷清单
|
||||
|
||||
### BUG-TP-001:学员可以访问培训计划管理接口
|
||||
|
||||
| 属性 | 描述 |
|
||||
|------|------|
|
||||
| 缺陷编号 | BUG-TP-001 |
|
||||
| 关联用例 | TP-权限 |
|
||||
| 严重程度 | **严重** |
|
||||
| 优先级 | P0 |
|
||||
| 缺陷描述 | 学员角色可以访问培训计划管理的分页查询接口 |
|
||||
| 重现步骤 | 1. 学员账号登录<br>2. GET /api/training/plan/page<br>3. 成功返回培训计划列表 |
|
||||
| 预期结果 | 返回403 Forbidden |
|
||||
| 实际结果 | 返回200 OK,可查看培训计划管理数据 |
|
||||
| 建议修复 | 在TrainingPlanController的管理类接口上添加角色权限控制 |
|
||||
|
||||
---
|
||||
|
||||
## 四、测试覆盖接口
|
||||
|
||||
| 接口 | 方法 | 测试状态 | 结果 |
|
||||
|------|------|---------|------|
|
||||
| /api/training/plan | POST | 已测试 | 通过 |
|
||||
| /api/training/plan/{id} | GET | 已测试 | 通过 |
|
||||
| /api/training/plan/{id}/publish | POST | 已测试 | 通过 |
|
||||
| /api/training/plan/page | GET | 已测试 | 通过 |
|
||||
| /api/training/plan/my | GET | 已测试 | 通过 |
|
||||
| /api/training/plan/my/{planId}/progress | GET | 已测试 | 通过 |
|
||||
|
||||
---
|
||||
|
||||
## 五、测试数据
|
||||
|
||||
### 5.1 测试创建的培训计划
|
||||
|
||||
| ID | 标题 | 状态 | 部门 |
|
||||
|----|------|------|------|
|
||||
| 1 | Test Training Plan 001 | IN_PROGRESS | 救援一部 |
|
||||
|
||||
---
|
||||
|
||||
## 六、结论与建议
|
||||
|
||||
### 6.1 测试结论
|
||||
|
||||
培训计划模块是**测试通过率最高**的模块(36.4%),基本CRUD功能正常,但存在**1个权限缺陷**。
|
||||
|
||||
### 6.2 正面发现
|
||||
|
||||
1. 培训计划创建成功(未受creator_id问题影响)
|
||||
2. 状态流转正常(NOT_STARTED -> IN_PROGRESS)
|
||||
3. 学员端接口正常(/my、/progress)
|
||||
|
||||
### 6.3 待改进
|
||||
|
||||
1. 修复学员权限控制问题
|
||||
2. 修复上游模块后补充知识关联、考试关联的测试
|
||||
|
||||
---
|
||||
|
||||
**报告生成时间:** 2026-01-09 15:45:00
|
||||
195
training-system/docs/test-reports/TestReport_Summary.md
Normal file
195
training-system/docs/test-reports/TestReport_Summary.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# 道路救援企业培训系统 - 测试总报告
|
||||
|
||||
> 测试日期:2026-01-09
|
||||
> 测试人员:AI测试工程师
|
||||
> 测试环境:Spring Boot 3.1.2 / MySQL 8.0 / JDK 17
|
||||
> 测试范围:PRD V1.0 MVP版本(模块1.3-模块6)
|
||||
|
||||
---
|
||||
|
||||
## 一、测试执行概览
|
||||
|
||||
### 1.1 总体统计
|
||||
|
||||
| 指标 | 数值 |
|
||||
|------|------|
|
||||
| 计划用例数 | 79 |
|
||||
| 已执行 | 79 |
|
||||
| **通过** | **11** |
|
||||
| **失败** | **11** |
|
||||
| **阻塞** | **57** |
|
||||
| **通过率** | **13.9%** |
|
||||
|
||||
### 1.2 各模块测试结果
|
||||
|
||||
| 模块 | 用例数 | 通过 | 失败 | 阻塞 | 通过率 |
|
||||
|------|--------|------|------|------|--------|
|
||||
| 1.3 员工管理 | 7 | 4 | 3 | 0 | 57.1% |
|
||||
| 2.0 知识库 | 19 | 2 | 2 | 15 | 10.5% |
|
||||
| 3.0 考题管理 | 11 | 0 | 3 | 8 | 0% |
|
||||
| 4.0 试卷管理 | 11 | 0 | 1 | 10 | 0% |
|
||||
| 5.0 考试管理 | 20 | 1 | 1 | 18 | 5% |
|
||||
| 6.0 培训计划 | 11 | 4 | 1 | 6 | 36.4% |
|
||||
|
||||
---
|
||||
|
||||
## 二、缺陷统计
|
||||
|
||||
### 2.1 缺陷严重程度分布
|
||||
|
||||
| 严重程度 | 数量 | 占比 |
|
||||
|---------|------|------|
|
||||
| **阻断(Blocker)** | 3 | 27.3% |
|
||||
| **严重(Critical)** | 6 | 54.5% |
|
||||
| **高(High)** | 2 | 18.2% |
|
||||
| **中(Medium)** | 0 | 0% |
|
||||
| 合计 | 11 | 100% |
|
||||
|
||||
### 2.2 缺陷清单汇总
|
||||
|
||||
| 缺陷编号 | 模块 | 严重程度 | 描述 | 状态 |
|
||||
|---------|------|---------|------|------|
|
||||
| BUG-USER-001 | 员工管理 | 中 | 手机号未做唯一性校验 | 待修复 |
|
||||
| BUG-USER-002 | 员工管理 | 高 | 讲师未实现部门数据隔离 | 待修复 |
|
||||
| BUG-USER-003 | 员工管理 | **严重** | 学员可访问员工管理接口 | 待修复 |
|
||||
| BUG-KM-001 | 知识库 | **阻断** | 创建知识时creator_id未设置 | 待修复 |
|
||||
| BUG-KM-002 | 知识库 | 高 | 讲师可操作其他部门分类 | 待修复 |
|
||||
| BUG-KM-003 | 知识库 | 高 | 文件上传功能异常 | 待修复 |
|
||||
| BUG-Q-001 | 考题管理 | **阻断** | 创建题目时creator_id未设置 | 待修复 |
|
||||
| BUG-Q-002 | 考题管理 | 高 | 讲师可操作其他部门题库 | 待修复 |
|
||||
| BUG-Q-003 | 考题管理 | **严重** | 学员可访问题目管理接口 | 待修复 |
|
||||
| BUG-P-001 | 试卷管理 | **阻断** | 创建试卷时creator_id未设置 | 待修复 |
|
||||
| BUG-P-002 | 试卷管理 | **严重** | 学员可访问试卷管理接口 | 待修复 |
|
||||
| BUG-E-001 | 考试管理 | **严重** | 学员可访问考试管理接口 | 待修复 |
|
||||
| BUG-TP-001 | 培训计划 | **严重** | 学员可访问培训计划管理接口 | 待修复 |
|
||||
|
||||
---
|
||||
|
||||
## 三、共性问题分析
|
||||
|
||||
### 3.1 阻断级问题:creator_id未设置
|
||||
|
||||
**影响范围:** 知识库、考题管理、试卷管理
|
||||
|
||||
**问题描述:** 创建知识/题目/试卷时,未从当前登录用户获取creator_id并设置,导致数据库插入失败。
|
||||
|
||||
**根本原因:** Service层创建实体时未调用SecurityContext获取当前用户ID。
|
||||
|
||||
**修复建议:**
|
||||
```java
|
||||
// 在各ServiceImpl的create方法中添加:
|
||||
Long currentUserId = SecurityContextHolder.getContext().getAuthentication()...
|
||||
entity.setCreatorId(currentUserId);
|
||||
```
|
||||
|
||||
**阻塞影响:**
|
||||
- 知识库:15个用例
|
||||
- 考题管理:8个用例
|
||||
- 试卷管理:10个用例
|
||||
- 考试管理:18个用例(级联阻塞)
|
||||
- **合计:51个用例(占64.6%)**
|
||||
|
||||
---
|
||||
|
||||
### 3.2 严重级问题:学员权限未控制
|
||||
|
||||
**影响范围:** 员工管理、考题管理、试卷管理、考试管理、培训计划
|
||||
|
||||
**问题描述:** 学员角色可以访问管理员/讲师专属的管理接口,存在越权访问风险。
|
||||
|
||||
**安全风险:**
|
||||
- 信息泄露:学员可查看所有员工信息、题库、试卷
|
||||
- 潜在篡改:如果POST/PUT/DELETE接口也未限制,可能造成数据篡改
|
||||
|
||||
**修复建议:**
|
||||
在Controller上添加Spring Security注解:
|
||||
```java
|
||||
@PreAuthorize("hasAnyRole('ADMIN', 'LECTURER')")
|
||||
@GetMapping("/page")
|
||||
public Result<PageResult<XXX>> page(...) { ... }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.3 高优先级问题:讲师部门隔离未实现
|
||||
|
||||
**影响范围:** 员工管理、知识库分类、题库分类
|
||||
|
||||
**问题描述:** 讲师可以查看/操作其他部门的数据,违反PRD中"讲师只能管理本部门"的要求。
|
||||
|
||||
**修复建议:**
|
||||
在Service层添加部门校验:
|
||||
```java
|
||||
Long userDeptId = getCurrentUserDepartmentId();
|
||||
if (!userDeptId.equals(dto.getDepartmentId())) {
|
||||
throw new BusinessException("无权操作其他部门数据");
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、测试结论
|
||||
|
||||
### 4.1 系统当前状态
|
||||
|
||||
| 评估项 | 状态 | 说明 |
|
||||
|--------|------|------|
|
||||
| 基础功能 | **部分可用** | 员工管理、培训计划基础功能可用 |
|
||||
| 核心业务 | **不可用** | 知识库、考试流程因creator_id问题无法使用 |
|
||||
| 权限控制 | **存在漏洞** | 学员可越权访问管理接口 |
|
||||
| 数据隔离 | **未实现** | 讲师部门隔离未生效 |
|
||||
|
||||
### 4.2 上线评估
|
||||
|
||||
**结论:当前版本不建议上线**
|
||||
|
||||
**原因:**
|
||||
1. 存在3个阻断级BUG,核心业务流程无法使用
|
||||
2. 存在6个严重级权限漏洞,安全风险高
|
||||
3. 测试通过率仅13.9%,远低于上线标准(通常≥90%)
|
||||
|
||||
### 4.3 修复优先级建议
|
||||
|
||||
| 优先级 | 问题 | 预计影响 |
|
||||
|--------|------|---------|
|
||||
| **P0** | creator_id未设置(3处) | 修复后可解除51个用例阻塞 |
|
||||
| **P0** | 学员权限控制(5处) | 修复后消除越权访问风险 |
|
||||
| **P1** | 讲师部门隔离(3处) | 修复后满足PRD数据隔离要求 |
|
||||
| **P1** | 文件上传异常 | 修复后知识库文件功能可用 |
|
||||
| **P2** | 手机号唯一性校验 | 修复后防止重复数据 |
|
||||
|
||||
---
|
||||
|
||||
## 五、下一步行动
|
||||
|
||||
### 5.1 短期(修复后)
|
||||
|
||||
1. 修复creator_id问题后,重新执行知识库、考题、试卷、考试模块测试
|
||||
2. 修复权限问题后,执行权限矩阵完整测试
|
||||
3. 修复部门隔离后,执行数据隔离专项测试
|
||||
|
||||
### 5.2 中期
|
||||
|
||||
1. 补充边界测试用例执行
|
||||
2. 执行接口自动化测试
|
||||
3. 执行性能压力测试
|
||||
|
||||
---
|
||||
|
||||
## 六、测试报告文件清单
|
||||
|
||||
| 报告名称 | 文件路径 |
|
||||
|---------|---------|
|
||||
| 1.3 员工管理测试报告 | docs/test-reports/TestReport_1.3_UserManagement.md |
|
||||
| 2.0 知识库测试报告 | docs/test-reports/TestReport_2.0_Knowledge.md |
|
||||
| 3.0 考题管理测试报告 | docs/test-reports/TestReport_3.0_Question.md |
|
||||
| 4.0 试卷管理测试报告 | docs/test-reports/TestReport_4.0_Paper.md |
|
||||
| 5.0 考试管理测试报告 | docs/test-reports/TestReport_5.0_Exam.md |
|
||||
| 6.0 培训计划测试报告 | docs/test-reports/TestReport_6.0_TrainingPlan.md |
|
||||
| 测试总报告 | docs/test-reports/TestReport_Summary.md |
|
||||
|
||||
---
|
||||
|
||||
**报告生成时间:** 2026-01-09 15:50:00
|
||||
|
||||
**报告签发:** AI测试工程师
|
||||
Reference in New Issue
Block a user