Testing Levels

What each testing level checks, which risks it covers, and why one level cannot replace another.

Updated:

Contents

Testing levels distribute checks across system layers. Different defects are detected more cheaply and reliably at different levels: some within a function, some at integration boundaries, and others only in a user journey.

The main levels

  • →Unit testing checks individual functions, methods, or classes in isolation.
  • →Integration testing checks interactions among modules, services, databases, queues, and external dependencies.
  • →System testing evaluates the complete product with its business logic and environment.
  • →Acceptance testing checks whether the solution meets user or business expectations and is ready for acceptance.

What each level provides

  • →Unit: fast, inexpensive feedback on low-level logic failures.
  • →Integration: protection against contract, data, and component-interaction problems.
  • →System: complete user scenarios and end-to-end behavior.
  • →Acceptance: confirmation that the team solves the right problem as well as implementing it correctly.

Why one level is insufficient

  • →Unit tests do not reveal integration failures between services.
  • →System tests are too expensive and fragile to cover every rule.
  • →Acceptance testing without technical levels often provides feedback too late.
  • →Imbalance creates blind spots or an excessively expensive regression suite.

A QA perspective

  • →For every risk, ask which level will detect it earlier, more cheaply, and more reliably.
  • →Plan checks for contracts, data, rules, and integrations alongside the UI.
  • →Use levels strategically rather than as a requirement to test everything everywhere.
📐

If a risk can be detected earlier at a lower level, there is little reason to wait for it to surface in the UI or a full end-to-end scenario.