Skip to main content

Why unit tests are not enough

Short answer

Unit testing verifies each unit in isolation using stubs and drivers, so it misses interface errors, real-data behavior, and emergent system properties. Systems with interacting units also need integration, regression, system, performance, security, recovery, release, and acceptance testing.

Why unit test is not enough in system with multiple interacting units? What other tests are required?

Unit testing checks each unit (function, method or class) separately, usually with stubs and drivers standing in for the units it talks to. It shows that each unit works on its own, but in a system with many interacting units most serious faults lie in the interactions, which unit tests do not exercise.

Why unit testing is not enough

  1. Interface errors are not found. Sommerville lists the interface types where faults occur:

    • Parameter interfaces: data passed between functions
    • Shared memory interfaces: blocks of memory shared by units
    • Procedural interfaces: a sub-system offering a set of procedures
    • Message passing interfaces: units requesting services by messages

    The common interface errors are:

    • Interface misuse: wrong type, order or number of parameters.
    • Interface misunderstanding: the caller makes wrong assumptions about the called unit, e.g. calling a binary search with an unsorted array.
    • Timing errors: producer and consumer run at different speeds, so stale data is read (in real-time and shared-memory systems).
  2. Stubs and drivers are not the real units. A stub returns simple fixed values, so behaviour with real data is not tested.

  3. Data can be lost or changed across an interface, and global data structures shared by units can be corrupted by one unit and break another.

  4. Combined functions may not work. Sub-functions that are each correct may not produce the required main function when combined.

  5. Small errors add up. Rounding errors that are acceptable in one unit can be magnified across units.

  6. Emergent and non-functional properties (performance, security, reliability, usability) appear only when the whole system runs.

  7. Environment problems: databases, networks, operating systems and hardware are not used in unit tests.

Example: in an online shop, the cart unit computes the total in paisa and passes it to the payment unit, which expects rupees. Both units pass their unit tests, but the customer is charged 100 times too much. Only integration testing finds this.

Other tests required

TestPurpose
Integration testingCombine units (top-down, bottom-up, sandwich) and test their interfaces
Regression testingRe-run tests after each change or integration step
System testingTest the whole system against requirements
Performance/stress testingCheck response time and behaviour beyond the normal load
Security and recovery testingCheck protection against attack and recovery after failure
Release testingIndependent black-box test of the version to be delivered
Acceptance testing (alpha, beta)Users confirm the system meets their needs

✓ Answer checked by Claude Opus 5.5 (high effort)

All Software Engineering chapter 8 questions →