Test Design Skill
A structured approach to designing tests that give confidence without excessive maintenance burden.
Core Philosophy
Test behavior, not implementation. Tests that couple to internal implementation details become fragile and refactor-resistant. Aim to test what the code does, not how it does it.
The best test is the one that fails when something breaks, and passes when everything works. Perfect coverage means nothing if tests don't catch real bugs.
Testing Pyramid
CODEBLOCK0
Unit tests form the base — fast, isolated, cover individual functions.
Integration tests verify components work together.
E2E tests validate complete user journeys.
Test Case Design
Arrange-Act-Assert (AAA) Pattern
CODEBLOCK1
Given-When-Then (GWT) Pattern
CODEBLOCK2
Test Categories
🔴 Happy Path Tests
- - Verify the main success scenario works
- At least one per feature/function
🟡 Edge Case Tests
- - Boundary values (0, -1, max integer)
- Empty/null inputs
- Rare but possible conditions
🟡 Error Case Tests
- - Invalid inputs
- Missing dependencies
- Permission denied scenarios
🟢 Edge/Extreme Cases
- - Very large inputs
- Very small inputs
- Unicode/special characters
- Concurrent access
Test Doubles (Mocks/Stubs/Fakes)
| Type | Purpose | Use When |
|---|
| Dummy | Fill parameter lists | Never actually used |
| Stub |
Provide predetermined responses | Test requires specific data |
|
Spy | Record how something was called | Verify interactions |
|
Mock | Pre-programmed expectations | Verify behavior + interactions |
|
Fake | Working implementation (simplified) | Real impl too slow/complex |
Rule: Prefer real objects over mocks when practical. Mocks hide integration problems.
Test Naming Convention
CODEBLOCK3
Examples:
- - INLINECODE0
- INLINECODE1
- INLINECODE2
Coverage Targets
| Layer | Target | Purpose |
|---|
| Unit | 70-80% | Core business logic |
| Integration |
40-60% | Key flows work together |
| E2E | Critical paths only | User journeys |
Note: Coverage is a guide, not a goal. 100% coverage with shallow tests is worse than 70% with meaningful assertions.
Test Execution
Unit Tests
Run frequently during development (every save).
CODEBLOCK4
Integration Tests
Run before PR, after unit tests pass.
CODEBLOCK5
E2E Tests
Run on CI against deployed environment.
CODEBLOCK6
Test Data Management
Strategies
- 1. Factories/Fixtures — Create test data on demand
- Seeded Data — Deterministic test datasets
- Randomized Data — Fuzz testing with random inputs
- Snapshot Testing — Verify serializable outputs
Best Practices
- - Tests should be independent (no shared state)
- Each test should clean up after itself
- Use meaningful data, not magic values
- Avoid test interdependencies
File Structure
CODEBLOCK7
测试设计技能
一种结构化的测试设计方法,既能提供信心,又不会带来过重的维护负担。
核心理念
测试行为,而非实现。 与内部实现细节耦合的测试会变得脆弱且难以重构。目标是测试代码做什么,而不是如何做。
最好的测试是:当代码出错时失败,一切正常时通过。 如果测试无法捕获真正的缺陷,完美的覆盖率也毫无意义。
测试金字塔
┌─────────┐
│ E2E │ ← 少量、慢速、高置信度
┌┴─────────┴┐
│ 集成测试 │ ← 适量、中等速度
┌┴───────────┴┐
│ 单元测试 │ ← 大量、快速、细粒度
└─────────────┘
单元测试构成基础——快速、隔离、覆盖单个函数。
集成测试验证组件协同工作。
E2E测试验证完整的用户旅程。
测试用例设计
安排-执行-断言(AAA)模式
python
def testwithdrawamountexceedsbalance():
# 安排
account = Account(balance=Decimal(100.00))
# 执行
result = account.withdraw(Decimal(150.00))
# 断言
assert result.is_failed()
assert account.balance == Decimal(100.00) # 保持不变
给定-当-那么(GWT)模式
gherkin
功能:账户取款
场景:取款金额超过余额
给定一个余额为100美元的账户
当我取款150美元
那么取款被拒绝
并且余额仍为100美元
测试分类
🔴 快乐路径测试
- - 验证主要成功场景是否正常
- 每个功能/特性至少一个
🟡 边界情况测试
- - 边界值(0, -1, 最大整数)
- 空/空值输入
- 罕见但可能发生的条件
🟡 错误情况测试
🟢 边缘/极端情况
- - 非常大的输入
- 非常小的输入
- Unicode/特殊字符
- 并发访问
测试替身(模拟/桩/伪造)
提供预设响应 | 测试需要特定数据 |
|
间谍 | 记录调用方式 | 验证交互 |
|
模拟 | 预编程期望 | 验证行为+交互 |
|
伪造 | 工作实现(简化版) | 真实实现太慢/太复杂 |
规则: 在可行时优先使用真实对象而非模拟。模拟会隐藏集成问题。
测试命名规范
test<单元><场景>_<预期结果>
示例:
- - testusercreatewithvalidinputsucceeds
- testusercreatewithduplicateemailfails
- testordercancelaftershipmentrefundsfull_amount
覆盖率目标
| 层级 | 目标 | 目的 |
|---|
| 单元测试 | 70-80% | 核心业务逻辑 |
| 集成测试 |
40-60% | 关键流程协同工作 |
| E2E测试 | 仅关键路径 | 用户旅程 |
注意: 覆盖率是指导而非目标。100%的浅层测试不如70%的有意义断言。
测试执行
单元测试
开发过程中频繁运行(每次保存)。
bash
Go
go test ./...
Python
pytest tests/unit/ -v
TypeScript
npm test -- --coverage
集成测试
在PR前、单元测试通过后运行。
bash
启动依赖
docker-compose up -d
运行集成测试套件
pytest tests/integration/ -v
E2E测试
在CI上针对已部署环境运行。
bash
CI/CD流水线
npm run test:e2e -- --specs=critical-paths
测试数据管理
策略
- 1. 工厂/夹具 — 按需创建测试数据
- 种子数据 — 确定性的测试数据集
- 随机数据 — 使用随机输入进行模糊测试
- 快照测试 — 验证可序列化的输出
最佳实践
- - 测试应相互独立(无共享状态)
- 每个测试应自行清理
- 使用有意义的数据,而非魔法值
- 避免测试间的依赖
文件结构
test-design/
├── SKILL.md
└── references/
├── test-case-templates.md
├── testing-pyramid.md
├── mocking-strategies.md
├── test-naming-conventions.md
└── per-type/
├── unit-test-guide.md
├── integration-test-guide.md
└── e2e-test-guide.md