Agent Skills: Test-Driven Development

Use this skill when writing new features, fixing bugs, or adding test coverage. Enforces Red-Green-Refactor — write the test first, then the code. Trigger on "add tests", "write tests first", "TDD", "test this feature", "fix this bug" (reproduce with a failing test first), or when starting any new implementation. Prevents testing anti-patterns like over-mocking, test-per-method, and tests that pass but verify nothing.

UncategorizedID: carvalab/k-skills/test-driven-development

Install this agent skill to your local

pnpm dlx add-skill https://github.com/carvalab/k-skills/tree/HEAD/skills/test-driven-development

Skill Files

Browse the full folder contents for test-driven-development.

Download Skill

Loading file tree…

skills/test-driven-development/SKILL.md

Skill Metadata

Name
test-driven-development
Description
Use this skill when writing new features, fixing bugs, or adding test coverage. Enforces Red-Green-Refactor — write the test first, then the code. Trigger on "add tests", "write tests first", "TDD", "test this feature", "fix this bug" (reproduce with a failing test first), or when starting any new implementation. Prevents testing anti-patterns like over-mocking, test-per-method, and tests that pass but verify nothing.

Test-Driven Development

Write tests before code. The test is the specification. If you can't write a test, you don't understand the requirement.

Related Skills:

  • kavak-documentation - Query for Kavak-specific testing patterns, kbroker event testing, STS mocking
  • Use kavak-platform/platform_docs_search MCP tool for testing best practices at Kavak

Quick Start

# 1. Write failing test first
# 2. Run to see it fail (RED)
# 3. Write minimal code to pass (GREEN)
# 4. Refactor while tests pass (REFACTOR)
# 5. Repeat

Test commands by language: | Language | Run Tests | Watch Mode | |----------|-----------|------------| | Go | go test ./... | go test ./... -v | | Node/TS | npm test | npm test -- --watch | | Python | pytest | pytest-watch | | Java | ./mvnw test | ./mvnw test -Dtest=* |

The Red-Green-Refactor Cycle

1. RED: Write Failing Test

- Write ONE test for the next piece of behavior
- Test must fail for the RIGHT reason
- Use descriptive names: should_calculate_total_with_tax
- Follow Arrange-Act-Assert structure

2. GREEN: Make It Pass

- Write MINIMAL code to pass the test
- Don't optimize, don't refactor, don't add features
- "Fake it till you make it" is valid
- The goal is GREEN, not perfect

3. REFACTOR: Improve Design

- Clean up code while tests stay green
- Remove duplication
- Improve names
- Extract methods/functions
- Run tests after EVERY change

Common Rationalizations (Resist Them)

| Rationalization | Counter | |-----------------|---------| | "Let me just write one more method" | Stop. Test what exists first | | "I'll add tests after" | You won't. Tests written after verify nothing | | "It's too simple to test" | Simple now, complex later. Test it | | "I'll refactor tests later" | Refactor production code, not test structure | | "This is just scaffolding" | Scaffolding becomes foundation. Test it |

Anti-Patterns (What NOT to Do)

| Anti-Pattern | Problem | Fix | |--------------|---------|-----| | The Liar | Test passes but tests nothing | Assert actual behavior | | The Mockery | Over-mocking hides real bugs | Mock boundaries only | | Excessive Setup | 50 lines setup, 2 lines test | Simplify SUT or use builders | | The Slow Poke | Tests take minutes | Isolate, mock I/O | | The Local Hero | Passes locally, fails in CI | No env dependencies | | Test-per-Method | 1:1 test-to-method | Test behaviors, not methods |

Verification Checklist

Before committing, verify your tests:

[ ] Test fails when behavior is removed?
[ ] Test name describes the behavior?
[ ] Arrange-Act-Assert structure clear?
[ ] No test-only code in production?
[ ] Mocks verify behavior, not implementation?
[ ] Edge cases covered?

When TDD Is Mandatory

  • New features (write test first)
  • Bug fixes (write failing test that reproduces bug)
  • Refactoring (tests protect behavior)
  • API changes (contract tests first)

When to Adapt TDD

  • Exploratory/spike work (delete code after, then TDD)
  • UI prototyping (test logic, not layout)
  • Legacy code (add tests before changing)

Test Naming Convention

should_[expected_behavior]_when_[condition]

Examples:
- should_return_zero_when_cart_is_empty
- should_throw_error_when_user_not_found
- should_apply_discount_when_coupon_valid

References

| Reference | Purpose | |-----------|---------| | references/red-green-refactor.md | Detailed cycle walkthrough | | references/anti-patterns.md | Full anti-pattern catalog | | references/examples-go.md | Go TDD examples | | references/examples-node.md | Node/TypeScript TDD examples | | references/examples-python.md | Python TDD examples | | references/examples-java.md | Java TDD examples | | references/verification-checklist.md | Pre-commit verification | | references/testing-boundaries.md | What to mock, what not to mock |

Best Practices

  1. One assertion per test - Multiple assertions hide failures
  2. Test behavior, not implementation - Tests survive refactoring
  3. Isolated tests - No shared state between tests
  4. Fast tests - Under 100ms per unit test
  5. Deterministic - Same result every run
  6. Self-documenting - Test name = specification

Principle: If you can't write a test for it, you don't understand what it should do. The test IS the specification.