Direct answer
The Skill enforces the correct order of Test-Driven Development by blocking code generation until a test fails, thereby ensuring that tests drive design and implementation is written after verification. This approach prevents "test theatre" where tests seem rigorous but don't test significant functionality, and instead promotes immediate live coverage of endpoints with naturally increasing coverage over time.
Test-Driven Development written in autonomy by a LLM is suspicious:
the output seems TDD but in reality is "write code, then write tests around
it". The skill tdd-guide Superpowers solves exactly this:
forcing the correct order (test before implementation)
by blocking code generation until there is a test that fails.
Independence Disclaimer: I am not affiliated with Obra nor with Anthropic. I use tdd-guide About a year ago on the entire
new business logic in my portfolio. In areas where skill doesn't make sense (UI, glue code) I explicitly disable them in CLAUDE.md project.
The problem with TDD generated by LLM "on instinct"
Without skill, a typical session produces:
- Write a function that does X
- Template writes the implementation.
- Now write the tests.
- Template writes tests that They are alreadyBecause they observe the existing implementation.
Result: test that documents the current behavior of the code, not that They drive Design. Coverage grows, confidence does not increase. If the implementation was wrong, the tests are also wrong for symmetry. This is the most common way to write "TDD" that is not TDD.
The Skill tdd-guide Imposes correct order: The test exists and fails before implementation is writtenThe verification process occurs by actually running the test (not simulating).
The RED-GREEN-REFACTOR cycle applied
Every feature goes through a cycle (or more, for edge cases):
- RedWrite the test that describes the expected behavior. Run it. It should fail (because there is no implementation or its logic is wrong). If it passes, it's not a valid test - it's just observing existing working code.
- GreenWrite the minimum Code that passes the test. Resist the temptation of "writing what will be needed tomorrow". Only write what is required today.
- REFACTORWith the tests that run like a network security, reorganize the code. Extract functions, simplify names, and duplicate. Re-run the tests after every modification.
The Skill tdd-guide formalize this loop as three gates
explicit. Each gate must be overcome before proceeding to the next one.
No "GREEN without RED first"; no "REFACTOR without GREEN stable".
Example illustration: IBAN validator for the dev-tool
On my portfolio I have a dev-tool generator IBAN for over 50 countries. When I added the validation MOD-97 (ISO 7064), I used tdd-guide. Session summary (summary, not literal transcript):
RED 1 (happy path)
Test: validateIban("IT60 X054 2811 1010 0000 0123 456") -> true
Esecuzione: fallisce (funzione non esiste)
Esecuzione dopo creazione signature: fallisce (return false default)
GREEN 1
Implementazione minima: parse + MOD-97 check
Test passa
RED 2 (edge case: spazi multipli)
Test: validateIban("IT60 X054 2811...") -> true (gestione spazi)
Esecuzione: fallisce (regex strict)
GREEN 2
Aggiunta normalize-whitespace prima della validation
Entrambi i test passano
RED 3 (edge case: lowercase)
Test: validateIban("it60 x054...") -> true (case-insensitive)
Esecuzione: fallisce (case-sensitive lookup table country)
GREEN 3
toUpperCase() su country code + intero IBAN
Tutti i test passano
REFACTOR
Estrai normalizeIban() come helper privato
Estrai countryCheckDigitTable come const top-of-file
Re-esegui suite: green
Result: a function of ~40 lines + 12 tests. Coverage 100% on the function. Final refactor extracted two reusable helpers.
When the skill does not pay off
tdd-guide It has an overhead. Three cases where it is better not to invoke it:
- Pure UIComponents of Angular/React that render data without internal logic. Snapshot tests or visual regression tests are sufficient; structured TDD is overkill.
- Glue code Note: I've kept the original formatting and punctuation of the Italian text, as well as the proper nouns and HTML tags verbatim, to ensure an accurate translation while preserving their context.code that organizes what you call libraries existing (e.g. fetch + format + display). The value of the test is low compared to the cost of writing it.
- Simple CRUD operationsRepository with find/save/delete methods assigned to an ORM. Tests integrate the integration (real DB), unit tests on abstraction are redundant.
On my portfolio I use a specific rule in the CLAUDE.md project file: "TDD for business logic (tax calculators, validations, transformations). Standard execute for UI, glue, CRUD." The skill is invoked automatically only for patterns of the first group.
Anti-pattern: "test theatre"
The test theater is when you write tests that They seem Rigorous but they do not test anything significant. Typical patterns:
-
Test that test the implementationInstead of verifying observable behavior, they verify the invocation of a specific method. "Expectation:
userService.createCalled once." The refactor changes the method breaks the test, even if the behavior remains unchanged. - Full test with a total of mock dataEverything is mocked, nothing is actually exercised. Verification passes, production explodes.
-
Trivial test for coverage:
expect(true).toBe(true)Wrapped in a descriptive test. The file has tests, but does not protect against anything.
The Skill tdd-guide Avoid these anti-patterns by instructing to start from observable external behavior (input/output of the function, endpoint response), not from internal implementation. The RED of the first cycle is almost always an assert on output, not on side effects.
Test-Driven Development on an API Endpoint
On a typical REST endpoint, the TDD cycle is applied thus: Note: I've preserved the exact format of the original token XPHX0XPHX and its surrounding words.
- RED 1 (happy path)Test integration that calls the endpoint with a valid payload, waits for 200 and the specific response body.
- Green 1Implement a controller and use case that produces at least that response.
- Red 2 (validation 400)Test integration with payload Invalid, wait for 400 + specific error message.
- Green 2Add validation and error handling.
- RED 3 (authentication failed)Test with missing or expired JWT token, awaiting response code 401.
- Green 3Add guard auth.
- REFACTORExtract mapper DTO, reorganize errors and handling.
Five-eight cycles RED-GREEN for medium endpoint complexity. Time: 30-60 minutes with the skill. Advantage: immediate live coverage of the endpoint, no "test backfill" future.
Integration with CI threshold
On my portfolio I use a coverage threshold as a gate for CI:
- Backend Spring BootJaCoCo, minimum threshold of 30%, progressive target of 80%.
- Frontend AngularIstanbul, threshold 25% (growing), target 80%.
- Machine Learning service Pythonpytest-cov, threshold 55%, target 80%.
The Skill tdd-guide Produce naturally tests that increase coverage because every new feature comes with its own test set. On my repository, since I consistently adopted the skill on new PRs, the backend coverage has grown from 28% to 41% without any "test backfill sprint" dedicated to it. For the frontend, growth is slower (more legacy architecture), but the pattern remains.
Asynchronous execution compatibility
Async code (Promise, async/await) is notoriously harder to test. The skill teaches three specific patterns:
-
Asynchronous test:
async functiontest +awaitOn the call, never pure callbacks. - Explicit timeoutEvery asynchronous test declares a reasonable timeout (5-30 seconds). Tests that exceed this timeout are considered to be deterministic.
- No arbitrary sleepNothing "wait 500ms and check". Use polling until conditions or events of the framework.
The body of the skill has a section dedicated to edge cases async, which the model reads only when the test requires asynchronous patterns (lazy-loading of references).
Typical session: times and costs
- Feature Medium (4-6 cycles RED-GREEN): 30-50 minutes, 20-40k tokens.
- Complex feature (10+ cycles, multi-edge case handling): 60-120 minutes, 50-100k tokens.
- Bug fix with regression test15-30 minutes, 10-20k tokens.
Comparison: without skill, the same features with tests written after consume a similar total token but produce test theater more than 30% of the time (personal sample, pre-skill period).
Test Development Checklist Invocation
- Does the feature have defined and observable input/output? (yes = Test-Driven Development; no = standard execution)
- Is it business logic (calculations, validations, transformations, algorithms)? (yes = TDD)
- Is it pure, simple code or just CRUD? (yes = standard execute)
- Is there already a configured test framework? If not, the first step is to create the framework scaffold (Wave 0).
Custom variant: Test-Driven Development for Data Transformation Pipeline
On my portfolio I have a custom variant of tdd-guide
Specialized in a transformation pipeline (ETL, data normalization, complex parsing). Modified compared to the base for:
- Start with a real sample dataset always (not synthetic).
- Test of "shape" (output structure) before test of "value" (correctness of values).
- Snapshot test on typical samples, unit test on function transformations.
The variant is effective on pipelines where the challenge is structural coherence, not the algorithm (e.g., parsing XLF i18n, content normalization of articles and front matter).
When the model "bara"
It happens rarely, but it happens: the model, under pressure of context or token budget, writes both the test and implementation in the same cycle without failing the test first. The skill has an auto-control mechanism (re-reads the flow, checks that RED is preceded by real execution of a failed test), but sometimes rarely slips.
Mitigation: after the session, check that every commit RED has a commit GREEN distinct immediately afterwards. If you see a commit "test + impl together", it's likely the skill missed the gate. Reformat the request ("repeat the cycle RED-GREEN separately for feature X").
What I learned writing this article
The thing that struck me is how easily the true TDD differs from test theatre when you know what to look for. Before adopting the skill, I thought I was doing TDD but in reality I was doing "implement-then-test" 70% of the time. The symptom was obvious in hindsight: my tests passed Always After the first run after having been written. Tests that pass always at the first run do not test anything: they are just observing what exists.
According to insight: TDD is not universally convenient. I lost time in the first months trying to apply it to UI components where it didn't make sense. The rule "TDD for business logic, standard for the rest" was the one that allowed me to sustain the practice for a year without effort.
Avoided pattern
- Enforcing Test-Driven Development on everythingHigh cost, low value on the UI Pure and glue code. It's better to have a clear rule in CLAUDE.md of the project that declares where TDD applies and where it doesn't.
- Red without real execution of the testThe "see that it fails" must be literal (execute the test, read the output). If the skill or the model skips verification, you have a theater test from the first cycle. Trust but verify.
A story worth sharing
Placeholder Section If you have experience with structured TDD (positive or frustrated), write to me at federico@federicocalo.devThe pseudonymized true stories enter subsequent clusters.
Previous cluster: Debugging skill Next cluster: Code-reviewer skill →
Frequently asked questions
What is the main issue with using a Large Language Model (LLM) for Test-Driven Development (TDD)?
The LLM may produce code that appears to be TDD, but in reality, it is "write code, then write tests around it", which does not follow the true principles of TDD.
What is the benefit of using a skill like Superpowers for TDD?
It forces the correct order of test before implementation by blocking code generation until there is a test that fails, ensuring that the true RED-GREEN-REFACTOR cycle is applied.
How does the skill help avoid "test theatre", where tests seem rigorous but do not test anything significant?
The skill instructs to start from observable external behavior (input/output of the function, endpoint response), not from internal implementation, and ensures that the RED of the first cycle is an assert on output, not on side effects.
What is a common pitfall when using a skill like Superpowers for TDD?
The model may occasionally write both the test and implementation in the same cycle without failing the test first, which can be mitigated by checking that every commit RED has a distinct commit GREEN immediately afterwards.
Commenti
Caricamento commenti...
Sign in to comment