Theory: Integration Testing, Top-Down vs. Bottom-Up
Units that pass their own tests are a good start, but nobody uses a unit on its own. This lesson explains why tested units can still fail when they are put together, where integration testing sits in the V-model, and the two strategies for putting units together: top-down and bottom-up.
Why Unit Tests Are Not Enough
Think of an orchestra. Every musician has practised their part alone and plays it perfectly. At the first full rehearsal it still sounds wrong: one section is slightly out of tune with another, someone comes in a beat early, two players reach for the same music stand. None of these problems existed in solo practice. They only exist between the players.
Integration testing puts tested units together, step by step, and tests them as a group. It has two purposes:
to test subsystems as units (a group of units now behaves like one bigger unit), and
to test the interfaces between units (the messages, calls and data they exchange).
The professor gave three reasons why units that work alone can fail together.
Precision errors grow
Suppose three modules each produce a result with a precision of 0.9, and each passes its result to the next:
0.9×0.9=0.81,0.81×0.9=0.729
Each module was acceptable alone, but the combined chain has a precision of only 0.729. No unit test can see this, because no unit test runs the chain. Only an integration test can.
Interface errors
The calls and messages between units were never tested in action. One unit may send a date as day/month/year while the other expects month/day/year; one may pass centimetres where the other expects metres. Each unit is “correct” by itself.
Timing problems
Some failures appear only when units run together and at the same time: race conditions (the result depends on which unit gets there first), resource contention (two units competing for the same file, memory or device), and similar problems, especially in real-time systems.
Where It Fits: the V-Model
The V-model pairs each development step on the way down (decomposition) with a test level on the way up (composition). Integration testing is the step right after unit testing on the way up, and it checks the design.
Each test level on the right checks the step at the same height on the left; integration testing checks the design.
Two Strategies: Top-Down and Bottom-Up
You can assemble a system starting from the top or from the bottom. Either way, some modules are missing at the start, and something fake must stand in for them (see 8.2).
Diagram loads as you scroll.
Top-down: start with the top module (the main control module, which acts as the driver). The lower modules are not ready, so use stubs. Then replace the stubs with real modules, step by step. Like a film crew shooting the main scenes first, with stand-ins reading the lines of actors who have not arrived yet.
Bottom-up: start with the lowest modules. The higher modules are not ready, so write drivers to call them. Then replace the drivers with real higher modules, step by step. Like testing every brick and beam on a rig before building any walls.
Top-down
Bottom-up
Fakes needed
Stubs (for missing lower modules)
Drivers (for missing higher modules)
Good points
An executable program is available early. Interface flaws are found early.
Better controllability and observability of the low-level modules.
Bad points
Poorer controllability and observability of low-level modules. Writing and maintaining stubs costs a lot.
An executable program is available very late. Writing many drivers is very expensive.
Exam radar: know the pairs top-down → stubs and bottom-up → drivers, and one good point and one bad point for each. Notice that they are mirror images: what one is good at, the other is bad at.
In practice the choice depends on which risk you want to see early: the shape of the whole system and its upper interfaces (top-down), or tight control of the low-level modules (bottom-up).
How to write the answer for a “compare” question: state the shared goal first, then discuss both strategies under the same criteria (how they start, which fakes they need, strengths, weaknesses), and end with when each is preferable. Do not declare one universally better.
Worked Examples
Exercise 1
What are the two purposes of integration testing?
Show solution ↓Hide solution ↑
Solution
To test subsystems as units: a group of integrated units is tested as one bigger unit.
To test the interfaces between units: the calls, messages and data that units exchange, which unit tests never exercise in action.
Exercise 2
Three modules each have a precision of 0.9, and each passes its result on to the next. What is the precision of the chain, and what does this example show about unit testing?
Show solution ↓Hide solution ↑
Solution
0.9×0.9×0.9=0.81×0.9=0.729
The chain has a precision of 0.729, much worse than any single module. It shows that errors can grow when results pass from one unit to the next. Each unit test only runs one module, so it sees 0.9 and passes; only an integration test, which runs the modules together, can reveal the combined effect.
Exercise 3
In top-down integration, which kind of fake module do you need, and why? Answer the same question for bottom-up integration.
Show solution ↓Hide solution ↑
Solution
Top-down needs stubs. It starts with the top (main control) module, which calls lower modules that are not ready yet. The fakes must therefore be called, so they are stubs.
Bottom-up needs drivers. It starts with the lowest modules, whose callers (higher modules) are not ready yet. The fakes must therefore call the real modules, so they are drivers.
Exercise 4
Give one advantage and one disadvantage of each integration strategy.
Show solution ↓Hide solution ↑
Solution
Advantage
Disadvantage
Top-down
An executable program is available early (and interface flaws are found early).
Poorer controllability and observability of low-level modules; stubs are costly to write and maintain.
Bottom-up
Better controllability and observability of the low-level modules.
An executable program is available only very late; writing many drivers is very expensive.
They are mirror images of each other.
Exercise 5
(Compare.) Compare top-down and bottom-up integration testing.
Show solution ↓Hide solution ↑
Solution
Both strategies integrate previously tested units incrementally, so that the team can test interfaces and interactions step by step. Top-down integration begins with the main control module. Missing lower modules are replaced with stubs, and the stubs are replaced one at a time by real implementations. It provides an executable high-level structure early and can reveal upper-level interface problems sooner. Its weaknesses are poorer access to low-level behaviour (weaker controllability and observability) and the cost of building realistic stubs.
Bottom-up integration begins with the low-level modules, combines them into clusters, and uses drivers to call them, supply test inputs and capture results. It normally gives stronger controllability and observability at the lower levels. However, the complete executable program and the high-level coordination behaviour appear late, and many drivers may be expensive to build and maintain. The choice depends on which risks need early visibility: top-down favours an early system shape and upper interfaces; bottom-up favours direct control of the low-level units.
Exercise 6
(Explain why.) Explain why passing unit tests is insufficient evidence that the complete system works.
Show solution ↓Hide solution ↑
Solution
Because unit tests only establish the behaviour of each component within its own boundaries. They run one unit at a time, often with stubs, drivers, a controlled starting state and direct observation of its outputs. They do not show that the real components communicate correctly once they are combined.
When units are combined, new risks appear: interface and protocol mismatches, incompatible data formats, accumulated precision errors (0.9 × 0.9 × 0.9 = 0.729), timing and synchronization failures such as race conditions, and contention for shared resources. Integration testing examines exactly these interactions; function testing then checks the externally specified functions, and system testing checks the complete product against its objectives, where independent testers or IV&V can expose assumptions the whole development team shares, at extra cost. Therefore successful unit testing is necessary, but it cannot replace integration, function, system or acceptance testing.