| 版本 | 日期 | 描述 | 作者 |
|---|---|---|---|
| 2.4 | 2025-09-20 | 更新测试策略与主架构文档版本一致 | Winston |
| 2.5 | 2025-09-24 | 更新数据库配置,修正数据库类型 | Winston |
| 2.6 | 2025-09-27 | 添加移动端应用测试策略 | Winston |
本文档定义了D8D Starter项目的完整测试策略,基于现有的测试基础设施和最佳实践。测试策略遵循测试金字塔模型,确保代码质量、功能稳定性和系统可靠性。
src/**/__tests__/**/*.test.{ts,tsx}src/**/__integration_tests__/**/*.integration.test.{ts,tsx}tests/e2e/**/*.test.{ts,tsx}// 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
}
}
}
});
# 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% | - |
// 测试数据工厂模式
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 });
# 运行所有测试
pnpm test
# 运行API测试
pnpm test:api
# 运行组件测试
pnpm test:components
# 运行集成测试
pnpm test:integration
# 运行E2E测试
pnpm test:e2e:chromium
# 生成覆盖率报告
pnpm test:coverage
实时通信测试:
股票训练系统测试:
音视频通信测试:
移动端UI/UX测试:
// 良好的测试示例
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| 日期 | 版本 | 描述 |
|---|---|---|
| 2025-09-19 | 1.0 | 初始版本,基于现有测试基础设施 |
| 2025-09-20 | 2.4 | 更新版本与主架构文档一致 |
文档状态: 正式版 下次评审: 2025-12-19