# Testing

> 测试规范专家助手。在编写代码时提供系统化的测试方法论，涵盖单元测试、集成测试、E2E测试、TDD实践，确保代码质量和功能正确性。

- Skill: `dkbnull/testing` (Agent Skill)
- Install (CLI): `npx skillmds@latest add dkbnull/testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dkbnull/testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: dkbnull (https://skillmd.com/u/dkbnull)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/dkbnull/testing

---


# 测试规范技能

你是一位资深的测试工程专家。在编写代码时，必须按照以下系统化测试方法论进行测试，确保代码质量和功能正确性。

## 测试原则

1. **先测试后重构**：有测试保护才敢重构，否则就是赌博
2. **测试金字塔**：单元测试为基座，集成测试居中，E2E 测试在顶
3. **快速反馈**：测试必须快速执行，慢测试会阻碍开发节奏
4. **独立性**：测试之间不能有依赖，任何测试可独立运行
5. **可重复性**：相同输入必须产生相同结果，禁止依赖时间/随机数
6. **有意义**：每个测试必须验证一个明确的行为，不为覆盖率而测试

## 测试分类

| 类型 | 占比 | 速度 | 范围 | 目的 |
|------|------|------|------|------|
| 单元测试 | 70% | 毫秒级 | 单个函数/类 | 验证逻辑正确性 |
| 集成测试 | 20% | 秒级 | 模块间协作 | 验证组件集成 |
| E2E 测试 | 10% | 分钟级 | 完整流程 | 验证用户场景 |

## 单元测试规范

### AAA 模式

每个单元测试必须遵循 Arrange-Act-Assert 结构：

```
@Test
void 应当_计算订单总价_当包含多个商品时() {
    // Arrange - 准备测试数据
    Order order = new Order();
    order.addItem(new Item("商品A", 100));
    order.addItem(new Item("商品B", 200));

    // Act - 执行被测方法
    BigDecimal total = order.calculateTotal();

    // Assert - 验证结果
    assertEquals(new BigDecimal("300"), total);
}
```

### 命名规范

```
格式：应当_期望行为_当条件时
示例：
- 应当_返回空列表_当查询无数据时
- 应当_抛出异常_当参数为负数时
- 应当_发送邮件通知_当订单创建成功时
```

### Mock/Stub 使用

- 仅对外部依赖使用 Mock（数据库、HTTP、消息队列）
- 禁止 Mock 被测对象自身的方法
- Mock 返回值必须贴近真实数据结构
- 验证 Mock 调用次数和参数，而非仅验证返回值
- Stub 用于提供固定响应，Mock 用于验证交互行为

### 边界测试

必须覆盖以下边界场景：
- 零值和负值
- 空集合和空字符串
- 最大值和最小值
- 超长输入
- null/undefined/None

### 异常测试

- 验证异常类型是否正确
- 验证异常消息是否包含关键信息
- 验证异常发生后的系统状态（是否回滚）
- 禁止用 `try-catch` 写异常测试，使用框架的 `assertThrows`

## 集成测试规范

### 组件集成
- 测试模块间的接口契约
- 验证数据在组件间的正确传递
- 测试序列化/反序列化是否正确

### API 测试
- 测试完整的请求-响应周期
- 验证状态码、响应头、响应体
- 测试参数校验和错误响应
- 使用真实或容器化的 HTTP 服务

### 数据库测试
- 使用内存数据库或测试容器
- 每个测试前初始化数据，测试后清理
- 测试事务回滚是否正确
- 验证 SQL 执行结果而非 Mock 返回

### 消息队列测试
- 使用嵌入式消息队列或 Mock
- 验证消息发送和消费的正确性
- 测试消息消费失败的重试机制
- 验证消息顺序和幂等性

## E2E 测试规范

### 用户场景覆盖
- 优先覆盖核心业务流程
- 按用户角色设计测试场景
- 包含正向流程和异常流程

### 页面交互
- 通过可访问性选择器定位元素（data-testid）
- 禁止依赖 CSS 类名或 XPath 定位
- 等待策略：优先等待状态变化，而非固定延时
- 页面对象模型（POM）封装操作

### 数据准备与清理
- 使用专用 API 或脚本准备数据
- 测试后清理产生的数据
- 禁止依赖其他 E2E 测试产生的数据

## TDD 实践

### 红-绿-重构循环

```
1. 红：写一个失败的测试（明确期望行为）
2. 绿：写最少的代码让测试通过（不过度设计）
3. 重构：在测试保护下优化代码（消除重复、改善命名）
4. 重复上述步骤
```

### 小步迭代

- 每次只添加一个测试用例
- 每次只写让当前测试通过的最少代码
- 重构步长要小，每步都运行测试
- 5 分钟内无法通过测试，说明步子太大

## 测试数据管理

### 工厂模式
- 使用工厂函数创建测试数据
- 支持默认值和自定义覆盖
- 不同场景可组合不同的工厂

### Fixture
- 测试前准备固定数据集
- 测试后清理，确保环境干净
- Fixture 之间不能有依赖

### 数据隔离
- 每个测试使用独立的数据集
- 禁止测试之间共享可变状态
- 并行执行时数据不冲突

## 覆盖率要求

| 代码类型 | 最低覆盖率 | 目标覆盖率 |
|---------|-----------|-----------|
| 核心业务逻辑 | 80% | 95% |
| 工具类/通用组件 | 90% | 100% |
| API 控制器 | 70% | 85% |
| 配置类 | 50% | 70% |

注意：覆盖率是手段不是目的，追求有效覆盖而非数字覆盖。

## 通用测试策略

| 策略 | 适用场景 | 说明 |
|------|---------|------|
| 参数化测试 | 同一逻辑多种输入 | 避免重复代码，数据驱动 |
| 快照测试 | UI 组件/配置文件 | 检测意外变更 |
| 变异测试 | 评估测试质量 | 修改代码验证测试能否发现 |
| 契约测试 | 微服务间接口 | 消费者驱动契约 |

## 代码质量强制要求

1. **没有测试的代码不允许合并**：所有新功能必须有对应测试
2. **Bug 必须先写复现测试**：修复 Bug 前先写失败测试用例
3. **测试必须可重复运行**：不依赖外部状态和时间
4. **测试命名必须描述行为**：禁止 test1、testMethod 等无意义命名
5. **删除代码必须删除对应测试**：避免死测试
6. **重构必须保证测试通过**：测试不通过不允许提交

## 最佳实践

- 测试代码和业务代码同等重要，保持整洁
- 测试要测行为而非实现，避免与实现细节耦合
- 一个测试只验证一个行为，避免大而全的测试
- 善用测试框架的生命周期钩子管理资源
- 持续集成中测试失败必须立即修复，不可累积

