The Testing Pyramid Is Not a Suggestion

Most teams have an inverted pyramid — heavy on E2E, light on unit tests. Here's how to audit and rebalance the test portfolio.

The testing pyramid has been around for over fifteen years. Everyone knows it. Almost nobody follows it.

The typical codebase has:

  • A handful of unit tests (mostly for utility functions)
  • Almost no component or integration tests
  • A massive, slow, flaky E2E suite that runs for 45 minutes and fails on every third build

That’s not a pyramid. That’s an ice cream cone — expensive at the top, hollow in the middle.

The layers, and what each should verify

Unit tests (the base — largest quantity)

Unit tests verify individual functions, methods, or classes in isolation. They’re fast (milliseconds), deterministic, and cheap to write.

What to test at this level:

  • Business logic and calculations
  • Validation rules
  • Data transformations
  • Conditional branching
  • Error handling and edge cases

What NOT to test here:

  • Database queries (that’s integration)
  • HTTP responses (that’s component/integration)
  • Full user flows (that’s E2E)

Target: Every function with meaningful logic should have unit tests. Use branch coverage, not line coverage, to measure thoroughness. For what actually belongs in those tests, Write Tests That Mean Something covers negative and boundary cases in more depth.

Component tests (the middle — moderate quantity)

Component tests verify that a single service or module works correctly with its immediate dependencies — a real database, a real message queue, or a real filesystem.

What to test at this level:

  • API endpoint behaviour (request → response contract)
  • Database operations (repository layer with a real DB, via TestContainers or similar)
  • Message handling (publish → consume → side effect)
  • Service orchestration logic

Why this layer is almost always missing: It’s harder to set up than unit tests but less “impressive” than E2E tests. It requires test infrastructure (containers, in-memory databases, mocked external services) that many teams haven’t invested in.

This is the most valuable missing layer in most test suites. It catches integration bugs — serialization issues, query errors, configuration problems — without the cost and flakiness of E2E tests.

Integration tests (the upper-middle)

Integration tests verify that multiple services or modules work together correctly. They test the boundaries between systems: API contracts, event schemas, data flow across services.

What to test at this level:

  • Service-to-service API contracts (consumer-driven contract tests)
  • Data flow through multi-step pipelines
  • Authentication and authorization across service boundaries
  • External service integration (with sandbox/mock environments)

E2E tests (the tip — smallest quantity)

E2E tests verify complete user workflows through the full application stack. They’re slow, expensive, and fragile — by design, because they’re testing the whole system.

What to test at this level:

  • Critical user journeys (sign up, purchase, submit claim)
  • Flows that cross multiple services and require real orchestration
  • Smoke tests for deployment verification

What NOT to test here:

  • Individual validation rules (that’s unit)
  • API response formats (that’s component)
  • Database edge cases (that’s integration)

Target: 5–15 critical path tests, not 500 tests that duplicate unit-level assertions through the browser.

How to audit your test portfolio

As a quality engineer, this is one of your highest-leverage activities: auditing the distribution of tests, not just the count.

Step 1: Categorise

Count your tests by layer:

Layer Count % of total Run time
Unit ? ? ?
Component ? ? ?
Integration ? ? ?
E2E ? ? ?

Step 2: Check the ratios

A healthy pyramid looks roughly like:

  • 70% unit tests
  • 15% component/integration tests
  • 10% integration/contract tests
  • 5% E2E tests

The exact numbers don’t matter. The shape does. If E2E is your largest layer, your pyramid is inverted.

Step 3: Find the duplication

The most common waste: E2E tests that verify behaviour already covered by unit tests. A Playwright test that checks “entering an invalid email shows an error” is duplicating a unit test on the validation function — except it takes 30 seconds instead of 3 milliseconds and depends on a browser, a server, a database, and a network connection all being healthy.

For every E2E test, ask: can this assertion be made at a lower layer? If yes, move it down.

Step 4: Find the gaps

The most dangerous gaps are in the middle layers. If you have unit tests and E2E tests but nothing in between, you’re missing:

  • Service integration bugs (wrong HTTP status, missing headers, serialization mismatches)
  • Database query bugs (incorrect joins, missing indexes, constraint violations)
  • Configuration bugs (wrong connection strings, missing feature flags, environment-specific behaviour)

These are the bugs that pass unit tests (no real DB), pass in dev (different config), and fail in production.

Step 5: Measure time, not just count

A test suite with 500 unit tests (30s) and 50 E2E tests (20min) spends 97% of its runtime on 9% of its tests. That’s a feedback loop problem.

If your CI pipeline takes more than 10 minutes, the bottleneck is almost certainly in the upper layers. Push assertions down.

The quality engineer’s role

Quality engineers don’t just write tests. They design the test architecture. That means:

  1. Setting the layer strategy — which assertions belong at which level
  2. Building the infrastructure — TestContainers, API test harnesses, contract testing frameworks
  3. Reviewing test placement — catching tests written at the wrong layer during code review
  4. Measuring and reporting — showing the team the pyramid shape, the time distribution, and where the gaps are
  5. Coaching the team — helping developers write better unit tests so the quality engineering team can focus on integration and E2E

The pyramid isn’t a suggestion. It’s an engineering decision about where to allocate your testing investment for maximum signal at minimum cost. Quality engineers own that decision.


When AI agents write your tests, the pyramid problem compounds fast. Specialist agents with scoped responsibilities are one structural answer for keeping it balanced.