关于 tdd-workflow
一项为开发任务提供测试驱动开发流程的技能,适用于新功能实现、回归测试和缺陷修复。它将工作拆分为 RED、GREEN、REFACTOR 和提交阶段,并规定逐次验证测试。
主要功能
- 01按 RED-GREEN-REFACTOR 循环工作
- 02每次只编写一个失败测试
- 03以最少实现通过测试
- 04每次改动后运行测试
- 05每轮重构后提交代码
适用场景
- 01以测试优先实现新功能
- 02先编写回归测试再修复缺陷
- 03为现有代码补充特征测试后重构
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ hieutrtr/ ai1-skills --skill tdd-workflow安装后在 Claude Code 中输入/tdd-workflow确认已加载。
详细介绍
TDD 工作流
适用场景
在以下情况启用此技能:
- 用户明确要求使用 TDD、测试优先或红-绿-重构
- 实现新函数、方法、端点或组件,且测试优先很有价值
- 修复 Bug,且应先编写回归测试
- 用户说“先写测试”“用 TDD 实现”或“红-绿-重构”
以下情况不要使用此技能:
- 配置文件、环境设置或静态内容
- 单行修复或琐碎更改
- 探索性原型或概念验证代码
- 无法进行有意义的独立测试的代码
- 测试模式的细节(如何编写测试,请使用
pytest-patterns或react-testing-patterns)
说明
TDD 循环
┌─────────────────────────────────────────────────────┐
│ │
│ ┌─────┐ ┌───────┐ ┌──────────┐ │
│ │ RED │ ──→ │ GREEN │ ──→ │ REFACTOR │ ──→ ... │
│ └─────┘ └───────┘ └──────────┘ │
│ │
│ Write ONE Write MINIMUM Clean up code │
│ failing code to make while ALL tests │
│ test it pass stay GREEN │
│ │
└─────────────────────────────────────────────────────┘
阶段 1:RED — 编写失败的测试
- 只编写一个测试,描述预期行为
- 测试必须具体:测试一种行为,而非多种行为
- 运行测试套件,确认新测试失败
- 失败消息应明确说明缺少什么
后端(pytest):
pytest tests/unit/test_user_service.py::test_create_user_returns_user -x
# Expected: FAILED (function/class does not exist yet)
前端(Vitest):
npx vitest run src/hooks/useAuth.test.ts --reporter=verbose
# Expected: FAILED (hook/component does not exist yet)
RED 阶段规则:
- 编写能够表达需求的最简单测试
- 测试应因正确的原因失败(缺少实现,而非语法错误)
- 一次不要编写多个失败的测试
- 从代码将要存放的位置导入(即使代码尚不存在)
阶段 2:GREEN — 让测试通过
- 编写让失败测试通过所需的最少代码
- 不要添加额外功能、错误处理或边界情况
- 可以对值进行硬编码,或使用简单实现
- 运行测试套件,确认所有测试都通过(而非仅新测试)
# Backend
pytest tests/unit/test_user_service.py -x
# Frontend
npx vitest run src/hooks/useAuth.test.ts
GREEN 阶段规则:
- 最少代码就是最少代码——如果常量就能满足测试,就使用常量
- 不要添加任何测试未要求的代码
- 此阶段不要重构
- 此阶段不要编写额外测试
- 如果测试通过,就进入 REFACTOR 阶段
阶段 3:REFACTOR — 清理代码
- 提高代码质量,同时确保所有测试仍然通过
- 消除重复(DRY)
- 改进命名和可读性
- 按需提取函数或类
- 每次更改后都运行测试——必须确保测试始终通过
# After each refactoring change
pytest tests/ -x # Must pass
npx vitest run # Must pass
REFACTOR 阶段规则:
- 每次更改都必须确保测试通过
- 同时重构生产代码和测试代码
- 不要添加新功能(这需要开启新的 RED 阶段)
- 如果测试失败,立即撤销重构
阶段 4:COMMIT
REFACTOR 阶段成功后:
- 暂存所有更改(测试 + 实现)
- 使用描述性消息提交
- 返回阶段 1(RED),开始实现下一个行为
严格的 TDD 规则
此技能启用时,以下规则不可妥协:
- 绝不在没有先编写失败测试的情况下编写生产代码
- 绝不一次编写多个失败的测试
- 绝不添加任何测试未要求的功能
- 始终在每次更改后运行测试
- 始终在每个成功的 GREEN-REFACTOR 循环后提交
- 始终保持 RED-GREEN-REFACTOR 循环简短(以分钟计,而非小时)
后端 TDD 流程(pytest)
1. Write test: tests/unit/test_user_service.py::test_create_user_returns_user
2. Run: pytest tests/unit/test_user_service.py::test_create_user_returns_user -x
3. See: FAILED - ImportError or AssertionError
4. Implement: app/services/user_service.py (minimum code)
5. Run: pytest tests/unit/test_user_service.py -x
6. See: PASSED
7. Refactor: Clean up, run tests again
8. Commit: "Add UserService.create_user"
9. Next test: test_create_user_rejects_duplicate_email
前端 TDD 流程(Testing Library)
1. Write test: src/components/UserCard.test.tsx::renders user name
2. Run: npx vitest run src/components/UserCard.test.tsx
3. See: FAILED - module not found
4. Implement: src/components/UserCard.tsx (minimum code)
5. Run: npx vitest run src/components/UserCard.test.tsx
6. See: PASSED
7. Refactor: Clean up, run tests again
8. Commit: "Add UserCard component"
9. Next test: calls onEdit when button clicked
Bug 修复 TDD 流程
修复 Bug 时,始终先编写一个能复现该 Bug 的失败测试:
1. Reproduce: Understand the bug and its trigger condition
2. Write test: Test that exercises the exact scenario that causes the bug
3. Run: Confirm FAILED (the test reproduces the bug)
4. Fix: Implement the minimum fix
5. Run: Confirm PASSED (bug is fixed)
6. Refactor: Clean up if needed
7. Commit: "Fix: [describe the bug]"
这样可以确保 Bug 不会再次出现——测试会将其捕获。
示例
TDD:UserService.create_user(3 个循环)
循环 1 — RED: 测试 create_user 是否返回用户
async def test_create_user_returns_user(db_session):
service = UserService(db_session)
user = await service.create_user(UserCreate(email="[email protected]", password="12345678", display_name="A"))
assert user.email == "[email protected]"
assert user.id is not None
GREEN: 使用基本逻辑实现 UserService.create_user。
REFACTOR: 提取密码哈希处理。提交。
循环 2 — RED: 测试重复邮箱是否会引发错误
async def test_create_user_rejects_duplicate_email(db_session):
service = UserService(db_session)
await service.create_user(UserCreate(email="[email protected]", password="12345678", display_name="A"))
with pytest.raises(ConflictError):
await service.create_user(UserCreate(email="[email protected]", password="87654321", display_name="B"))
GREEN: 在插入前添加重复项检查。 REFACTOR: 清理代码。提交。
循环 3 — RED: 测试密码是否经过哈希处理
async def test_create_user_hashes_password(db_session):
service = UserService(db_session)
user = await service.create_user(UserCreate(email="[email protected]", password="12345678", display_name="A"))
assert user.hashed_password != "12345678"
assert verify_password("12345678", user.hashed_password)
GREEN: 如果在循环 1 的重构后测试已经通过,那么这只是验证,而非 RED。请改为编写一个测试新行为的测试。
边缘情况
-
何时跳过 TDD: 配置文件(
.env、tsconfig.json)、静态内容、自动生成的代码(Alembic 迁移)、一次性脚本和探索性原型。 -
使用外部依赖进行 TDD: 在边界处进行模拟。如果要测试调用外部 API 的服务,请模拟 API 客户端,而不是 HTTP 库。测试服务的行为,而不是模拟对象。
-
大型功能: 将功能拆分为小型、可测试的行为。每个行为都执行自己的 RED-GREEN-REFACTOR 循环。所有循环共同实现完整功能。
-
重构没有测试的现有代码: 首先为现有行为编写测试(特征测试)。然后在这些测试的安全保障下进行重构。这不属于严格的 TDD,但属于有效的测试优先思维方式。
-
结合模式技能: 此技能定义工作流(何时编写测试、何时编写代码)。使用
pytest-patterns或react-testing-patterns了解模式(如何组织测试、使用哪些断言)。