一键导入
flow-code-tdd
Use when implementing with test-first methodology in Worker Phase 4, fixing bugs with Prove-It Pattern, or establishing test coverage strategy.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when implementing with test-first methodology in Worker Phase 4, fixing bugs with Prove-It Pattern, or establishing test coverage strategy.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Internal pipeline engine. Manages the entire pipeline (brainstorm, plan, plan-review, work, impl-review, close) via flowctl phase commands. Invoked by /flow-code:go.
Use when exploring requirements before planning. Pressure-tests ideas, generates approaches, and outputs a requirements doc for /flow-code:plan. Supports --auto mode for AI self-interview (no human input needed).
Use when exploring requirements before planning. Pressure-tests ideas, generates approaches, and outputs a requirements doc for /flow-code:plan.
Use when planning features or designing implementation. Triggers on /flow-code:plan with text descriptions or Flow IDs.
Use when reviewing code changes — self-review in Worker Phase 6, impl-review, or PR review. Applies five-axis scoring with severity labels.
Use when implementing a plan or working through a spec. Triggers on /flow-code:work with Flow IDs.
| name | flow-code-tdd |
| description | Use when implementing with test-first methodology in Worker Phase 4, fixing bugs with Prove-It Pattern, or establishing test coverage strategy. |
| tier | 2 |
| user-invocable | false |
Write the test first, watch it fail, make it pass, then clean up. TDD is not about testing — it's about design. Tests written first produce better APIs, clearer boundaries, and fewer bugs. The Prove-It Pattern extends TDD to bug fixes.
--tdd flag is set)When NOT to use:
┌───────┐ ┌───────┐ ┌──────────┐
│ RED │───>│ GREEN │───>│ REFACTOR │──┐
│ Write │ │ Make │ │ Clean up │ │
│ test │ │ pass │ │ code │ │
└───────┘ └───────┘ └──────────┘ │
^ │
└──────── next behavior ────────────┘
test_user_with_expired_token_gets_401test('rejects login with invalid email format', () => {
const result = validateLogin({ email: 'not-an-email', password: 'valid123' });
expect(result.success).toBe(false);
expect(result.errors).toContain('Invalid email format');
});
For every bug fix, PROVE the bug exists before fixing it:
1. Write a test that demonstrates the bug
2. Run it — confirm it FAILS (proves the bug exists)
3. Fix the code
4. Run it — confirm it PASSES (proves the fix works)
5. Commit test + fix together (regression guard)
Why this matters: Without Step 1-2, you might fix the wrong thing or "fix" something that wasn't broken. The test becomes a permanent regression guard.
// Step 1: Write the bug-proving test
test('handles negative quantities without crashing', () => {
// This was crashing in production (ticket #123)
expect(() => calculateTotal({ quantity: -1, price: 10 })).not.toThrow();
expect(calculateTotal({ quantity: -1, price: 10 })).toBe(0);
});
// Step 2: Run — should fail (proves the bug)
// Step 3: Fix calculateTotal to handle negative quantities
// Step 4: Run — should pass (proves the fix)
/ E2E \ ~5% Slow, fragile, high confidence
/─────────\
/ Integration\ ~15% Real dependencies, medium speed
/──────────────\
/ Unit \ ~80% Fast, isolated, focused
/──────────────────\
| Level | Scope | Speed | Dependencies | When to Write |
|---|---|---|---|---|
| Unit | Single function/class | <10ms | None (mocks OK) | Every behavior |
| Integration | Module boundaries | <1s | Real DB/API | Boundary interactions |
| E2E | User journey | <30s | Full system | Critical paths only |
// Good: tests behavior
test('expired token returns unauthorized', () => {
const token = createToken({ expiresAt: pastDate });
const result = validateToken(token);
expect(result.valid).toBe(false);
expect(result.reason).toBe('expired');
});
// Bad: tests implementation
test('calls jwt.verify with correct args', () => {
validateToken(token);
expect(jwt.verify).toHaveBeenCalledWith(token, SECRET);
});
PREFER real implementations (fast, accurate)
USE fakes for slow external services (payment APIs, email)
USE stubs for non-deterministic behavior (time, random)
AVOID mocking internal modules (couples test to implementation)
Tests should be Descriptive And Meaningful Phrases — readability beats reuse:
// Good: DAMP — each test is self-contained and readable
test('admin can delete any post', () => {
const admin = createUser({ role: 'admin' });
const post = createPost({ author: createUser() });
expect(deletePost(admin, post.id)).resolves.toBe(true);
});
test('regular user cannot delete others posts', () => {
const user = createUser({ role: 'user' });
const post = createPost({ author: createUser() });
expect(deletePost(user, post.id)).rejects.toThrow('Forbidden');
});
// Bad: DRY — shared setup obscures test intent
let admin, user, post;
beforeEach(() => { admin = createUser({role:'admin'}); /* ... */ });
| Rationalization | Reality |
|---|---|
| "I'll add tests later" | Later never comes. Tests written after code test what you built, not what you should have built. |
| "This is too simple to test" | Simple code is the easiest to test. Start the habit. |
| "Tests slow me down" | Tests save 10x debugging time. The slowdown is an investment. |
| "Mocks are necessary for unit tests" | Most code can be tested with real implementations. Mocks test your assumptions, not your code. |
| "100% coverage is the goal" | Coverage measures lines executed, not correctness. Focus on behavior coverage. |
After TDD cycle:
See also: Testing Patterns for AAA, factories, anti-patterns, and framework commands.