What makes a good unit test (FIRST principles)?
Quick Answer
Good tests are FIRST: Fast (milliseconds), Isolated (no shared state, no order dependence), Repeatable (same result every run, any machine), Self-validating (pass/fail, no manual checking), Timely (written with or just after the code). They test behaviour, not implementation details.
The acronym is FIRST — fast, isolated, repeatable, self-validating, timely. Fast so I run them constantly. Isolated so one test can't affect another and order doesn't matter. Repeatable so they don't depend on the date or the machine. Self-validating so it's a clean pass or fail. And timely, written close to the code. Beyond that, the biggest thing is testing behaviour through the public interface, not implementation details — if I refactor the internals without changing what the class does, the tests shouldn't break. If they do, they were testing the wrong thing.
- Brittle test smells: asserting on private state, verifying every internal call, hard-coded dates/GUIDs, sleeping, depending on test order.
- Test the public contract — a refactor that keeps behaviour should not break tests.
- One reason to fail per test; a clear name so a failure tells you what broke.
- Avoid logic in tests (loops, conditionals) — a test with a bug is worse than no test.