From an SRE lens, each test type's value is measured by which production incident class it would have prevented and how that maps to mean time to detect (MTTD) and mean time to repair (MTTR), not just by its speed.
The five types, from an SRE perspective
| Type | Runs on | Typical execution time | Production risk it mitigates | Example incident it would help prevent |
|---|
| Unit | Every pull request | Seconds | Logic bugs that would silently corrupt data or compute wrong results | A billing calculation bug that silently overcharges customers over weeks before anyone notices |
| Integration | Pull request (subset) and nightly (full) | Low minutes | Wiring bugs between your service and a real dependency (database, cache) | A schema mismatch that causes every write to a specific field to silently fail after a migration |
| Contract | Every pull request | Seconds to low minutes | A dependency silently changing its API shape underneath you | An upstream service renaming a response field, causing your service to read null and degrade silently instead of failing loudly |
| End-to-end | Pre-production / pre-release gate | Minutes | The whole request path being broken in a way no single component's tests would catch | A load balancer misconfiguration that makes health checks pass while real user traffic still fails |
| Load | Nightly or scheduled, rarely per-commit | Tens of minutes to hours | Capacity and latency degradation under realistic traffic | A memory leak or connection-pool exhaustion that only manifests after sustained load, causing a slow-building outage |
How the mix influences MTTD and MTTR
A mix weighted correctly toward the cheap, fast levels (unit and contract) catches the majority of bugs BEFORE they ever reach a running system, which is the strongest possible MTTD: zero, because the bug never becomes a production incident at all. Integration and end-to-end tests catch what those cheaper levels structurally cannot (real wiring and real request-path issues), and doing so before release keeps MTTD from being measured in the field at all. Load tests specifically target incidents that would otherwise have very poor MTTD in production, since capacity-degradation issues often build slowly and are easy to miss until they cause a cascading incident; catching them in a scheduled load test converts a potentially multi-hour, hard-to-diagnose production incident into a same-day, well-instrumented test failure. For MTTR specifically, a well-distributed mix helps because a well-isolated test failure (a unit test naming the exact broken function, a contract test naming the exact field that changed) gives you a head start on diagnosis that a bare production alert, with none of that isolation, does not; an incident whose root cause a test failure would have pinpointed immediately can take an SRE far longer to isolate live, under production pressure, with incomplete information.
An alternate taxonomy some candidates will reach for
Some teams describe this same territory as four levels instead of five: unit, integration, system, and acceptance, where "system" plays a similar role to end-to-end above (the whole assembled service validated as one unit) and "acceptance" verifies the service meets its stated requirements before sign-off, with load testing folded in as a specialized system-level check rather than called out as its own row. Either taxonomy is fine to use in an interview; what matters for the MTTD/MTTR argument is the underlying cost-and-realism ordering (cheap and isolated through to slow and fully realistic), not which label set you reach for.
Trade-offs and pitfalls
The SRE-specific pitfall is treating test types purely as pre-release quality gates and underweighting their role as an MTTD/MTTR lever: a team that skips load testing because "it's slow and rarely fails" is trading a controlled, well-instrumented same-day test failure for a real production incident with a much worse MTTD, at a point where the cost of detection has shifted entirely onto on-call engineers and real users instead of a scheduled test run.