Test strategymedium0-2 years

A service has 800 unit tests that run in 4 seconds and 40 browser tests that take 25 minutes, and nothing in between. A repository query with a wrong `JOIN` shipped and was caught only by a browser test, three hours after the merge. Name the shape, explain why the unit tests could not have caught it, and say where you would add tests.

That is the hourglass: many unit tests, many end-to-end tests, nothing in the middle. A unit test of a repository mocks the database or never reaches it, so it cannot tell whether the SQL is valid or returns the right rows; only a database can say that. The missing layer is integration: a @DataJpaTest against a real PostgreSQL in a container, which runs in seconds and fails on the exact query. The rule for placing a test is 'the lowest level that could actually fail for this reason': a discount threshold is a unit test, a query is an integration test against a real database, and 'can a customer check out' is one end-to-end test, not forty.

The lesson behind it →
More on Test strategy