Files
training-system/training-system/docs/test-reports/RegressionReport_1.3_UserManagement_V2.md
2026-01-13 17:07:23 +08:00

11 KiB
Raw Blame History

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. 管理员登录
2. 前端编辑员工,状态选择"禁用"
3. 点击保存,提示"保存成功"
4. 刷新页面,状态仍为"启用"
预期结果 员工状态变为"禁用"
实际结果 员工状态仍为"启用",状态修改被静默忽略
根因分析 后端问题UserDTO类中没有定义status字段updateUser()方法也未处理状态更新
影响范围 前端编辑表单中的状态选择功能完全无效,用户体验严重受损

前端代码验证

前端代码正确传递了status字段user.html:139

const data = {
    realName: ...,
    phone: ...,
    username: ...,
    departmentId: ...,
    groupId: ...,
    role: ...,
    status: document.getElementById('formStatus').value  // ✅ 前端正确传递
};

问题定位

层级 状态 说明
前端页面 正常 有状态选择下拉框,正确绑定值
前端JS 正常 saveData()正确收集status并发送
后端DTO 缺失 UserDTO没有status字段Jackson忽略该值
后端Service 未处理 updateUser()没有setStatus()调用

测试请求:

PUT /api/system/user
Content-Type: application/json
{
  "id": 5,
  "username": "test_user_002",
  "realName": "TestUser002",
  "phone": "13800138001",
  "role": "STUDENT",
  "departmentId": 1,
  "status": "DISABLED"  // 尝试修改状态
}

测试响应:

{
  "code": 200,
  "message": "操作成功",
  "success": true
}

验证查询结果:

{
  "data": {
    "id": 5,
    "status": "ENABLED",  // 状态未改变!
    "statusName": "启用"
  }
}

修复建议(二选一):

方案A在UserDTO中添加status字段

// 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
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());
        }
    }
}
  1. 问题根源JwtUtils.java:37-48
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
  1. AuthInterceptor尝试获取但失败AuthInterceptor.java:68-70
if (jwt.getClaim("departmentId") != null && !jwt.getClaim("departmentId").isNull()) {
    context.setDepartmentId(jwt.getClaim("departmentId").asLong());
}
// 由于JWT中没有departmentId这段代码不会执行

修复建议:

修改 JwtUtils.generateToken() 方法,添加 departmentId 参数:

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. 管理员调用重置密码接口
2. 使用新密码登录
3. 使用旧密码登录
实际结果 新密码登录成功旧密码登录失败返回1003密码错误

测试详情:

# 重置密码
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
2. 查询用户状态
3. 调用 PUT /api/system/user/{id}/enable
4. 查询用户状态
实际结果 专用接口可正常切换状态

测试详情:

# 禁用用户
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测试工程师