# 步骤5:测试覆盖检查 ## 🎯 检查目标 检查测试文件的完整性和覆盖率,确保严格的一对一测试映射和测试分离。 ## 📋 测试文件存在性检查 ### 需要测试文件的类型 ```typescript ✅ 必须有测试文件: - *.service.ts # Service类 - 业务逻辑类 - *.controller.ts # Controller类 - 控制器类 - *.gateway.ts # Gateway类 - WebSocket网关类 - *.guard.ts # Guard类 - 守卫类(游戏服务器安全重要) - *.interceptor.ts # Interceptor类 - 拦截器类(日志监控重要) - *.middleware.ts # Middleware类 - 中间件类(性能监控重要) ❌ 不需要测试文件: - *.dto.ts # DTO类 - 数据传输对象 - *.interface.ts # Interface文件 - 接口定义 - *.constants.ts # Constants文件 - 常量定义 - *.config.ts # Config文件 - 配置文件 - *.utils.ts # 简单Utils工具类(复杂工具类需要) ``` ### 测试文件命名规范 ```typescript ✅ 正确的一对一映射: src/business/auth/auth.service.ts src/business/auth/auth.service.spec.ts src/core/location_broadcast_core/location_broadcast_core.service.ts src/core/location_broadcast_core/location_broadcast_core.service.spec.ts src/business/admin/admin.gateway.ts src/business/admin/admin.gateway.spec.ts ❌ 错误的命名: src/business/auth/auth_services.spec.ts # 测试多个service,违反一对一原则 src/business/auth/auth_test.spec.ts # 命名不对应 ``` ## 🔥 严格一对一测试映射(重要) ### 强制要求 - **严格对应**:每个测试文件必须严格对应一个源文件 - **禁止多对一**:不允许一个测试文件测试多个源文件 - **禁止一对多**:不允许一个源文件的测试分散在多个测试文件 - **命名对应**:测试文件名必须与源文件名完全对应(除.spec.ts后缀外) ### 测试范围严格限制 ```typescript // ✅ 正确:只测试LoginService的功能 // 文件:src/business/auth/login.service.spec.ts describe('LoginService', () => { describe('validateUser', () => { it('should validate user credentials', () => { // 只测试LoginService.validateUser方法 // 使用Mock隔离UserRepository等外部依赖 }); it('should throw error for invalid credentials', () => { // 测试异常情况 }); }); describe('generateToken', () => { it('should generate valid JWT token', () => { // 只测试LoginService.generateToken方法 }); }); }); // ❌ 错误:在LoginService测试中测试其他服务 describe('LoginService', () => { it('should integrate with UserRepository', () => { // 错误:这是集成测试,应该移到test/integration/ }); it('should work with EmailService', () => { // 错误:测试了EmailService的功能,违反范围限制 }); }); ``` ## 🏗️ 测试分离架构(强制要求) ### 顶层test目录结构 ``` test/ ├── integration/ # 集成测试 - 测试多个模块间的交互 │ ├── auth_integration.spec.ts │ ├── location_broadcast_integration.spec.ts │ └── zulip_integration.spec.ts ├── e2e/ # 端到端测试 - 完整业务流程测试 │ ├── user_registration_e2e.spec.ts │ ├── location_broadcast_e2e.spec.ts │ └── admin_operations_e2e.spec.ts ├── performance/ # 性能测试 - WebSocket和高并发测试 │ ├── websocket_performance.spec.ts │ ├── database_performance.spec.ts │ └── memory_usage.spec.ts ├── property/ # 属性测试 - 基于属性的随机测试 │ ├── admin_property.spec.ts │ ├── user_validation_property.spec.ts │ └── position_update_property.spec.ts └── fixtures/ # 测试数据和工具 ├── test_data.ts └── test_helpers.ts ``` ### 测试类型分离要求 ```typescript // ✅ 正确:单元测试只在源文件同目录 // 文件位置:src/business/auth/login.service.spec.ts describe('LoginService Unit Tests', () => { // 只测试LoginService的单个方法功能 // 使用Mock隔离所有外部依赖 }); // ✅ 正确:集成测试统一在test/integration/ // 文件位置:test/integration/auth_integration.spec.ts describe('Auth Integration Tests', () => { it('should integrate LoginService with UserRepository and TokenService', () => { // 测试多个模块间的真实交互 }); }); // ✅ 正确:E2E测试统一在test/e2e/ // 文件位置:test/e2e/user_auth_e2e.spec.ts describe('User Authentication E2E Tests', () => { it('should handle complete user login flow', () => { // 端到端完整业务流程测试 }); }); ``` ## 🎮 游戏服务器特殊测试要求 ### WebSocket Gateway测试 ```typescript // ✅ 正确:完整的WebSocket测试 // 文件:src/business/location/location_broadcast.gateway.spec.ts describe('LocationBroadcastGateway', () => { let gateway: LocationBroadcastGateway; let mockServer: jest.Mocked; beforeEach(async () => { // 设置Mock服务器和依赖 }); describe('handleConnection', () => { it('should accept valid WebSocket connection with JWT token', () => { // 正常连接测试 }); it('should reject connection with invalid JWT token', () => { // 异常连接测试 }); it('should handle connection when room is at capacity limit', () => { // 边界情况测试 }); }); describe('handlePositionUpdate', () => { it('should broadcast position to all room members', () => { // 实时通信测试 }); it('should validate position data format', () => { // 数据验证测试 }); }); describe('handleDisconnect', () => { it('should clean up user resources on disconnect', () => { // 断开连接测试 }); }); }); ``` ### 双模式服务测试 ```typescript // ✅ 正确:内存服务测试 // 文件:src/core/users/users_memory.service.spec.ts describe('UsersMemoryService', () => { it('should create user in memory storage', () => { // 测试内存模式特定功能 }); it('should handle concurrent access correctly', () => { // 测试内存模式并发处理 }); }); // ✅ 正确:数据库服务测试 // 文件:src/core/users/users_database.service.spec.ts describe('UsersDatabaseService', () => { it('should create user in database', () => { // 测试数据库模式特定功能 }); it('should handle database transaction correctly', () => { // 测试数据库事务处理 }); }); // ✅ 正确:双模式一致性测试(集成测试) // 文件:test/integration/users_dual_mode_integration.spec.ts describe('Users Dual Mode Integration', () => { it('should have identical behavior for user creation', () => { // 测试两种模式行为一致性 }); }); ``` ### 属性测试(管理员模块) ```typescript // ✅ 正确:属性测试 // 文件:test/property/admin_property.spec.ts import * as fc from 'fast-check'; describe('AdminService Properties', () => { it('should handle any valid user status update', () => { fc.assert(fc.property( fc.integer({ min: 1, max: 1000000 }), // userId fc.constantFrom(...Object.values(UserStatus)), // status async (userId, status) => { try { const result = await adminService.updateUserStatus(userId, status); expect(result).toBeDefined(); expect(result.status).toBe(status); } catch (error) { expect(error).toBeInstanceOf(NotFoundException || BadRequestException); } } )); }); }); ``` ## 📍 测试文件位置规范 ### 正确位置 ``` ✅ 正确:测试文件与源文件同目录 src/business/auth/ ├── auth.service.ts ├── auth.service.spec.ts # 单元测试 ├── auth.controller.ts └── auth.controller.spec.ts # 单元测试 src/core/location_broadcast_core/ ├── location_broadcast_core.service.ts └── location_broadcast_core.service.spec.ts ``` ### 错误位置(必须修正) ``` ❌ 错误:测试文件在单独文件夹 src/business/auth/ ├── auth.service.ts ├── auth.controller.ts └── tests/ # 错误:单独的测试文件夹 ├── auth.service.spec.ts # 应该移到上级目录 └── auth.controller.spec.ts src/business/auth/ ├── auth.service.ts ├── auth.controller.ts └── __tests__/ # 错误:单独的测试文件夹 └── auth.spec.ts # 应该拆分并移到上级目录 ``` ## 🧪 测试执行验证(强制要求) ### 测试命令执行 ```bash # 单元测试(严格限制:只执行.spec.ts文件) npm run test:unit # 等价于: jest --testPathPattern=spec.ts --testPathIgnorePatterns="integration|e2e|performance|property" # 集成测试(统一在test/integration/目录执行) npm run test:integration # 等价于: jest test/integration/ # E2E测试(统一在test/e2e/目录执行) npm run test:e2e # 等价于: jest test/e2e/ # 属性测试(统一在test/property/目录执行) npm run test:property # 等价于: jest test/property/ # 性能测试(统一在test/performance/目录执行) npm run test:performance # 等价于: jest test/performance/ ``` ### 测试执行顺序 1. **第一阶段**:单元测试(快速反馈) 2. **第二阶段**:集成测试(模块协作) 3. **第三阶段**:E2E测试(业务流程) 4. **第四阶段**:性能测试(系统性能) ## 🔍 检查执行步骤 1. **扫描需要测试的文件类型** - 识别所有.service.ts、.controller.ts、.gateway.ts等文件 - 检查是否有对应的.spec.ts测试文件 2. **验证一对一测试映射** - 确保每个测试文件严格对应一个源文件 - 检查测试文件命名是否正确对应 3. **检查测试范围限制** - 确保测试内容严格限于对应源文件功能 - 识别跨文件测试和混合测试 4. **检查测试文件位置** - 确保单元测试与源文件在同一目录 - 识别需要扁平化的测试文件夹 5. **分离集成测试和E2E测试** - 将集成测试移动到test/integration/ - 将E2E测试移动到test/e2e/ - 将性能测试移动到test/performance/ - 将属性测试移动到test/property/ 6. **执行测试验证** - 运行单元测试命令验证通过 - 确保测试覆盖率达标 - 验证测试质量和有效性 7. **游戏服务器特殊检查** - WebSocket Gateway的完整测试覆盖 - 双模式服务的一致性测试 - 属性测试的正确实现 ## 🔥 重要提醒 **如果在本步骤中执行了任何修改操作(创建测试文件、移动测试文件、修正测试内容等),必须立即重新执行步骤5的完整检查!** - ✅ 执行修改 → 🔥 立即重新执行步骤5 → 提供验证报告 → 等待用户确认 - ❌ 执行修改 → 直接进入步骤6(错误做法) **不能跳过重新检查环节!**