tdd
Test-Driven Development
Philosophy
Core principle: Tests should verify observable behavior through the most stable contract boundary available, not incidental implementation details. Code can change entirely; tests should not fail unless behavior changes.
Good tests are integration-style: they exercise real code paths through public APIs. They describe what the system does, not how it does it. A good test reads like a specification - "user can checkout with valid cart" tells you exactly what capability exists. These tests survive refactors because they don't care about internal structure.
Bad tests are coupled to implementation. They mock internal collaborators, test private methods, or assert incidental call order. The warning sign: the test breaks when behavior-preserving internals are renamed or rearranged.
Public responses are not always sufficient evidence. Persistence, idempotency, concurrency, queue, and recovery contracts may require a fresh process, independent connection, post-commit read, or durable-state assertion. Use that evidence when it is part of the observable contract; do not substitute a green response or mock interaction for the real invariant.