Files
Environment-Monitoring-System/Report/系统测试.md
ChuXun 02a830145e 1
2025-10-25 19:18:43 +08:00

110 lines
7.5 KiB
Markdown
Raw 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.
# 3.4 系统测试
为确保系统交付质量,我制定并执行了一套覆盖从代码单元到用户场景、从功能正确性到非功能性需求的、多层次、全方位的测试策略。
## 3.4.1 后端测试
我主要负责后端的单元测试、集成测试和API接口测试旨在从源头保证服务的稳定、可靠与安全。
### 1. 单元测试 (Unit Testing)
我坚持“测试驱动开发”TDD的理念使用`JUnit 5``Mockito`框架为核心的`Service`层和`Repository`层的公共方法编写了详尽的单元测试。单元测试的目标是隔离验证最小代码单元(一个方法或一个类)的逻辑正确性。
**测试用例示例:`TaskAssignmentService`单元测试**
```java:ems-backend/src/test/java/com/dne/ems/service/TaskAssignmentServiceTest.java
@ExtendWith(MockitoExtension.class)
class TaskAssignmentServiceTest {
@Mock
private FeedbackRepository feedbackRepository;
@Mock
private UserAccountRepository userAccountRepository;
@Mock
private TaskRepository taskRepository;
@Mock
private AssignmentRepository assignmentRepository;
@InjectMocks
private TaskAssignmentServiceImpl taskAssignmentService;
@Test
void assignTask_Success_ShouldReturnSavedAssignment() {
// Arrange: 准备测试数据和模拟行为
Feedback mockFeedback = new Feedback(1L, "Test", "Desc", FeedbackStatus.CONFIRMED, 101L);
UserAccount mockAssignee = new UserAccount(202L, "worker", "pass", Role.GRID_WORKER);
when(feedbackRepository.findById(1L)).thenReturn(Optional.of(mockFeedback));
when(userAccountRepository.findById(202L)).thenReturn(Optional.of(mockAssignee));
when(taskRepository.save(any(Task.class))).thenAnswer(i -> i.getArgument(0));
when(assignmentRepository.save(any(Assignment.class))).thenAnswer(i -> i.getArgument(0));
// Act: 执行被测试的方法
Assignment result = taskAssignmentService.assignTask(1L, 202L, 303L);
// Assert: 验证结果和交互
assertNotNull(result);
assertEquals(202L, result.getAssigneeId());
verify(feedbackRepository, times(1)).save(any(Feedback.class)); // 验证Feedback状态是否被更新并保存
assertEquals(FeedbackStatus.ASSIGNED, mockFeedback.getStatus());
}
@Test
void assignTask_FeedbackNotFound_ShouldThrowException() {
// Arrange
when(feedbackRepository.findById(99L)).thenReturn(Optional.empty());
// Act & Assert
assertThrows(IllegalArgumentException.class, () -> {
taskAssignmentService.assignTask(99L, 202L, 303L);
});
}
}
```
**测试策略说明:**
* **Mocking:** 使用`Mockito`框架模拟Mock外部依赖如各个Repository使得测试可以专注于`Service`层自身的业务逻辑,而不受数据库或文件系统的影响。
* **覆盖度:** 我为每个公共方法都编写了多个测试用例,覆盖了“成功路径”和各种“异常路径”(如输入非法、依赖返回空等),力求达到较高的代码覆盖率和逻辑覆盖率。
### 2. API接口测试 (API Testing)
我利用`SpringDoc`与`Swagger UI`的无缝集成以及更专业的API测试工具`Postman`对所有RESTful API进行了系统性的黑盒测试。
* **测试范围:** 覆盖了用户认证、权限管理、反馈生命周期、任务生命周期等所有核心模块的每一个API端点。
* **测试方法:** 我为每个API编写了一系列测试用例形成了一个`Postman`测试集Collection这使得测试可以被保存、共享和重复执行。
**API测试用例表示例 (扩展):**
| 用例ID | 模块 | 接口 | 场景描述 | 输入数据 | 预期HTTP状态 | 预期响应体关键内容 | 结果 |
| :--- | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
| TC-API-001 | 任务管理 | `POST /api/assignments` | 成功分配任务 | 合法的`feedbackId`, `assigneeId` | `201 Created` | 返回新创建的`assignment`对象JSON | 通过 |
| TC-API-002 | 任务管理 | `POST /api/assignments` | **异常**反馈ID不存在 | `feedbackId: 9999` | `404 Not Found` | `"message": "Feedback with id 9999 not found"` | 通过 |
| TC-API-003 | 任务管理 | `POST /api/assignments` | **异常**:指派的用户不是网格员 | `assigneeId`指向一个`ADMIN`角色的用户 | `400 Bad Request` | `"message": "User is not a grid worker"` | 通过 |
| TC-API-004 | 任务管理 | `POST /api/assignments` | **异常**:反馈状态不正确 | `feedbackId`指向一个`PENDING`状态的反馈 | `400 Bad Request` | `"message": "Feedback is not in a CONFIRMED state"` | 通过 |
| TC-API-005 | 安全 | `POST /api/assignments` | **安全**无JWT令牌 | `Authorization`头为空 | `401 Unauthorized` | (空或错误提示) | 通过 |
| TC-API-006 | 安全 | `POST /api/assignments` | **安全**使用网格员角色的JWT | `Authorization`头为一个`GRID_WORKER`的JWT | `403 Forbidden` | (空或错误提示) | 通过 |
## 3.4.2 前端测试
我与负责前端的组员紧密协作进行了全面的前端功能、UI/UX和兼容性测试。
* **手工功能测试:** 我们以用户故事User Story为驱动模拟不同角色的用户公众、网格员、主管、管理员完整地执行了所有核心业务流程的端到端场景确保功能符合需求规格。
* **UI/UX测试:** 仔细检查了界面的布局、色彩、字体、图标和交互动效确保其在主流浏览器Chrome, Firefox, Edge的不同版本和不同屏幕分辨率下如`1920x1080`, `1366x768`)都能保持良好的一致性、美观度和用户体验。
## 3.4.3 集成与系统测试
在前后端分别完成各自的测试后,我们将整个系统部署到一台独立的测试服务器上,进行了端到端的集成测试和系统测试。
* **目的:** 验证前后端数据接口的正确性、API调用的顺畅性、以及在真实网络环境下整个系统业务流程的闭环。
* **过程:** 我们共同执行了一套预先设计的系统级测试用例,这些用例模拟了真实世界中的复杂操作序列。例如:
1. 公众用户A提交反馈 -> 主管B审核通过 -> 主管B将任务分配给网格员C -> 网格员C完成任务并提交数据 -> 主管B查看已完成的任务和数据。
2. 并发测试:多个用户同时提交反馈或更新任务,验证后端`synchronized`机制是否有效防止了数据冲突。
* **结果:** 通过严格的集成联调测试我们发现并修复了若干在单元测试阶段难以暴露的问题如跨域CORS配置问题、序列化/反序列化日期格式不一致问题、JWT刷新逻辑的边界条件等最终确保了前后端系统的无缝集成和稳定运行。
## 3.4.4 非功能性测试
除了功能测试,我还对系统的部分非功能性需求进行了初步的探索性测试。
* **性能测试:** 使用`Apache JMeter`工具对核心的登录和查询类API进行了简单的压力测试。模拟20个并发用户持续请求观察到API的平均响应时间仍在200ms以内CPU和内存占用率处于合理范围初步证明系统具备应对一定并发访问的能力。
* **安全测试:**
* **权限测试:** 严格测试了不同角色的用户访问未授权API的情况验证系统是否能正确返回`403 Forbidden`。
* **输入验证:** 尝试提交包含恶意脚本XSS或SQL注入虽然我们不是SQL数据库但原理相通的表单数据验证后端是否有充分的输入清理和验证机制。