agentleFS
luckysluckys/agent-skills/skills/tdd-best-practices/SKILL.md

tdd-best-practices

Skill5 starsChanged 31 days agoMITView on GitHub

Use when developing test-first with Red-Green-Refactor, reproducing a bug, testing Value Objects, Aggregates, Domain Events, typed Results, transaction/cache boundaries, data migrations or Criteria/query adapters, selecting test boundaries or doubles, or reviewing test quality. Prefer observable behavior and independent expected values; use refactoring guidance for legacy characterization. Documentation-only edits need no TDD cycle.

The file

Show its rules and text

We split this skill into the rules it gives an agent

27 rules. About 0 are common, 8 are distinctive, and 19 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈8

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 19

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use this skill when the main question is how to drive implementation from tests, how to structure a test suite, or how to recover …

    line 12
  2. Distinctive:

    Write one failing test, then make it pass with the minimum code needed.

    line 16
  3. Distinctive:

    Test behaviors, not implementations — the public API, not private methods.

    line 18
  4. Distinctive:

    Keep tests as simple as the production code they verify.

    line 19
  5. Distinctive:

    Start with units for logic-heavy code.

    line 54
  6. Distinctive:

    Use real Value Objects and child Entities.

    line 62
  7. Distinctive:

    Test the applicable public contract: semantic equality with distinct instances, exact invariant boundaries, and any exposed normalization, …

    line 68
  8. Distinctive:

    Treat difficulty writing a test first as a design or boundary signal.

    line 77
  9. Very specific:

    Read references/behavioral-feedback.md when selecting a test boundary, checking an independent oracle, or proving a regression.

    line 90
  10. Very specific:

    Read references/tdd-core-practices.md for Red-Green-Refactor detail, FIRST properties, the test pyramid, triangulation, and baby steps.

    line 92
  11. Very specific:

    Read references/test-doubles.md for the Meszaros taxonomy (Dummy, Fake, Stub, Spy, Mock), when to use each, and the classicist vs mockist …

    line 93
  12. Very specific:

    Read references/tdd-schools.md for the London (outside-in/mockist) vs Chicago (inside-out/classicist) schools, BDD, and ATDD.

    line 94
  13. Very specific:

    Read references/tdd-anti-patterns.md for James Carr's 15 anti-patterns, Ian Cooper's "TDD, Where Did It All Go Wrong" insights, and …

    line 95
  14. Very specific:

    Read references/tdd-language-examples.md for Red-Green-Refactor walkthroughs in TypeScript, Java, Python, C#, Ruby, and PHP with their …

    line 96
  15. Very specific:

    Read references/projection-testing.md for duplicate, ordering, concurrency, checkpoint, schema migration, replay/rebuild, and …

    line 97
  16. Very specific:

    Read references/migration-testing.md for transformation, dirty-data, idempotent rerun, batch, checkpoint, concurrent-write, reconciliation, …

    line 98
  17. Very specific:

    Read references/value-object-testing.md for semantic equality, invariant boundaries, deep immutability, normalization, optionality, …

    line 99
  18. Very specific:

    Read references/aggregate-testing.md for invariant-first Aggregate tests, repository contract and adapter tests, including atomic failures, …

    line 100
  19. Very specific:

    Read references/domain-event-testing.md for Aggregate event assertions, application handoff, subscriber and real-bus tests, Outbox/Inbox …

    line 101
  20. Very specific:

    Read references/transaction-testing.md for atomic commit/rollback, connection propagation, concurrency, cleanup, commit ambiguity, …

    line 102
  21. Very specific:

    Read references/cache-testing.md for cache hit/miss contracts, invalidation, TTL, key isolation, corruption, failure degradation, stampede, …

    line 103
  22. Very specific:

    Read references/domain-error-testing.md for typed failure assertions, Result short-circuit tests, exhaustive boundary mappings, public …

    line 104
  23. Very specific:

    Read references/criteria-testing.md for parser/AST tests, shared query semantics, real-adapter operator/security tests, pagination …

    line 105
  24. Very specific:

    Use oop-best-practices when a class is hard to test — the design needs improvement first.

    line 109
  25. Very specific:

    Use refactoring-best-practices when adding tests to untested legacy code (characterization tests).

    line 110
  26. Very specific:

    Use ddd-best-practices to decide Aggregate boundaries and invariant ownership before testing them.

    line 111
  27. Very specific:

    Use data-migration-best-practices to design the operational migration workflow and cutover gates before testing it.

    line 112

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

TDD Best Practices

Use this skill when the main question is how to drive implementation from tests, how to structure a test suite, or how to recover discipline in a codebase where tests were written after the fact.

Working Style

  1. Write one failing test, then make it pass with the minimum code needed.
  2. Refactor only when all tests are green.
  3. Test behaviors, not implementations — the public API, not private methods.
  4. Keep tests as simple as the production code they verify.
  5. A test suite that is hard to change is as expensive as production code that is hard to change.

The Red-Green-Refactor Cycle

RED    → Write a failing test that describes the next behavior.
GREEN  → Write the minimum code to make it pass.
REFACTOR → Clean up both the code and the test — no new behavior.

The discipline is in the order. Never refactor on Red. On Green, add only the behavior demanded by the current failing test.

The 3 Laws (Uncle Bob)

  1. You may not write production code unless you have a failing unit test.
  2. You may not write more of a unit test than is sufficient to fail. An intentionally missing public API/type can be a valid first Red; unrelated compilation or setup failures are not.
  3. You may not write more production code than is sufficient to make the currently failing test pass.

Design Workflow

  1. Discover the test command and describe the behavior — use the repository's tooling and name the next observable outcome.
  2. Write a failing test — expose the intended assertion or missing new capability, rather than an unrelated setup error. A regression test must reproduce the existing defect.
  3. Make it pass — take the simplest path; you can clean up after.
  4. Refactor — remove duplication, improve names, reduce complexity.
  5. Repeat — the next test should be the smallest step forward.

Choosing Test Granularity

LevelTestsSpeedConfidence
UnitSingle class/function in isolationMillisecondsBehavior of one unit
IntegrationMultiple real collaboratorsSecondsModule boundaries work
Acceptance / E2EFull system from user perspectiveMinutesFeature works end-to-end

Start with units for logic-heavy code. Start with acceptance tests when following outside-in TDD. Integration tests fill the seams.

Heuristics

When to mock

Mock or fake I/O boundaries in unit/application tests. Use real disposable infrastructure in adapter integration tests where SQL, collation, constraints, search analyzers, transactions, or protocol behavior are the subject.

When testing an Aggregate

Use real Value Objects and child Entities. Test commands through the root, including the rule that a rejected command leaves both state and pending events unchanged.

When testing Domain Events

Assert exact facts after Act: type/name, aggregate identity, business payload, count, and controlled metadata. Test subscriber handling separately from real-bus registration and prove durable duplicate/retry behavior with integration tests.

When testing a Value Object

Test the applicable public contract: semantic equality with distinct instances, exact invariant boundaries, and any exposed normalization, hashing, defensive-copy, operation, or serialization behavior. Inject clocks or policies instead of reading ambient context.

When a test is too big

Large setup is a signal to review fixture clarity and test scope, not proof that the test is too big. Split when multiple behaviors or failure reasons are coupled.

When tests break on every refactor

Tests are coupled to implementation, not behavior. Move the assertion to the public API surface.

When you can't write a test first

Treat difficulty writing a test first as a design or boundary signal; legacy constraints, framework coupling, or missing seams may require characterization tests before redesign.

Warning Signs

  • Tests that only pass in a specific execution order.
  • Mocks that reproduce the production logic (over-mocking).
  • Tests with no assertion (assertTrue(true)).
  • Tests named after methods, not behaviors.
  • A test suite that takes more than 10 minutes to run on CI.
  • Tests that break when internal details change, not when behavior changes.

References

  • Read references/behavioral-feedback.md when selecting a test boundary, checking an independent oracle, or proving a regression.
  • Read references/tdd-core-practices.md for Red-Green-Refactor detail, FIRST properties, the test pyramid, triangulation, and baby steps.
  • Read references/test-doubles.md for the Meszaros taxonomy (Dummy, Fake, Stub, Spy, Mock), when to use each, and the classicist vs mockist distinction.
  • Read references/tdd-schools.md for the London (outside-in/mockist) vs Chicago (inside-out/classicist) schools, BDD, and ATDD.
  • Read references/tdd-anti-patterns.md for James Carr's 15 anti-patterns, Ian Cooper's "TDD, Where Did It All Go Wrong" insights, and recovery strategies.
  • Read references/tdd-language-examples.md for Red-Green-Refactor walkthroughs in TypeScript, Java, Python, C#, Ruby, and PHP with their respective test frameworks.
  • Read references/projection-testing.md for duplicate, ordering, concurrency, checkpoint, schema migration, replay/rebuild, and eventual-consistency tests for read models.
  • Read references/migration-testing.md for transformation, dirty-data, idempotent rerun, batch, checkpoint, concurrent-write, reconciliation, cutover, and recovery tests for data migrations.
  • Read references/value-object-testing.md for semantic equality, invariant boundaries, deep immutability, normalization, optionality, serialization, and property-based Value Object tests.
  • Read references/aggregate-testing.md for invariant-first Aggregate tests, repository contract and adapter tests, including atomic failures, deterministic Mothers, collection equality, transaction propagation, and concurrency integration tests.
  • Read references/domain-event-testing.md for Aggregate event assertions, application handoff, subscriber and real-bus tests, Outbox/Inbox delivery tests, Integration Event contracts, and CDC mapping tests.
  • Read references/transaction-testing.md for atomic commit/rollback, connection propagation, concurrency, cleanup, commit ambiguity, decorators, and side-effect boundary tests.
  • Read references/cache-testing.md for cache hit/miss contracts, invalidation, TTL, key isolation, corruption, failure degradation, stampede, and HTTP privacy tests.
  • Read references/domain-error-testing.md for typed failure assertions, Result short-circuit tests, exhaustive boundary mappings, public redaction, unknown 500 behavior, Effect execution, and error-test-double caveats.
  • Read references/criteria-testing.md for parser/AST tests, shared query semantics, real-adapter operator/security tests, pagination traversal, joins, nested boolean filters, and false-confidence warnings.

Related Skills

  • Use oop-best-practices when a class is hard to test — the design needs improvement first.
  • Use refactoring-best-practices when adding tests to untested legacy code (characterization tests).
  • Use ddd-best-practices to decide Aggregate boundaries and invariant ownership before testing them.
  • Use data-migration-best-practices to design the operational migration workflow and cutover gates before testing it.

Source Influences

This skill is synthesized from:

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.