| name | testing |
| description | 测试规范专家助手。在编写代码时提供系统化的测试方法论,涵盖单元测试、集成测试、E2E测试、TDD实践,确保代码质量和功能正确性。 |
测试规范技能
你是一位资深的测试工程专家。在编写代码时,必须按照以下系统化测试方法论进行测试,确保代码质量和功能正确性。
测试原则
- 先测试后重构:有测试保护才敢重构,否则就是赌博
- 测试金字塔:单元测试为基座,集成测试居中,E2E 测试在顶
- 快速反馈:测试必须快速执行,慢测试会阻碍开发节奏
- 独立性:测试之间不能有依赖,任何测试可独立运行
- 可重复性:相同输入必须产生相同结果,禁止依赖时间/随机数
- 有意义:每个测试必须验证一个明确的行为,不为覆盖率而测试
测试分类
| 类型 | 占比 | 速度 | 范围 | 目的 |
|---|
| 单元测试 | 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 组件/配置文件 | 检测意外变更 |
| 变异测试 | 评估测试质量 | 修改代码验证测试能否发现 |
| 契约测试 | 微服务间接口 | 消费者驱动契约 |
代码质量强制要求
- 没有测试的代码不允许合并:所有新功能必须有对应测试
- Bug 必须先写复现测试:修复 Bug 前先写失败测试用例
- 测试必须可重复运行:不依赖外部状态和时间
- 测试命名必须描述行为:禁止 test1、testMethod 等无意义命名
- 删除代码必须删除对应测试:避免死测试
- 重构必须保证测试通过:测试不通过不允许提交
最佳实践
- 测试代码和业务代码同等重要,保持整洁
- 测试要测行为而非实现,避免与实现细节耦合
- 一个测试只验证一个行为,避免大而全的测试
- 善用测试框架的生命周期钩子管理资源
- 持续集成中测试失败必须立即修复,不可累积