testing-strategy.md 12 KB

测试策略

版本信息

版本 日期 描述 作者
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%
  • 执行频率: 每日或每次重大变更

测试环境配置

开发环境

// 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环境

# 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%集成测试覆盖率

测试数据管理

测试数据策略

// 测试数据工厂模式
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. 测试数据隔离 (使用唯一标识符)

测试执行流程

本地开发测试

# 运行所有测试
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: 移动端性能监控

测试文档标准

测试代码规范

// 良好的测试示例
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集成
  • 自定义报告: 业务指标测试报告
  • 历史趋势: 测试质量趋势分析

附录

相关文档

工具版本

  • 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