Skip to content

UnitTestingPrinciples

Dennis Lee edited this page May 27, 2026 · 1 revision

title: Unit Testing Principles radar_quadrant: Techniques radar_ring: Assess radar_position: inner created: 2026-05-26 last_updated: 2026-05-26 tags: [testing, tdd, unit-tests, quality] source_url: https://olano.dev/blog/unit-testing-principles/

Unit Testing Principles

A set of named principles for writing effective unit tests, as distilled by olano.dev. The principles address the most common failure modes in test suites: tests that break on refactoring, tests with ambiguous failure messages, and test suites that are slow or order-dependent.

The Principles

Test behaviour, not implementation. Tests should assert on observable outputs given specific inputs, not on which internal methods were called or what internal state was set. Implementation tests break whenever code is refactored, even when behaviour is unchanged — they add friction without adding safety.

One logical assertion per test. Each test should verify one thing. When a test with multiple assertions fails, the failure message identifies which assertion broke but leaves the others unverified. One assertion per test means a failure is unambiguous and the full picture is visible across all test results.

Arrange-Act-Assert structure. Every test follows three phases: set up preconditions (Arrange), execute the behaviour under test (Act), verify the outcome (Assert). Consistent structure makes tests scannable and reduces cognitive load when debugging failures.

Test independence. Tests must not share state or depend on execution order. A test suite where tests pass individually but fail when run together, or pass in one order but not another, is unreliable. Each test must set up its own preconditions and clean up after itself.

Names as failure documentation. A test name should describe the scenario and expected outcome precisely enough that the failure message alone tells you what broke. A name like test_user fails this; test_user_creation_fails_when_email_is_missing passes it.

Relationship to Other Radar Entries

Complements TDD Guard (enforces TDD discipline during development), testcontainers-python (real infrastructure in tests), and Lambda Unit Testing with Moto (AWS service mocking). Those entries cover what to test against; these principles cover how to write the tests themselves.

Radar Assessment

Placed in Techniques / Assess / inner. Named principles applicable to any test suite in any language without tooling changes. Inner position reflects that most codebases have existing test suites where these principles can be applied immediately as a quality improvement pass. Trial gate: one existing test module refactored to satisfy all five principles, with test count held constant and a failing build confirmed after introducing a real regression.

Clone this wiki locally