PrepGenAICerts

Four Test Levels: Unit, Functional, Integration, End-to-End

Core

Identify the type of a Claude application error · Difficulty 2/5

0%
test-levelsintegration-testingunit-testingend-to-end-testing

Explanation

A Different Cut Than the Failure Buckets

The five failure buckets classify a failure *after* it happens. Test levels are a complementary idea: they classify what a given *test* is actually capable of catching *before* anything fails, so a passing test suite doesn't quietly hide a gap nobody wrote a test for. A given test only tells you something if you know in advance the specific class of failure it's positioned to catch -- and, equally, the classes it has no way of catching.

LevelWhat it isolatesWhat it cannot catch
UnitA single function on its own -- a parser, a tool wrapper, isolated from its surroundingsWhether the pieces actually work once wired together
FunctionalOne Claude call, checked for the right shape and type against a given inputProblems in the system surrounding that one call
IntegrationThe join between two components -- e.g., a retrieval result feeding into a model callProblems that only show up once the whole pipeline runs together
End-to-endThe complete path, run the way a real user would trigger it, input through to output*Which* link in the chain actually broke -- it only shows you the final outcome, and it's the slowest tier to run

Why the Integration Level Is Where Silent Failures Hide

This is the level worth dwelling on, because it's the one most teams skip. Each side of a handoff can sail through its own test while the connection between the two sides is still broken -- and neither unit test, run on its own, will ever surface that.

Here's a concrete shape of that failure: an order-lookup function is unit-tested in isolation and correctly returns a structured order record -- it passes. A response-formatter function is functionally tested by handing it a hand-built order record directly, and it correctly renders a customer-facing summary from that record -- it passes too. Wire the two together, though, and the order-lookup function actually returns its record wrapped inside a status envelope ({"status": "ok", "data": {...}}), while the formatter was written expecting the bare record itself. The formatter chokes silently on the mismatch and falls back to a generic "order not found" message even though the lookup succeeded. Neither test sees this: the lookup function is doing exactly what its unit test checks, and the formatter is doing exactly what its functional test checks against a well-formed input. The gap lives specifically in the never-written contract *between* the two functions, and only a test exercising both together, with real data flowing from one into the other, would catch it.

PASS  test_lookup_unit             returns a valid order record
PASS  test_formatter_functional    renders a summary from a well-formed record
FAIL  test_full_flow_e2e
  step 1 lookup_order(id)      ok  -> {"status": "ok", "data": {...}}
  step 2 format_summary(resp)  ok  -> formatter reads resp directly, not resp["data"]
  step 3 assert summary        FAIL -> "order not found" shown despite a successful lookup

Complementary to, Not a Replacement For, Reproduce-Inspect-Localize

The four test levels and the reproduce-inspect-localize procedure (4.2.1) answer different questions and work together, not as alternatives. Test levels are a *design-time* discipline: deciding in advance which level of test would catch a given class of bug, so the gap is closed before it ships. Reproduce-inspect-localize is a *post-hoc* discipline: given a failure that already happened in the wild, working backward to find which layer owns it. A missing integration test is exactly the kind of gap that reproduce-inspect-localize will eventually surface in production -- the fix, once localized, is often to add the integration test that should have existed already, so the same seam-level break can't ship silently again.

Common exam traps

  • Assuming that unit tests plus functional tests passing means the system works. Both can pass while the handoff between the two components they cover is still broken -- that gap is precisely what the integration level exists to close.
  • Treating end-to-end tests as sufficient on their own because they exercise the whole flow. They catch that *something* broke but are the hardest level to localize a failure within -- they don't tell you *where* in the chain the break occurred.

Key Takeaways

  • Four test levels: unit (one function in isolation), functional (one Claude call returns the expected shape), integration (the seam between two components), end-to-end (the full flow)
  • The integration level is where most silent failures hide -- each side can pass its own test while the handoff between them is still broken
  • Classic integration gap: a retrieval function returns a list of dicts, a prompt-builder expects a plain string -- both pass their own tests, the combination silently fails
  • End-to-end tests are the slowest to run and the hardest to localize a failure within, even though they exercise the whole flow
  • Test levels are a design-time discipline (which test would catch this class of bug) that complements, not replaces, the post-hoc reproduce-inspect-localize procedure

Glossary Terms

Related Concepts

PrepGenAICerts.com is an independent third-party exam-prep platform for the Claude Certified Architect (CCA-F) certification. We are not affiliated with, endorsed by, or acting on behalf of Anthropic PBC.

Note: New premium upgrades are temporarily paused while we resolve an issue with our payment provider. Existing premium members retain full access.