with one click
test-driven-development
TDD: enforce RED-GREEN-REFACTOR, tests before code.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
TDD: enforce RED-GREEN-REFACTOR, tests before code.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating browser actions.
Reviews and removes unsupported, non-idiomatic code and UI/design changes introduced on a branch. Use when implementing or reviewing a feature or fix before handoff.
Design principles for REST and GraphQL APIs in 2025. Enforces OpenAPI-first, versioning strategies, and standardized error responses.
Use the `fm` CLI (Apple Foundation Models) for on-device and Private Cloud Compute LLM inference on macOS. Use when the user wants to prompt, chat, serve, or count tokens with Apple's built-in foundation models. Also use for structured output generation (`fm schema`), checking model availability (`fm available`), or checking quota usage (`fm quota-usage`). Trigger on phrases like 'run fm', 'Apple Foundation Model', 'on-device LLM', 'Apple AI', 'fm respond', 'fm chat', 'fm serve', 'fm token-count', 'fm schema', or any task involving Apple's local AI models.
This skill should be used when the user asks to "trigger a build", "check build status", "watch a build", "view build logs", "retry a build", "cancel a build", "list builds", "download artifacts", "upload artifacts", "manage secrets", "create a pipeline", "list pipelines", or "interact with Buildkite from the command line". Also use when the user mentions bk commands, bk build, bk job, bk pipeline, bk secret, bk artifact, bk cluster, bk package, bk auth, bk configure, bk use, bk init, bk api, or asks about Buildkite CLI installation, terminal-based Buildkite workflows, or command-line CI/CD operations.
Buildkite CI/CD pipeline setup, migration, validation, hardening, and live pipeline management. Use when Codex needs to create, review, debug, or update Buildkite pipelines, .buildkite/pipeline.yml files, steps, queues, triggers, artifacts, annotations, secrets, OIDC, or deployment stages.
| name | test-driven-development |
| description | TDD: enforce RED-GREEN-REFACTOR, tests before code. |
| version | 1.2.0 |
| author | Adapted from Hermes Agent (obra/superpowers) |
| license | MIT |
| tags | ["testing","tdd","development","quality","red-green-refactor"] |
Write the test first. Watch it fail. Write minimal code to pass.
Core principle: If you didn't watch the test fail, you don't know if it tests the right thing.
Violating the letter of the rules is violating the spirit of the rules.
Always:
Exceptions (ask first):
Thinking "skip TDD just this once"? Stop. That's rationalization.
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
Write code before the test? Delete it. Start over.
No exceptions:
Implement fresh from tests. Period.
Write one minimal test showing what should happen.
Good test:
def test_retries_failed_operations_3_times():
attempts = 0
def operation():
nonlocal attempts
attempts += 1
if attempts < 3:
raise Exception('fail')
return 'success'
result = retry_operation(operation)
assert result == 'success'
assert attempts == 3
Clear name, tests real behavior, one thing.
Bad test:
def test_retry_works():
mock = MagicMock()
mock.side_effect = [Exception(), Exception(), 'success']
result = retry_operation(mock)
assert result == 'success' # What about retry count? Timing?
Vague name, tests mock not real code.
Requirements:
MANDATORY. Never skip.
# Run the specific test
pytest tests/test_feature.py::test_specific_behavior -v
Confirm:
Test passes immediately? You're testing existing behavior. Fix the test.
Test errors? Fix the error, re-run until it fails correctly.
Write the simplest code to pass the test. Nothing more.
Good:
def add(a, b):
return a + b # Nothing extra
Bad:
def add(a, b):
result = a + b
logging.info(f"Adding {a} + {b} = {result}") # Extra!
return result
Don't add features, refactor other code, or "improve" beyond the test.
Cheating is OK in GREEN:
We'll fix it in REFACTOR.
MANDATORY.
# Run the specific test
pytest tests/test_feature.py::test_specific_behavior -v
# Then run ALL tests to check for regressions
pytest tests/ -q
Confirm:
Test fails? Fix the code, not the test.
Other tests fail? Fix regressions now.
After green only:
Keep tests green throughout. Don't add behavior.
If tests fail during refactor: Undo immediately. Take smaller steps.
Next failing test for next behavior. One cycle at a time.
"I'll write tests after to verify it works"
Tests written after code pass immediately. Passing immediately proves nothing:
Test-first forces you to see the test fail, proving it actually tests something.
"I already manually tested all the edge cases"
Manual testing is ad-hoc. You think you tested everything but:
Automated tests are systematic. They run the same way every time.
"Deleting X hours of work is wasteful"
Sunk cost fallacy. The time is already gone. Your choice now:
The "waste" is keeping code you can't trust.
"TDD is dogmatic, being pragmatic means adapting"
TDD IS pragmatic:
"Pragmatic" shortcuts = debugging in production = slower.
"Tests after achieve the same goals — it's spirit not ritual"
No. Tests-after answer "What does this do?" Tests-first answer "What should this do?"
Tests-after are biased by your implementation. You test what you built, not what's required. Tests-first force edge case discovery before implementing.
| Excuse | Reality |
|---|---|
| "Too simple to test" | Simple code breaks. Test takes 30 seconds. |
| "I'll test after" | Tests passing immediately prove nothing. |
| "Tests after achieve same goals" | Tests-after = "what does this do?" Tests-first = "what should this do?" |
| "Already manually tested" | Ad-hoc ≠ systematic. No record, can't re-run. |
| "Deleting X hours is wasteful" | Sunk cost fallacy. Keeping unverified code is technical debt. |
| "Keep as reference, write tests first" | You'll adapt it. That's testing after. Delete means delete. |
| "Need to explore first" | Fine. Throw away exploration, start with TDD. |
| "Test hard = design unclear" | Listen to the test. Hard to test = hard to use. |
| "TDD will slow me down" | TDD faster than debugging. Pragmatic = test-first. |
| "Manual test faster" | Manual doesn't prove edge cases. You'll re-test every change. |
| "Existing code has no tests" | You're improving it. Add tests for the code you touch. |
If you catch yourself doing any of these, delete the code and restart with TDD:
All of these mean: Delete code. Start over with TDD.
Before marking work complete:
Can't check all boxes? You skipped TDD. Start over.
| Problem | Solution |
|---|---|
| Don't know how to test | Write the wished-for API. Write the assertion first. Ask. |
| Test too complicated | Design too complicated. Simplify the interface. |
| Must mock everything | Code too coupled. Use dependency injection. |
| Test setup huge | Extract helpers. Still complex? Simplify the design. |
Use the project's canonical test runner whenever possible:
# RED — verify failure
pytest tests/test_feature.py::test_name -v
# If the project has a runner script, use it:
scripts/run_tests.sh tests/test_feature.py::test_name
# GREEN — verify pass
pytest tests/test_feature.py::test_name -v
# Full suite — verify no regressions
pytest tests/ -q
If the first RED attempt fails because pytest isn't installed, install it or use the project's venv/runner. Don't count a missing-dependency error as valid RED evidence — you need the test itself to fail because the feature is missing.
When implementing a small prototype with no test framework installed:
pytest is unavailable, use unittest rather than installing a new dependency just to validate a tiny deliverable.unittest discovery, make tests/ importable (tests/__init__.py) and use: python3 -m unittest discover -s tests -p 'test_*.py' -v.venv, .pytest_cache, __pycache__) if not part of the deliverable.Production code → test exists and failed first
Otherwise → not TDD
No exceptions without explicit permission.