Skip to main content

The Testing Trophy

The Testing Trophy reweights testing toward integration tests, layered on top of static analysis and unit tests, to maximize confidence per cost. It suits frontend and full-stack apps where behavior-focused tests deliver the strongest signal.

Organization
Kent C. Dodds
Published
May 1, 2018

Best Practice: The Testing Trophy

The Testing Trophy, introduced by Kent C. Dodds, is an alternative to the Test Pyramid that is especially popular for frontend and JavaScript applications. Its layers, from bottom to top, are static analysis, unit tests, integration tests, and end-to-end tests, with integration tests forming the widest band. The guiding principle is to "write tests that resemble the way your software is used," maximizing confidence per unit of effort. Integration tests sit at the sweet spot: they exercise real component interactions while staying faster and less brittle than full end-to-end runs.

Step-by-Step Implementation Guidance

  1. Establish static analysis first with a type checker and linter so whole classes of bugs never reach tests.
  2. Write unit tests for pure functions and complex logic that is hard to reach through the UI.
  3. Invest the most effort in integration tests that render real components together with realistic data.
  4. Avoid testing implementation details; assert on behavior and user-visible output.
  5. Add a thin layer of end-to-end tests for critical paths across the whole stack.
  6. Wire all four layers into CI, running static checks and unit tests on every push.
  7. Measure confidence and maintenance cost, not just coverage, and adjust the mix.

Common Mistakes Teams Make When Ignoring This Practice

  • Over-mocking until integration tests no longer reflect real behavior.
  • Skipping static analysis and re-discovering type errors in slower tests.
  • Testing component internals, so refactors break tests without behavior changing.
  • Treating every test as a unit test and missing integration regressions.
  • Letting end-to-end suites balloon and slow the feedback loop.

Tools and Techniques That Support This Practice

  • Static analysis: TypeScript, ESLint, Prettier.
  • Unit and integration: Jest, Vitest, Testing Library, MSW for network mocking.
  • End-to-end: Playwright, Cypress.
  • Coverage: Istanbul/nyc.
  • CI: GitHub Actions or GitLab CI to run layers in order.

How This Practice Applies to Different Migration Types

  • Cloud Migration: Keep integration tests focused on application behavior so they survive infrastructure changes underneath.
  • Database Migration: Use integration tests with a real test database to validate data access through the application layer.
  • SaaS Migration: Mock third-party APIs at the network layer so integration tests remain stable across providers.
  • Codebase Migration: Lean on behavior-focused integration tests to confirm a rewrite preserves user-facing behavior.

Checklist

  • Static analysis (types and linting) runs before tests.
  • Integration tests are the largest and most-invested layer.
  • Tests assert behavior, not implementation details.
  • Network and external calls are mocked realistically.
  • A small set of end-to-end tests covers critical paths.
  • All layers run in CI with fast checks gating pushes.
  • The mix is reviewed by confidence and maintenance cost.