# 测试策略 ## 版本信息 | 版本 | 日期 | 描述 | 作者 | |------|------|------|------| | 2.4 | 2025-09-20 | 更新测试策略与主架构文档版本一致 | Winston | | 2.5 | 2025-09-24 | 更新数据库配置,修正数据库类型 | Winston | | 2.6 | 2025-09-27 | 添加移动端应用测试策略 | Winston | ## 概述 本文档定义了D8D Starter项目的完整测试策略,基于现有的测试基础设施和最佳实践。测试策略遵循测试金字塔模型,确保代码质量、功能稳定性和系统可靠性。 ## 测试金字塔策略 ### 单元测试 (Unit Tests) - **范围**: 单个函数、类或组件 - **目标**: 验证独立单元的correctness - **位置**: `src/**/__tests__/**/*.test.{ts,tsx}` - **框架**: Vitest - **覆盖率目标**: ≥ 80% - **执行频率**: 每次代码变更 ### 集成测试 (Integration Tests) - **范围**: 多个组件/服务协作 - **目标**: 验证模块间集成和交互 - **位置**: `src/**/__integration_tests__/**/*.integration.test.{ts,tsx}` - **框架**: Vitest + Testing Library + hono/testing - **覆盖率目标**: ≥ 60% - **执行频率**: 每次API变更 ### E2E测试 (End-to-End Tests) - **范围**: 完整用户流程 - **目标**: 验证端到端业务流程 - **位置**: `tests/e2e/**/*.test.{ts,tsx}` - **框架**: Playwright - **覆盖率目标**: 关键用户流程100% - **执行频率**: 每日或每次重大变更 ## 测试环境配置 ### 开发环境 ```typescript // vitest.config.ts - 开发环境配置 export default defineConfig({ test: { environment: 'node', include: ['src/**/__tests__/**', 'src/**/__integration_tests__/**'], setupFiles: ['./src/test/setup.ts'], coverage: { provider: 'v8', thresholds: { branches: 70, functions: 70, lines: 70, statements: 70 } } } }); ``` ### CI/CD环境 ```yaml # GitHub Actions 测试配置 name: Test Pipeline jobs: unit-tests: runs-on: ubuntu-latest steps: - run: npm run test:api - run: npm run test:components integration-tests: runs-on: ubuntu-latest services: mysql: image: mysql:8.0.36 env: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: test_db options: >- --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 steps: - run: npm run test:integration e2e-tests: runs-on: ubuntu-latest steps: - run: npm run test:e2e:chromium ``` ## 测试覆盖率标准 ### 各层覆盖率要求 | 测试类型 | 最低要求 | 目标要求 | 关键模块要求 | |----------|----------|----------|--------------| | 单元测试 | 70% | 80% | 90% | | 集成测试 | 50% | 60% | 70% | | E2E测试 | 关键流程100% | 主要流程80% | - | ### 关键模块定义 - **认证授权模块**: 必须达到90%单元测试覆盖率 - **数据库操作模块**: 必须达到85%单元测试覆盖率 - **核心业务逻辑**: 必须达到80%集成测试覆盖率 - **用户管理功能**: 必须100% E2E测试覆盖 - **移动端实时通信**: 必须达到85%单元测试覆盖率 - **股票训练系统**: 必须达到80%集成测试覆盖率 - **音视频通信**: 必须达到75%集成测试覆盖率 ## 测试数据管理 ### 测试数据策略 ```typescript // 测试数据工厂模式 export function createTestUser(overrides = {}): User { return { id: 1, username: 'testuser', email: 'test@example.com', createdAt: new Date(), ...overrides }; } // 使用示例 const adminUser = createTestUser({ role: 'admin' }); const inactiveUser = createTestUser({ active: false }); ``` ### 数据库测试策略 - **单元测试**: 使用内存数据库或完全mock - **集成测试**: 使用专用测试数据库,事务回滚 - **E2E测试**: 使用接近生产环境的数据库 ### 数据清理策略 1. **事务回滚** (推荐) 2. **数据库清理** (每个测试后) 3. **测试数据隔离** (使用唯一标识符) ## 测试执行流程 ### 本地开发测试 ```bash # 运行所有测试 pnpm test # 运行API测试 pnpm test:api # 运行组件测试 pnpm test:components # 运行集成测试 pnpm test:integration # 运行E2E测试 pnpm test:e2e:chromium # 生成覆盖率报告 pnpm test:coverage ``` ### CI/CD流水线测试 1. **代码推送** → 触发测试流水线 2. **单元测试** → 快速反馈,必须通过 3. **集成测试** → 验证模块集成,必须通过 4. **E2E测试** → 验证完整流程,建议通过 5. **覆盖率检查** → 满足最低要求 6. **测试报告** → 生成详细报告 ## 质量门禁 ### 测试通过标准 - ✅ 所有单元测试通过 - ✅ 所有集成测试通过 - ✅ 关键E2E测试通过 - ✅ 覆盖率满足最低要求 - ✅ 无性能回归 - ✅ 安全测试通过 ### 失败处理流程 1. **测试失败** → 立即通知开发团队 2. **分析根本原因** → 确定是测试问题还是代码问题 3. **优先修复** → 阻塞性问题必须立即修复 4. **重新测试** → 修复后重新运行测试 5. **文档更新** → 更新测试策略和案例 ## 移动端应用测试策略 ### 移动端特有测试要求 **实时通信测试**: - **Socket.IO连接测试**: 验证WebSocket连接建立和断开 - **消息传递测试**: 测试实时消息发送和接收的正确性 - **事件处理测试**: 验证各种Socket事件的处理逻辑 - **并发测试**: 测试多用户同时连接和交互的场景 - **断线重连测试**: 验证网络异常后的自动重连机制 **股票训练系统测试**: - **实时数据推送测试**: 验证股票数据的实时更新和推送 - **交易执行测试**: 测试股票买卖操作的完整流程 - **K线图数据测试**: 验证图表数据的正确性和实时性 - **性能测试**: 测试大量实时数据推送的性能表现 - **数据一致性测试**: 确保前端显示与后端数据的一致性 **音视频通信测试**: - **RTC token生成测试**: 验证阿里云RTC token生成的安全性 - **音视频连接测试**: 测试音视频通话的连接建立和断开 - **媒体流测试**: 验证音视频流的传输质量 - **权限控制测试**: 测试不同角色用户的音视频权限 - **网络适应性测试**: 测试不同网络条件下的音视频质量 **移动端UI/UX测试**: - **响应式设计测试**: 验证在不同屏幕尺寸下的显示效果 - **触摸交互测试**: 测试触摸操作的响应性和准确性 - **手势操作测试**: 验证各种手势操作的识别和处理 - **离线功能测试**: 测试网络异常时的降级处理 - **性能优化测试**: 验证移动端性能优化措施的有效性 ### 移动端测试工具 - **Playwright Mobile**: 移动端E2E测试 - **Socket.IO Client Testing**: Socket.IO客户端测试工具 - **WebRTC Testing**: WebRTC连接和媒体流测试 - **React Native Testing Library**: React组件测试 - **Performance Monitoring**: 移动端性能监控工具 ## 安全测试策略 ### 安全测试要求 - **输入验证测试**: 所有API端点必须测试SQL注入、XSS等攻击 - **认证测试**: 测试令牌验证、权限控制 - **数据保护**: 测试敏感数据泄露风险 - **错误处理**: 测试错误信息是否泄露敏感数据 ### 移动端安全测试要求 - **实时通信安全**: 测试Socket.IO连接的身份验证和权限控制 - **音视频安全**: 测试RTC token的安全性和权限验证 - **数据加密**: 测试敏感数据传输的加密保护 - **移动端安全**: 测试移动端特有的安全风险(如本地存储安全) ### 安全测试工具 - **OWASP ZAP**: 自动化安全扫描 - **npm audit**: 依赖漏洞检查 - **自定义安全测试**: 针对业务逻辑的安全测试 ## 性能测试策略 ### 性能测试要求 - **API响应时间**: < 100ms (p95) - **数据库查询性能**: < 50ms (p95) - **并发用户数**: 支持100+并发用户 - **资源使用**: CPU < 70%, 内存 < 80% ### 移动端性能测试要求 - **实时通信延迟**: < 200ms (p95) 消息传递延迟 - **股票数据推送频率**: 支持每秒10+次数据更新 - **音视频延迟**: < 500ms (p95) 音视频传输延迟 - **移动端渲染性能**: 页面加载时间 < 2秒 - **移动端内存使用**: < 100MB 内存占用 - **移动端电池消耗**: 连续使用4小时以上 ### 性能测试工具 - **k6**: 负载测试 - **autocannon**: API性能测试 - **Playwright**: E2E性能监控 - **Socket.IO Performance Testing**: 实时通信性能测试 - **WebRTC Performance Testing**: 音视频性能测试 - **Mobile Performance Monitoring**: 移动端性能监控 ## 测试文档标准 ### 测试代码规范 ```typescript // 良好的测试示例 describe('UserService', () => { describe('createUser()', () => { it('应该创建新用户并返回用户对象', async () => { // Arrange const userData = { username: 'testuser', email: 'test@example.com' }; // Act const result = await userService.createUser(userData); // Assert expect(result).toHaveProperty('id'); expect(result.username).toBe('testuser'); expect(result.email).toBe('test@example.com'); }); it('应该拒绝重复的用户名', async () => { // Arrange const existingUser = await createTestUser({ username: 'existing' }); // Act & Assert await expect( userService.createUser({ username: 'existing', email: 'new@example.com' }) ).rejects.toThrow('用户名已存在'); }); }); }); // 移动端实时通信测试示例 describe('ClassroomSocketService', () => { describe('joinClassroom()', () => { it('应该成功加入课堂并接收欢迎消息', async () => { // Arrange const classroomId = 'classroom-123'; const userId = 'user-456'; // Act const socket = await classroomService.joinClassroom(classroomId, userId); // Assert await expect(socket).toReceiveMessage('welcome'); expect(socket.connected).toBe(true); }); it('应该处理网络异常并自动重连', async () => { // Arrange const socket = await classroomService.joinClassroom('classroom-123', 'user-456'); // Act socket.disconnect(); // 模拟网络断开 await waitForReconnection(); // Assert expect(socket.connected).toBe(true); }); }); }); // 股票训练系统测试示例 describe('StockTrainingService', () => { describe('subscribeStockData()', () => { it('应该订阅股票数据并接收实时更新', async () => { // Arrange const stockCode = 'AAPL'; // Act const subscription = await stockService.subscribeStockData(stockCode); // Assert await expect(subscription).toReceiveDataWithin(1000); // 1秒内收到数据 expect(subscription.isActive).toBe(true); }); it('应该处理高频数据推送的性能', async () => { // Arrange const stockCodes = ['AAPL', 'GOOGL', 'TSLA', 'MSFT']; // Act const startTime = Date.now(); const subscriptions = await Promise.all( stockCodes.map(code => stockService.subscribeStockData(code)) ); // Assert const duration = Date.now() - startTime; expect(duration).toBeLessThan(500); // 500ms内完成所有订阅 }); }); }); ``` ### 测试命名约定 - **文件名**: `[module].test.ts` 或 `[module].integration.test.ts` - **描述**: 使用「应该...」格式描述测试行为 - **用例**: 明确描述测试场景和预期结果 ## 监控和报告 ### 测试监控指标 - **测试通过率**: > 95% - **测试执行时间**: < 10分钟(单元+集成) - **测试稳定性**: 无flaky tests - **覆盖率趋势**: 持续改进或保持 ### 测试报告要求 - **HTML报告**: 详细的覆盖率报告 - **JUnit报告**: CI/CD集成 - **自定义报告**: 业务指标测试报告 - **历史趋势**: 测试质量趋势分析 ## 附录 ### 相关文档 - [集成测试最佳实践](../integration-testing-best-practices.md) - [编码标准](./coding-standards.md) - [API设计规范](./api-design-integration.md) ### 工具版本 - **Vitest**: 2.x (项目实际版本) - **Testing Library**: 13.x (项目实际版本) - **Playwright**: 最新版本 (项目实际版本) - **hono/testing**: 内置(Hono 4.8.5) ### 更新日志 | 日期 | 版本 | 描述 | |------|------|------| | 2025-09-19 | 1.0 | 初始版本,基于现有测试基础设施 | | 2025-09-20 | 2.4 | 更新版本与主架构文档一致 | --- **文档状态**: 正式版 **下次评审**: 2025-12-19