Testing
What to test at which level, and what a passing suite does not tell you.
Questions
Easy / Med / Hard
Your accuracy
Tests exist to let you change code without fear. Everything about how you write them follows from that.
The test pyramid describes proportions: many fast unit tests covering logic in isolation, fewer integration tests checking that pieces fit together, and a small number of end-to-end tests exercising a real user journey. Inverting it — mostly end-to-end — gives you a suite that is slow, flaky, and tells you something broke without telling you what. The test trophy is a popular variant arguing integration tests deserve the most weight.
Test doubles have distinct names, and interviewers use them precisely. A stub returns canned answers. A mock is preloaded with expectations and asserts it was called correctly. A fake is a working lightweight implementation, like an in-memory repository. A spy records calls without changing behaviour. Reaching for a mock when a fake would do is how test suites end up asserting on their own mocks rather than on behaviour.
Arrange, Act, Assert is the structure that keeps a test readable: set up state, perform one action, check one outcome. A test whose name contains "and" is usually two tests.
Coverage is a signal, not a target. It tells you which lines ran, not whether anything was verified — a test with no assertions still produces coverage. Chasing a percentage produces tests written to touch lines. Low coverage in a critical path is still worth knowing about.
Flaky tests are worse than missing ones, because a suite that fails randomly trains the team to ignore red. Quarantine and fix them; do not re-run until green.
Test behaviour, not implementation. A test coupled to how the code works breaks on every refactor and passes when the behaviour is wrong.