TheSkillz

TDD Workflow

Strict red-green-refactor with observed failures and a verification gate

TheSkillz Team TheSkillz Team No reviews yet2 installsv1.0.0
Scan passed · 100/100Human reviewedOfficial · TheSkillz
☆ Star 0

Turns a request into a list of behaviours, then drives one failing test at a time through minimal implementation and refactor, committing per green cycle. Ends with a gate that requires the full suite output pasted, not described.

SKILL.md

TDD Workflow

The point of test-driven development with an agent is not ideology; it is that a test you watched fail is the only proof that the test can fail. Code written before its test tends to get tests that assert whatever the code happens to do.

Ground rules

  1. No production code without a failing test that demands it.
  2. Run the test and see it fail for the right reason before writing the implementation. A test that fails because of a typo or missing import proves nothing.
  3. Write the smallest implementation that passes. Resist generalising until a second test forces it.
  4. Refactor only on green, and re-run the suite after refactoring.
  5. Keep each cycle under roughly ten minutes of work; if a step is bigger, split the behaviour.

Procedure

0. Discover the harness

  • Find the runner and command: package.json scripts, pyproject.toml, Makefile, CI config. Note how to run a single file (vitest run path, pytest path::test_name, go test ./pkg -run Name).
  • Read two existing tests to copy naming, fixture and assertion style. Match them; do not introduce a new testing style.

1. Turn the request into behaviours

List the observable behaviours as one-line test names before writing any test:

- returns empty list when cart has no items
- applies percentage discount before tax
- rejects negative quantities with ValidationError

Order them simplest first. Confirm the list with the user if the requirement is ambiguous.

2. Red

  • Write exactly one test for the first behaviour. Arrange, act, assert. One logical assertion per test.
  • Run only that test. Paste the failure output. Confirm the failure message is about missing behaviour, not a broken setup.

3. Green

  • Implement the minimum. Hard-coding a return value is acceptable for the first test; the next test will force real logic.
  • Run the single test, then the surrounding file. Both must pass.

4. Refactor

  • Remove duplication, rename for clarity, extract helpers — in both test and production code.
  • Run the full relevant suite. If it goes red, undo the refactor rather than patching.

5. Commit

  • One commit per green cycle or per small group of cycles: feat(cart): apply percentage discount before tax. Small commits make review and bisecting cheap.

6. Repeat for the next behaviour, then finish with the verification gate.

Verification gate (before saying "done")

  • Full suite passes locally with the exact command CI uses.
  • Every new behaviour has a test whose failure you observed.
  • No test was weakened (skip, loosened assertion, widened timeout) to get to green.
  • Coverage of the changed files did not drop (run the coverage command if one exists).
  • Lint and type checks pass.
  • Paste the final test run summary in your report; do not describe it from memory.

Writing good tests

  • Test behaviour through public interfaces; avoid asserting on private state or call counts unless the interaction is the behaviour (e.g., "sends one email").
  • Use real collaborators where cheap (in-memory DB, real date library); mock only network, time and randomness.
  • Name tests as sentences: test_refund_is_rejected_after_30_days.
  • Deterministic inputs: freeze time, seed randomness, avoid sleeping.
  • For bug fixes: first write the test that reproduces the bug (it must fail on the current code), then fix.

Output format

Report as a log of cycles:

Cycle 1 — returns empty list when cart has no items
  RED: FAIL cart.test.ts > "TypeError: total is not a function"
  GREEN: PASS (1 test)
Cycle 2 — ...
Final: 47 passed, 0 failed, 0 skipped (vitest run) — coverage 91% (+2%)
Commits: 3

Pitfalls

  • Writing all tests up front, then all code, is not TDD; the feedback loop is lost and tests end up coupled to a guessed design.
  • Do not assert on error message strings that are likely to change; assert on the error type or code.
  • Snapshot tests are not a substitute for behavioural tests; use them for serialised output only.
  • If you cannot make a test fail, the behaviour already exists or the test is not testing what you think.
  • When the harness is slow, run the narrowest command possible during the loop and the full suite only at the gate.

Reviews

Sign in to leave a review.

  • Be the first to review this skill.

More in testing