name: vitest-testing description: “AI友好的Vitest全面测试指南,包含实用模式和行为驱动开发。”
Vitest 测试技能 - 主参考
AI友好的Vitest全面测试指南,包含实用模式和行为驱动开发。
给人类: 从 README.md 开始全面导航 给AI代理: 此文件提供所有技能资源的快速访问
🎯 代理快速访问
决策支持
- 我应该写什么类型的测试? → index.md
- 我如何组织这个测试? → principles/aaa-pattern.md
- 这段代码可测试吗? → refactoring/testability-patterns.md
最常引用的模式
- F.I.R.S.T 原则 - 快速、隔离、可重复、自检、及时
- AAA 模式 - 安排-行动-断言结构
- 黑盒测试 - 通过公共API测试行为
- 测试替身 - 模拟、存根、间谍、假对象
📚 技能组织
核心原则 /principles/
指导所有测试决策的基础概念:
| 文件 | 目的 | 何时使用 |
|---|---|---|
| first-principles.md | F.I.R.S.T 质量属性 | 每个测试 |
| aaa-pattern.md | 安排-行动-断言结构 | 组织测试 |
| bdd-integration.md | Given/When/Then 与 AAA | 业务聚焦测试 |
测试策略 /strategies/
不同测试场景的方法:
| 文件 | 目的 | 何时使用 |
|---|---|---|
| black-box-testing.md | 通过公共API测试 | 默认方法(99% 的测试) |
| implementation-details.md | 何时测试内部 | 仅在极少数例外 |
实用模式 /patterns/
常用场景的即用模式:
| 文件 | 目的 | 何时使用 |
|---|---|---|
| test-doubles.md | 模拟、存根、间谍、假对象 | 隔离依赖 |
| async-testing.md | 测试承诺,async/await | 异步操作 |
| error-testing.md | 测试异常,边缘情况 | 错误场景 |
| component-testing.md | React/Vue 组件模式 | UI组件 |
| api-testing.md | HTTP客户端,REST API | API集成 |
| performance-testing.md | 基准测试,负载测试 | 性能关键代码 |
| test-data.md | 工厂、构建器、固定装置 | 测试数据管理 |
重构以提高可测试性 /refactoring/
将不可测试的代码转化为可测试的代码:
| 文件 | 目的 | 何时使用 |
|---|---|---|
| testability-patterns.md | 提取纯函数,DI等 | 难以测试的代码 |
快速参考 /quick-reference/
快速查找和决策辅助:
| 文件 | 目的 | 何时使用 |
|---|---|---|
| cheatsheet.md | 语法,匹配器,模拟 | 快速语法查找 |
| jest-to-vitest.md | 从Jest迁移 | 迁移项目 |
🤖 代理集成点
对于 typescript-coder 代理
编写测试时:
// 1. 检查决策树
const testType = checkDecisionTree(codeType)
// 参考:/skills/vitest-testing/index.md
// 2. 应用 F.I.R.S.T 原则
ensureTestsAreFast() // < 100ms
ensureTestsAreIsolated() // 无共享状态
// 参考:/skills/vitest-testing/principles/first-principles.md
// 3. 使用 AAA 结构
// 安排 → 行动 → 断言
// 参考:/skills/vitest-testing/principles/aaa-pattern.md
// 4. 遵循黑盒策略
testThroughPublicAPI() // 不是私有方法
// 参考:/skills/vitest-testing/strategies/black-box-testing.md
重构时:
// 检查代码是否可测试
if (isHardToTest(code)) {
// 应用可测试性模式
applyPattern(testabilityPatterns)
// 参考:/skills/vitest-testing/refactoring/testability-patterns.md
}
对于代码审查代理
检查这些方面:
- [ ] 测试遵循 F.I.R.S.T 原则
- [ ] 测试使用 AAA 结构
- [ ] 测试使用黑盒方法(仅限公共API)
- [ ] 正确模拟外部依赖
- [ ] 覆盖错误场景
- [ ] 正确处理异步操作
🎯 常见工作流
工作流 1:为新功能编写测试
1. 咨询决策树 → /skills/vitest-testing/index.md
2. 确定测试类型 → 单元/集成/组件
3. 应用 F.I.R.S.T 原则 → /skills/vitest-testing/principles/first-principles.md
4. 使用 AAA 结构 → /skills/vitest-testing/principles/aaa-pattern.md
5. 使用相关模式 → /skills/vitest-testing/patterns/
6. 参考示例 → /skills/vitest-testing/examples/(创建时)
工作流 2:为可测试性重构
1. 确定痛点 → 什么使得这难以测试?
2. 选择模式 → /skills/vitest-testing/refactoring/testability-patterns.md
3. 应用模式 → 提取纯函数,注入依赖等
4. 编写测试 → 重构代码的黑盒测试
5. 验证 → 所有测试通过,代码更容易测试
工作流 3:测试异步代码
1. 检查异步模式 → /skills/vitest-testing/patterns/async-testing.md
2. 模拟外部API → /skills/vitest-testing/patterns/test-doubles.md
3. 控制时间 → 使用 vi.useFakeTimers()
4. 测试状态 → 加载中、成功、错误
5. 验证清理 → 资源释放
📖 哲学
这项技能遵循以下核心信念:
1. 行为优于实现
测试应该验证代码做了什么,而不是怎么做的。关注可观察的结果和公共契约。实现细节应该通过公共API间接测试。
2. 例子驱动学习
每个原则都包括实际例子。重构前后展示了影响。完整的例子提供了工作模板。
3. 可测试性由设计决定
难以测试的代码设计不良。重构模式将不可测试的代码转化为可测试的。可测试性的提高增强了整体代码质量。
4. F.I.R.S.T 质量
快速、隔离、可重复、自检、及时的测试创建了一个开发者信任并维护的有价值的安全网。
🔍 技能图
vitest-testing/
├── SKILL.md ← 你在这里(AI代理入口点)
├── README.md ← 人类导航中心
├── index.md ← 决策树
├── principles/ ← 测试基础
│ ├── first-principles.md ← F.I.R.S.T(最重要的)
│ ├── aaa-pattern.md ← 测试结构
│ └── bdd-integration.md ← Given/When/Then
├── strategies/ ← 测试方法
│ ├── black-box-testing.md ← 默认策略
│ └── implementation-details.md ← 罕见例外
├── patterns/ ← 实际实现
│ ├── test-doubles.md ← 模拟(高度引用)
│ ├── component-testing.md ← React/UI测试
│ ├── async-testing.md ← 承诺,async/await
│ ├── error-testing.md ← 错误场景
│ ├── api-testing.md ← HTTP/API测试
│ ├── performance-testing.md ← 基准测试,负载测试
│ └── test-data.md ← 工厂,构建器
├── refactoring/ ← 使代码可测试
│ └── testability-patterns.md ← 提取,注入,隔离
└── quick-reference/ ← 快速查找
├── cheatsheet.md ← 语法参考
└── jest-to-vitest.md ← 迁移指南
🎓 学习路径
针对初学者
- F.I.R.S.T 原则 - 理解质量属性
- AAA 模式 - 学习测试结构
- Cheatsheet - 基本语法
- 测试替身 - 模拟基础
针对中级开发者
针对高级开发者
🚀 与其他技能集成
与 architecture-patterns 技能
- 领域模型 → 测试业务规则(黑盒)
- 聚合 → 测试不变性
- 用例 → 测试编排与模拟
- 存储库 → 测试与内存实现
与 typescript-coder 代理
- 自动引用此技能进行测试生成
- 应用 F.I.R.S.T 原则
- 使用 AAA 结构
- 遵循黑盒策略
📊 统计
创建文件: 20+ 覆盖范围:
- ✅ 核心原则(F.I.R.S.T,AAA,BDD)
- ✅ 测试策略(黑盒,实现细节)
- ✅ 实用模式(模拟,异步,错误,组件,API,性能,测试数据)
- ✅ 重构指导(可测试性模式)
- ✅ 快速参考(Cheatsheet,迁移指南)
集成:
- ✅ typescript-coder 代理更新
- ✅ 与 architecture-patterns 交叉引用
- ✅ 快速模式选择的决策树
💡 代理使用示例
示例 1:代理编写测试
// 代理收到:"为 UserService.register 函数编写测试"
// 第 1 步:检查决策树(index.md)
// → 新功能 → 单元测试(黑盒)
// 第 2 步:应用 F.I.R.S.T(first-principles.md)
// → 快速:模拟数据库
// → 隔离:每个 beforeEach 新鲜的模拟
// → 可重复:控制时间
// → 自检:使用 expect()
// → 及时:现在编写
// 第 3 步:使用 AAA 模式(aaa-pattern.md)
describe('UserService.register', () => {
it('创建用户并发送欢迎邮件', async () => {
// 安排
const mockDb = { users: { create: vi.fn().mockResolvedValue({...}) } }
const mockEmailer = { sendWelcome: vi.fn() }
const service = new UserService(mockDb, mockEmailer)
// 行动
const user = await service.register({ email: 'test@example.com' })
// 断言
expect(mockDb.users.create).toHaveBeenCalled()
expect(mockEmailer.sendWelcome).toHaveBeenCalledWith('test@example.com')
})
})
// 第 4 步:添加错误场景(error-testing.md)
it('因无效电子邮件而抛出 ValidationError', async () => {
const service = new UserService(mockDb, mockEmailer)
await expect(service.register({ email: 'invalid' }))
.rejects.toThrow(ValidationError)
})
示例 2:代理重构代码
// 代理收到:"使此代码可测试"
// 第 1 步:确定问题(testability-patterns.md)
// → 混合逻辑和副作用
// 第 2 步:应用模式 1:提取纯函数
// 之前:
class OrderService {
async processOrder(order) {
let total = 0
for (const item of order.items) {
total += item.price * item.quantity
}
await this.db.save({ ...order, total })
}
}
// 之后:
export function calculateOrderTotal(order) {
return order.items.reduce((sum, item) => sum + item.price * item.quantity, 0)
}
class OrderService {
async processOrder(order) {
const total = calculateOrderTotal(order)
await this.db.save({ ...order, total })
}
}
// 第 3 步:编写测试(black-box-testing.md)
describe('calculateOrderTotal', () => {
it.each([
[{ items: [{ price: 10, quantity: 2 }] }, 20],
[{ items: [{ price: 15, quantity: 3 }] }, 45],
])('计算 %o 为 %d', (order, expected) => {
expect(calculateOrderTotal(order)).toBe(expected)
})
})
🔗 外部资源
- Vitest 文档 - 官方文档
- Testing Library - React/DOM 测试
- MSW - API 模拟
- @faker-js/faker - 测试数据生成
📋 代理清单
生成测试时,请确保:
- [ ] 测试遵循 F.I.R.S.T 原则
- [ ] 测试使用 AAA 结构
- [ ] 测试使用 黑盒方法
- [ ] 外部依赖被 模拟
- [ ] 错误场景 被覆盖
- [ ] 异步操作 被正确处理
- [ ] 测试快速(< 100ms),隔离,可重复
🎯 常见代理任务
任务:生成单元测试
- 阅读 index.md → 确定测试类型
- 应用 first-principles.md → F.I.R.S.T
- 使用 aaa-pattern.md 结构
- 使用 test-doubles.md 模拟
- 参考 cheatsheet.md 语法
任务:生成组件测试
- 阅读 component-testing.md
- 使用 Testing Library 查询
- 测试用户交互
- 处理 异步操作
- 覆盖 错误状态
任务:为可测试性重构
- 阅读 testability-patterns.md
- 确定模式(提取,注入,包装)
- 应用重构
- 为重构后的代码生成测试
任务:审查测试质量
- 检查 F.I.R.S.T 合规性
- 验证 AAA 结构
- 确保 黑盒方法
- 验证 模拟使用
- 检查 错误覆盖
📖 技能元数据
版本: 1.0.0 类型: 测试指导 框架: Vitest 语言: TypeScript/JavaScript 集成: typescript-coder 代理,architecture-patterns 技能 状态: 生产就绪(核心文件完成)
文件: 20+ markdown 文档 类别: 原则(3),策略(2),模式(7),重构(1),快速参考(2)
💡 快速决策树
“我应该写什么测试?”
这是一个新功能吗?
└─ 是 → 单元测试(黑盒) + [index.md](index.md#new-feature)
这是一个bug修复吗?
└─ 是 → 回归测试 + [index.md](index.md#bug-fix)
这是异步代码吗?
└─ 是 → [async-testing.md](patterns/async-testing.md)
这是一个React组件吗?
└─ 是 → [component-testing.md](patterns/component-testing.md)
这是一个API客户端吗?
└─ 是 → [api-testing.md](patterns/api-testing.md)
这是复杂逻辑吗?
└─ 是 → 提取纯函数 + 黑盒测试
“我如何使这个测试可测试?”
混合逻辑和副作用吗?
└─ [testability-patterns.md](refactoring/testability-patterns.md#pattern-1)
硬编码依赖吗?
└─ [testability-patterns.md](refactoring/testability-patterns.md#pattern-2)
复杂的私有方法吗?
└─ [testability-patterns.md](refactoring/testability-patterns.md#pattern-3)
时间依赖的代码吗?
└─ [testability-patterns.md](refactoring/testability-patterns.md#pattern-5)
这是AI代理的主参考。对于人类友好的导航,请参阅 README.md。