# 测试策略

## 版本信息
| 版本 | 日期 | 描述 | 作者 |
|------|------|------|------|
| 2.9 | 2025-12-15 | 添加API模拟规范和前端组件测试策略，修正$path()方法描述与实际代码不一致问题 | James |
| 2.8 | 2025-11-11 | 更新包测试结构，添加模块化包测试策略 | Winston |
| 2.7 | 2025-11-09 | 更新为monorepo测试架构，清理重复测试文件 | James |
| 2.6 | 2025-10-15 | 完成遗留测试文件迁移到统一的tests目录结构 | Winston |
| 2.5 | 2025-10-14 | 更新测试文件位置到统一的tests目录结构 | Claude |
| 2.4 | 2025-09-20 | 更新测试策略与主架构文档版本一致 | Winston |

## 概述

本文档定义了D8D Starter项目的完整测试策略，基于monorepo架构和现有的测试基础设施。测试策略遵循测试金字塔模型，确保代码质量、功能稳定性和系统可靠性。

### 测试架构更新 (v2.8)

项目已重构为模块化包架构，测试架构相应调整为：
- **基础设施包**: shared-types、shared-utils、shared-crud、shared-test-util
- **业务模块包**: user-module、auth-module、file-module、geo-areas
- **应用层**: server (重构后)，包含模块集成测试
- **web**: Web应用，包含组件测试、集成测试和E2E测试
- **CI/CD**: 独立的工作流分别处理各包的测试

### 包测试架构 (v2.8)

项目采用分层测试架构，每个包独立测试：
- **基础设施包**: 纯单元测试，不依赖外部服务
- **业务模块包**: 单元测试 + 集成测试，验证模块功能
- **应用层**: 集成测试，验证模块间协作
- **共享测试工具**: shared-test-util 提供统一的测试基础设施

## 测试金字塔策略

### 单元测试 (Unit Tests)
- **范围**: 单个函数、类或组件
- **目标**: 验证独立单元的correctness
- **位置**:
  - **基础设施包**: `packages/shared-*/tests/unit/**/*.test.ts`
  - **业务模块包**: `packages/*-module/tests/unit/**/*.test.ts`
  - **server包**: `packages/server/tests/unit/**/*.test.ts`
  - **web应用**: `web/tests/unit/**/*.test.{ts,tsx}`
- **框架**: Vitest
- **覆盖率目标**: ≥ 80%
- **执行频率**: 每次代码变更

### 集成测试 (Integration Tests)
- **范围**: 多个组件/服务协作
- **目标**: 验证模块间集成和交互
- **位置**:
  - **业务模块包**: `packages/*-module/tests/integration/**/*.test.ts`
  - **server包**: `packages/server/tests/integration/**/*.test.ts` (模块集成测试)
  - **web应用**: `web/tests/integration/**/*.test.{ts,tsx}`
- **框架**: Vitest + Testing Library + hono/testing + shared-test-util
- **覆盖率目标**: ≥ 60%
- **执行频率**: 每次API变更

### E2E测试 (End-to-End Tests)
- **范围**: 完整用户流程
- **目标**: 验证端到端业务流程
- **位置**: `web/tests/e2e/**/*.test.{ts,tsx}`
- **框架**: Playwright
- **覆盖率目标**: 关键用户流程100%
- **执行频率**: 每日或每次重大变更

### 小程序测试策略
- **项目**: mini小程序 (Taro小程序)
- **测试框架**: Jest (不是Vitest)
- **测试位置**: `mini/tests/unit/**/*.test.{ts,tsx}`
- **测试特点**:
  - 使用Jest测试框架，配置在`mini/jest.config.js`中
  - 包含Taro小程序API的模拟 (`__mocks__/taroMock.ts`)
  - 组件测试使用React Testing Library
  - 支持TypeScript和ES6+语法
- **测试命令**:
  - `pnpm test` - 运行所有测试
  - `pnpm test --testNamePattern "测试名称"` - 运行特定测试
  - `pnpm test:coverage` - 生成覆盖率报告

## 测试环境配置

### 开发环境
```typescript
// vitest.config.ts - 开发环境配置
export default defineConfig({
  test: {
    projects: [
      // Node.js 环境项目 - 后端测试
      {
        test: {
          include: [
            'tests/unit/server/**/*.test.{ts,js}',
            'tests/integration/server/**/*.test.{ts,js}'
          ],
          // ... 其他配置
        }
      },
      // Happy DOM 环境项目 - 前端组件测试
      {
        test: {
          include: [
            'tests/unit/client/**/*.test.{ts,js,tsx,jsx}',
            'tests/integration/client/**/*.test.{ts,js,tsx,jsx}'
          ],
          // ... 其他配置
        }
      }
    ]
  }
});
```

### CI/CD环境
```yaml
# GitHub Actions 测试配置 (模块化包架构)
name: Test Pipeline

jobs:
  # 基础设施包测试
  shared-packages-tests:
    runs-on: ubuntu-latest
    steps:
      - run: cd packages/shared-types && pnpm test
      - run: cd packages/shared-utils && pnpm test
      - run: cd packages/shared-crud && pnpm test
      - run: cd packages/shared-test-util && pnpm test

  # 业务模块包测试
  business-modules-tests:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:17
        env:
          POSTGRES_PASSWORD: test_password
          POSTGRES_DB: test_d8dai
    steps:
      - run: cd packages/user-module && pnpm test
      - run: cd packages/auth-module && pnpm test
      - run: cd packages/file-module && pnpm test
      - run: cd packages/geo-areas && pnpm test

  # 服务器集成测试
  server-integration-tests:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:17
        env:
          POSTGRES_PASSWORD: test_password
          POSTGRES_DB: test_d8dai
    steps:
      - run: cd packages/server && pnpm test

  # Web应用测试
  web-integration-tests:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:17
        env:
          POSTGRES_PASSWORD: test_password
          POSTGRES_DB: test_d8dai
    steps:
      - run: cd web && pnpm test:integration

  web-component-tests:
    runs-on: ubuntu-latest
    steps:
      - run: cd web && pnpm test:components

  web-e2e-tests:
    runs-on: ubuntu-latest
    steps:
      - run: cd web && pnpm test:e2e:chromium
```

## 测试覆盖率标准

### 各层覆盖率要求
| 测试类型 | 最低要求 | 目标要求 | 关键模块要求 |
|----------|----------|----------|--------------|
| 单元测试 | 70% | 80% | 90% |
| 集成测试 | 50% | 60% | 70% |
| E2E测试 | 关键流程100% | 主要流程80% | - |

### 关键模块定义
- **认证授权模块**: 必须达到90%单元测试覆盖率
- **数据库操作模块**: 必须达到85%单元测试覆盖率
- **核心业务逻辑**: 必须达到80%集成测试覆盖率
- **用户管理功能**: 必须100% E2E测试覆盖

## 测试数据管理

### 测试数据策略
```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. **测试数据隔离** (使用唯一标识符)

## API模拟规范

### 概述
API模拟规范为管理后台UI包提供测试中的API模拟策略。虽然当前项目实践中每个UI包都有自己的客户端管理器，但为了简化测试复杂度、特别是跨UI包集成测试场景，规范要求统一模拟共享UI组件包中的`rpcClient`函数。

### 问题背景
当前实现中，每个UI包测试文件模拟自己的客户端管理器（如`AdvertisementClientManager`、`UserClientManager`）。这种模式在单一UI包测试时可行，但在**跨UI包集成测试**时存在严重问题：

**示例场景**：收货地址UI包中使用区域管理UI包的区域选择组件，两个组件分别使用各自的客户端管理器。
- 收货地址组件 → 使用`DeliveryAddressClientManager`
- 区域选择组件 → 使用`AreaClientManager`
- 测试时需要同时模拟两个客户端管理器，配置复杂且容易冲突

**统一模拟优势**：通过模拟`@d8d/shared-ui-components`包中的`rpcClient`函数，可以：
1. **统一控制**：所有API调用都经过同一个模拟点
2. **简化配置**：无需关心具体客户端管理器，只需配置API响应
3. **跨包支持**：天然支持多个UI包组件的集成测试
4. **维护性**：API响应配置集中管理，易于更新

### 现有模式分析（仅供参考）
项目中的管理后台UI包当前遵循以下架构模式：
1. **客户端管理器模式**：每个UI包都有一个客户端管理器类（如`AdvertisementClientManager`、`UserClientManager`）
2. **rpcClient使用**：客户端管理器使用`@d8d/shared-ui-components`包中的`rpcClient`函数创建Hono RPC客户端
3. **API结构**：生成的客户端使用Hono风格的方法调用（如`index.$get`、`index.$post`、`:id.$put`等）

**注意**：新的测试规范要求直接模拟`rpcClient`函数，而不是模拟各个客户端管理器。

### rpcClient函数分析
`rpcClient`函数位于`@d8d/shared-ui-components`包的`src/utils/hc.ts`文件中，其核心功能是创建Hono RPC客户端：

```typescript
// packages/shared-ui-components/src/utils/hc.ts
export const rpcClient = <T extends Hono<any, any, any>>(aptBaseUrl: string): ReturnType<typeof hc<T>> => {
  return hc<T>(aptBaseUrl, {
    fetch: axiosFetch
  })
}
```

该函数接收API基础URL参数，返回一个配置了axios适配器的Hono客户端实例。

### 模拟策略

#### 1. 统一模拟rpcClient函数
在测试中，使用Vitest的`vi.mock`直接模拟`@d8d/shared-ui-components`包中的`rpcClient`函数，统一拦截所有API调用：

```typescript
// 测试文件顶部 - 统一模拟rpcClient函数
import { vi } from 'vitest'
import type { Hono } from 'hono'

// 创建模拟的rpcClient函数
const mockRpcClient = vi.fn((aptBaseUrl: string) => {
  // 根据页面组件实际调用的RPC路径定义模拟端点
  return {
    // 收货地址UI包使用的端点
    index: {
      $get: vi.fn(),
      $post: vi.fn(),
    },
    ':id': {
      $put: vi.fn(),
      $delete: vi.fn(),
    },

    // 区域管理UI包使用的端点（跨包集成）
    provinces: {
      $get: vi.fn(),
    },

    // 地区列表API端点
    $get: vi.fn(),
  }
})

// 模拟共享UI组件包中的rpcClient函数
vi.mock('@d8d/shared-ui-components/utils/hc', () => ({
  rpcClient: mockRpcClient
}))
```

#### 2. 创建模拟响应辅助函数
创建通用的模拟响应辅助函数，用于生成一致的API响应格式：

```typescript
// 在测试文件中定义或从共享工具导入
const createMockResponse = (status: number, data?: any) => ({
  status,
  ok: status >= 200 && status < 300,
  body: null,
  bodyUsed: false,
  statusText: status === 200 ? 'OK' : status === 201 ? 'Created' : status === 204 ? 'No Content' : 'Error',
  headers: new Headers(),
  url: '',
  redirected: false,
  type: 'basic' as ResponseType,
  json: async () => data || {},
  text: async () => '',
  blob: async () => new Blob(),
  arrayBuffer: async () => new ArrayBuffer(0),
  formData: async () => new FormData(),
  clone: function() { return this; }
});

// 创建简化版响应工厂（针对常见业务数据结构）
const createMockApiResponse = <T>(data: T, success = true) => ({
  success,
  data,
  timestamp: new Date().toISOString()
})

const createMockErrorResponse = (message: string, code = 'ERROR') => ({
  success: false,
  error: { code, message },
  timestamp: new Date().toISOString()
})
```

#### 3. 在测试用例中配置模拟响应
在测试用例的`beforeEach`或具体测试中配置模拟响应，支持跨UI包集成：

```typescript
// 跨UI包集成测试示例：收货地址UI包（包含区域选择组件）
describe('收货地址管理（跨UI包集成）', () => {
  let mockClient: any;

  beforeEach(() => {
    vi.clearAllMocks();

    // 获取模拟的rpcClient实例
    mockClient = mockRpcClient('/');

    // 配置收货地址API响应（收货地址UI包）
    mockClient.index.$get.mockResolvedValue(createMockResponse(200, {
      data: [
        {
          id: 1,
          name: '测试地址',
          phone: '13800138000',
          provinceId: 1,
          cityId: 2,
          districtId: 3,
          detail: '测试街道'
        }
      ],
      pagination: { total: 1, page: 1, pageSize: 10 }
    }));

    mockClient.index.$post.mockResolvedValue(createMockResponse(201, {
      id: 2,
      name: '新地址'
    }));

    mockClient[':id']['$put'].mockResolvedValue(createMockResponse(200));
    mockClient[':id']['$delete'].mockResolvedValue(createMockResponse(204));

    // 配置区域API响应（区域管理UI包 - 跨包支持）
    mockClient.$get.mockResolvedValue(createMockResponse(200, {
      data: [
        { id: 1, name: '北京市', code: '110000', level: 1 },
        { id: 2, name: '朝阳区', code: '110105', level: 2, parentId: 1 },
        { id: 3, name: '海淀区', code: '110108', level: 2, parentId: 1 }
      ]
    }));

    mockClient.provinces.$get.mockResolvedValue(createMockResponse(200, {
      data: [
        { id: 1, name: '北京市', code: '110000' },
        { id: 2, name: '上海市', code: '310000' }
      ]
    }));

    // 获取某个地区的子地区（如城市）通常通过查询参数实现
    mockClient.$get.mockImplementation((options?: any) => {
      if (options?.query?.parentId === 1) {
        return Promise.resolve(createMockResponse(200, {
          data: [
            { id: 2, name: '朝阳区', code: '110105', parentId: 1 },
            { id: 3, name: '海淀区', code: '110108', parentId: 1 }
          ]
        }));
      }
      // 默认返回空列表
      return Promise.resolve(createMockResponse(200, { data: [] }));
    });
  });

  it('应该显示收货地址列表并支持区域选择', async () => {
    // 测试代码：验证收货地址UI和区域选择组件都能正常工作
    // 所有API调用都通过统一的mockRpcClient模拟
  });

  it('应该处理API错误场景', async () => {
    // 模拟API错误
    mockClient.index.$get.mockRejectedValue(new Error('网络错误'));

    // 测试错误处理
  });
});
```

### 管理后台UI包测试策略

#### 1. 模拟范围
- **统一模拟点**: 集中模拟`@d8d/shared-ui-components/utils/hc`中的`rpcClient`函数
- **HTTP方法**: 支持Hono风格的`$get`、`$post`、`$put`、`$delete`方法
- **API端点**: 支持标准端点（`index`）、参数化端点（`:id`）和属性访问端点（如`client.provinces.$get()`）
- **响应格式**: 模拟完整的Response对象，包含`status`、`ok`、`json()`等方法
- **跨包支持**: 天然支持多个UI包组件的API模拟，无需分别模拟客户端管理器

#### 2. 测试设置
1. **统一模拟**: 在每个测试文件顶部使用`vi.mock`统一模拟`rpcClient`函数
2. **测试隔离**: 每个测试用例使用独立的模拟实例，在`beforeEach`中重置
3. **响应配置**: 根据测试场景配置不同的模拟响应（成功、失败、错误等）
4. **错误测试**: 模拟各种错误场景（网络错误、验证错误、权限错误、服务器错误等）
5. **跨包集成**: 支持配置多个UI包的API响应，适用于组件集成测试

#### 3. 最佳实践
- **统一模拟**: 所有API调用都通过模拟`rpcClient`函数统一拦截
- **按需定义**: 根据页面组件实际调用的RPC路径定义模拟端点，无需动态创建所有可能端点
- **类型安全**: 使用TypeScript确保模拟响应与API类型兼容
- **可维护性**: 保持模拟响应与实际API响应结构一致，便于后续更新
- **文档化**: 在测试注释中说明模拟的API行为和预期结果
- **响应工厂**: 创建可重用的模拟响应工厂函数，确保响应格式一致性
- **跨包考虑**: 为集成的UI包组件配置相应的API响应

### 验证和调试

#### 1. 模拟验证
```typescript
// 验证API调用次数和参数 - 使用统一模拟的rpcClient
describe('API调用验证（统一模拟）', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('应该验证API调用次数和参数', async () => {
    // 获取模拟的客户端实例
    const mockClient = mockRpcClient('/');

    // 配置模拟响应
    mockClient.index.$get.mockResolvedValue(createMockResponse(200, { data: [] }));
    mockClient.index.$post.mockResolvedValue(createMockResponse(201, { id: 1 }));
    mockClient[':id']['$put'].mockResolvedValue(createMockResponse(200));
    mockClient.$get.mockResolvedValue(createMockResponse(200, { data: [] }));

    // 执行测试代码（触发API调用）...

    // 验证API调用次数
    expect(mockClient.index.$get).toHaveBeenCalledTimes(1);
    expect(mockClient.$get).toHaveBeenCalledTimes(1);

    // 验证API调用参数
    expect(mockClient.index.$post).toHaveBeenCalledWith({
      json: {
        title: '新广告',
        code: 'new-ad',
        typeId: 1
      }
    });

    // 验证带参数的API调用
    expect(mockClient[':id']['$put']).toHaveBeenCalledWith({
      param: { id: 1 },
      json: {
        title: '更新后的广告'
      }
    });

    // 验证地区API调用
    expect(mockClient.$get).toHaveBeenCalledWith({
      query: { level: 1 }
    });
  });

  it('应该验证错误场景', async () => {
    const mockClient = mockRpcClient('/');

    // 配置错误响应
    mockClient.index.$get.mockRejectedValue(new Error('网络错误'));

    // 执行测试代码...

    // 验证错误调用
    expect(mockClient.index.$get).toHaveBeenCalledTimes(1);
  });
});
```

#### 2. 调试技巧
- **console.debug**: 在测试中使用`console.debug`输出模拟调用信息，便于调试
  ```typescript
  // 在测试中输出调试信息
  console.debug('Mock client calls:', {
    getCalls: mockClient.index.$get.mock.calls,
    postCalls: mockClient.index.$post.mock.calls
  });
  ```

- **调用检查**: 使用`vi.mocked()`检查模拟函数的调用参数和次数
  ```typescript
  // 检查mockRpcClient的调用
  const mockCalls = vi.mocked(mockRpcClient).mock.calls;
  console.debug('rpcClient调用参数:', mockCalls);

  // 检查具体端点调用
  const getCalls = vi.mocked(mockClient.index.$get).mock.calls;
  ```

- **响应验证**: 确保模拟响应的格式与实际API响应一致
  ```typescript
  // 验证响应格式
  const response = await mockClient.index.$get();
  expect(response.status).toBe(200);
  expect(response.ok).toBe(true);
  const data = await response.json();
  expect(data).toHaveProperty('data');
  expect(data).toHaveProperty('pagination');
  ```

- **错误模拟**: 测试各种错误场景，确保UI能正确处理
  ```typescript
  // 模拟不同类型的错误
  mockClient.index.$get.mockRejectedValue(new Error('网络错误')); // 网络错误
  mockClient.index.$get.mockResolvedValue(createMockResponse(500)); // 服务器错误
  mockClient.index.$get.mockResolvedValue(createMockResponse(401)); // 认证错误
  ```

- **快照测试**: 使用Vitest的快照测试验证UI在不同API响应下的渲染结果
- **跨包调试**: 在跨UI包集成测试中，验证所有相关API都正确配置了模拟响应

## 测试执行流程

### 本地开发测试

#### 基础设施包
```bash
# 运行所有基础设施包测试
cd packages/shared-types && pnpm test
cd packages/shared-utils && pnpm test
cd packages/shared-crud && pnpm test
cd packages/shared-test-util && pnpm test

# 生成覆盖率报告
cd packages/shared-utils && pnpm test:coverage
```

#### 业务模块包
```bash
# 运行所有业务模块包测试
cd packages/user-module && pnpm test
cd packages/auth-module && pnpm test
cd packages/file-module && pnpm test
cd packages/geo-areas && pnpm test

# 运行单元测试
cd packages/user-module && pnpm test:unit

# 运行集成测试
cd packages/auth-module && pnpm test:integration

# 生成覆盖率报告
cd packages/user-module && pnpm test:coverage
```

#### server包
```bash
# 运行所有测试
cd packages/server && pnpm test

# 运行集成测试
cd packages/server && pnpm test:integration

# 生成覆盖率报告
cd packages/server && pnpm test:coverage
```

#### web应用
```bash
# 运行所有测试
cd web && pnpm test

# 运行单元测试
cd web && pnpm test:unit

# 运行集成测试
cd web && pnpm test:integration

# 运行组件测试
cd web && pnpm test:components

# 运行E2E测试
cd web && pnpm test:e2e:chromium

# 生成覆盖率报告
cd web && pnpm test:coverage
```

#### 小程序 (mini)
```bash
# 运行所有测试
cd mini && pnpm test

# 运行特定测试
cd mini && pnpm test --testNamePattern "商品卡片"

# 生成覆盖率报告
cd mini && pnpm test:coverage

# 调试测试
cd mini && pnpm test --testNamePattern "测试名称" --verbose
```

### CI/CD流水线测试
1. **代码推送** → 触发测试流水线
2. **单元测试** → 快速反馈，必须通过
3. **集成测试** → 验证模块集成，必须通过
4. **E2E测试** → 验证完整流程，建议通过
5. **覆盖率检查** → 满足最低要求
6. **测试报告** → 生成详细报告

## 质量门禁

### 测试通过标准
- ✅ 所有单元测试通过
- ✅ 所有集成测试通过
- ✅ 关键E2E测试通过
- ✅ 覆盖率满足最低要求
- ✅ 无性能回归
- ✅ 安全测试通过

### 失败处理流程
1. **测试失败** → 立即通知开发团队
2. **分析根本原因** → 确定是测试问题还是代码问题
3. **优先修复** → 阻塞性问题必须立即修复
4. **重新测试** → 修复后重新运行测试
5. **文档更新** → 更新测试策略和案例

## 安全测试策略

### 安全测试要求
- **输入验证测试**: 所有API端点必须测试SQL注入、XSS等攻击
- **认证测试**: 测试令牌验证、权限控制
- **数据保护**: 测试敏感数据泄露风险
- **错误处理**: 测试错误信息是否泄露敏感数据

### 安全测试工具
- **OWASP ZAP**: 自动化安全扫描
- **npm audit**: 依赖漏洞检查
- **自定义安全测试**: 针对业务逻辑的安全测试

## 性能测试策略

### 性能测试要求
- **API响应时间**: < 100ms (p95)
- **数据库查询性能**: < 50ms (p95)
- **并发用户数**: 支持100+并发用户
- **资源使用**: CPU < 70%, 内存 < 80%

### 性能测试工具
- **k6**: 负载测试
- **autocannon**: API性能测试
- **Playwright**: E2E性能监控

## 测试文档标准

### 测试代码规范
```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('用户名已存在');
    });
  });
});
```

### 测试命名约定
- **文件名**: `[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**: 3.2.4
- **Testing Library**: 16.3.0
- **Playwright**: 1.55.0
- **hono/testing**: 内置（Hono 4.8.5）
- **shared-test-util**: 1.0.0 (测试基础设施包)
- **TypeORM**: 0.3.20 (数据库测试)
- **Redis**: 7.0.0 (会话管理测试)
- **Jest**: 29.x (mini小程序专用)

### 更新日志
| 日期 | 版本 | 描述 |
|------|------|------|
| 2025-11-11 | 2.8 | 更新包测试结构，添加模块化包测试策略 |
| 2025-11-09 | 2.7 | 更新为monorepo测试架构，清理重复测试文件 |
| 2025-10-15 | 2.6 | 完成遗留测试文件迁移到统一的tests目录结构 |
| 2025-10-14 | 2.5 | 重构测试文件结构，统一到tests目录 |
| 2025-09-20 | 2.4 | 更新版本与主架构文档一致 |
| 2025-09-19 | 1.0 | 初始版本，基于现有测试基础设施 |

---

**文档状态**: 正式版
**下次评审**: 2025-12-19