一键导入
test-driven-development
Use when implementing features or fixing bugs - enforces RED-GREEN-REFACTOR cycle requiring tests to fail before writing code
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when implementing features or fixing bugs - enforces RED-GREEN-REFACTOR cycle requiring tests to fail before writing code
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when shaping a feature before implementation - turns rough ideas into an approved markdown spec and local task directory
Use to execute an approved local markdown task directory iteratively - work the current Now slice, update docs, then stop
Use when implementation is complete and verified - delete finished local task docs, present integration options, and clean up safely
Use for advanced markdown task-doc operations - split work, reprioritize slices, delete finished local task dirs, and keep docs clean
Use after executing a task directory - verifies implementation against plan.md, acceptance checks, and anti-goals
Use when starting any conversation - establishes skill selection and the local task-doc workflow
| name | test-driven-development |
| description | Use when implementing features or fixing bugs - enforces RED-GREEN-REFACTOR cycle requiring tests to fail before writing code |
<skill_overview> Write the test first, watch it fail, write minimal code to pass. If you didn't watch the test fail, you don't know if it tests the right thing. </skill_overview>
<rigidity_level> LOW FREEDOM - Follow these exact steps in order. Do not adapt.
Violating the letter of the rules is violating the spirit of the rules. </rigidity_level>
<quick_reference>
| Phase | Action | Command Example | Expected Result |
|---|---|---|---|
| RED | Write failing test | cargo test test_name | FAIL (feature missing) |
| Verify RED | Confirm correct failure | Check error message | "function not found" or assertion fails |
| GREEN | Write minimal code | Implement feature | Test passes |
| Verify GREEN | All tests pass | cargo test | All green, no warnings |
| REFACTOR | Clean up code | Improve while green | Tests still pass |
Iron Law: NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
</quick_reference>
<when_to_use> Always use for:
Ask your human partner for exceptions:
Thinking "skip TDD just this once"? Stop. That's rationalization. </when_to_use>
<the_process>
Write one minimal test showing what should happen.
Requirements:
See resources/language-examples.md for Rust, Swift, TypeScript examples.
MANDATORY. Never skip.
Run the test and confirm:
If test passes: You're testing existing behavior. Fix the test. If test errors: Fix syntax error, re-run until it fails correctly.
Write simplest code to pass the test. Nothing more.
Key principle: Don't add features the test doesn't require. Don't refactor other code. Don't "improve" beyond the test.
MANDATORY.
Run tests and confirm:
If test fails: Fix code, not test. If other tests fail: Fix now before proceeding.
Only after green:
Keep tests green. Don't add behavior.
Next failing test for next feature.
</the_process>
Developer writes implementation first, then adds test that passes immediately
// Code written FIRST
def validate_email(email):
return "@" in email # Bug: accepts "@@"
// Test written AFTER
def test_validate_email():
assert validate_email("user@example.com") # Passes immediately!
// Missing edge case: assert not validate_email("@@")
<why_it_fails> When test passes immediately:
Tests written after verify remembered cases, not required behavior. </why_it_fails>
**TDD approach:**def test_validate_email():
assert validate_email("user@example.com") # Will fail - function doesn't exist
assert not validate_email("@@") # Edge case up front
NameError: function 'validate_email' is not defined
def validate_email(email):
return "@" in email and email.count("@") == 1
Result: Test failed first, proving it works. Edge case discovered during test writing, not in production.
Developer has already written 3 hours of code without tests. Wants to keep it as "reference" while writing tests.
// 200 lines of untested code exists
// Developer thinks: "I'll keep this and write tests that match it"
// Or: "I'll use it as reference to speed up TDD"
<why_it_fails> Keeping code as "reference":
Result: All the problems of test-after, none of the benefits of TDD. </why_it_fails>
**Delete it. Completely.**git stash # Or delete the file
Then start TDD:
Why delete:
What you gain:
// Test attempt:
func testUserServiceCreatesAccount() {
// Need to mock database, email service, payment gateway, logger...
// This is getting complicated, maybe I should just implement first
}
<why_it_fails> "Test is hard" is valuable signal:
Implementing first ignores this signal:
Hard to test? Simplify the interface:
// Instead of:
class UserService {
init(db: Database, email: EmailService, payments: PaymentGateway, logger: Logger) { }
func createAccount(email: String, password: String, paymentToken: String) throws { }
}
// Make testable:
class UserService {
func createAccount(request: CreateAccountRequest) -> Result<Account, Error> {
// Dependencies injected through request or passed separately
}
}
Test becomes simple:
func testCreatesAccountFromRequest() {
let service = UserService()
let request = CreateAccountRequest(email: "user@example.com")
let result = service.createAccount(request: request)
XCTAssertEqual(result.email, "user@example.com")
}
TDD forces good design. If test is hard, fix design before implementing.
<critical_rules>
Write code before test? → Delete it. Start over.
Test passes immediately? → Not TDD. Fix the test or delete the code.
Can't explain why test failed? → Fix until failure makes sense.
Want to skip "just this once"? → That's rationalization. Stop.
All of these mean: Stop, follow TDD:
</critical_rules>
<verification_checklist>
Before marking work complete:
Can't check all boxes? You skipped TDD. Start over.
</verification_checklist>
This skill calls:
This skill is called by:
Agents used:
Detailed language-specific examples:
When stuck: