Skip to content
Engineering/testing-strategy

Test what breaks

"We prioritize integration tests over unit tests and eliminate flaky tests within 24 hours."

Why this exists

Unreliable test suites are worse than no tests at all. They generate false confidence, slow down continuous integration, and get ignored. We write tests to catch errors in critical user paths, not to hit arbitrary coverage targets.

Operational Flow

1

Unit tests: Write unit tests only for pure functions with complex calculations or logic. Do not write them for wrapper functions.

2

Integration tests: Make integration tests your primary focus. Test actions that users take, such as form submissions, endpoint requests, and worker execution. Use a test database rather than mocking database state.

3

End-to-end: Maintain one Playwright suite covering critical user flows like registration and billing. Run these on every pull request.

4

Coverage: Treat 80% line coverage as a minimum threshold. Focus coverage on high-risk features. The billing flow needs 95% coverage, while admin settings are fine at 60%.

5

Naming: Write test names as full sentences. Use `signs in with valid credentials and returns a session token` instead of `test_user_auth`.

6

Flakes: Fix or delete unstable tests within 24 hours of discovery. Flaky tests train developers to ignore build failures.

7

Test data: Generate test state using factories. Never hardcode identifiers or share state between tests.

What good looks like

  • Unit and integration tests run in under 90 seconds. The Playwright suite completes in under 8 minutes.
  • A test fails in CI, and you identify the broken behavior immediately from the test name without opening execution logs.
  • A new endpoint ships with integration tests verifying both the success path and expected error responses.

What NOT to do

  • Do not mock database calls in integration tests. You end up verifying mock behavior rather than code correctness.
  • Do not write tests that only verify that a function executes without throwing.
  • Do not ignore intermittent test failures. Red builds must indicate real issues.
  • Do not write dozens of unit tests for trivial functions that are likely to change.

Ask yourself this when writing tests: will this failure surface before a customer reports it? A test suite that only covers happy paths creates false confidence. Good tests reduce outages. Great tests make regressions obvious immediately after a deployment.

Focus your effort on integration tests. Unit tests are fast but fail to catch system integration issues. End-to-end tests catch configuration errors but run slowly. Optimize for integration testing first. Do not treat code coverage as your primary metric. Coverage shows which lines executed, not whether you verified the logic. If a developer can delete core feature logic and the test suite remains green, you are missing tests.