The model
Tests provide evidence about behavior at different boundaries. Unit tests isolate a small decision; integration tests exercise collaboration between components; end-to-end tests validate a user-visible path. Each level trades feedback speed, realism, and setup cost differently.
A concrete walk-through
A unit test can verify that a retry policy stops after its configured budget. An integration test can verify that the persistence adapter records an idempotency key. An end-to-end test can prove the checkout flow returns the expected result through the deployed browser-facing path.
Costs and failure cases
High coverage does not prove meaningful behavior was asserted. Tests that duplicate implementation details can block harmless refactoring, while a few end-to-end tests may miss many edge cases. Choose representative contracts and include failure and boundary conditions.
Check your understanding
A service test passes with a mocked database but production loses updates under concurrent requests. Which test layer was missing, and what invariant should the new test exercise?