Pairwise Testing¶
Pairwise testing, also called all-pairs or 2-way combinatorial testing, covers every pair of parameter values instead of every full combination. It exists because configuration spaces explode and because most interaction defects involve only two factors.
The explosion it solves¶
| Parameter | Values |
|---|---|
| Browser | Chrome, Firefox, Safari |
| Operating system | Windows, macOS, Linux |
| Language | English, German, Japanese |
| Account type | Free, Pro, Enterprise |
| Payment method | Card, Transfer, Invoice |
Full coverage is 3 x 3 x 3 x 3 x 3 = 243 configurations. Every pair of values from every pair of parameters can be covered in around 15, roughly a 94% reduction with most of the defect-finding power retained.
graph LR
FULL["Exhaustive: 243 configurations"] --> COST[Days of runtime, unmaintainable]
PAIR["Pairwise: about 15 configurations"] --> VALUE[Every two-factor interaction exercised]
Why pairs are enough¶
Empirical studies of defect reports across several domains found that the large majority of interaction failures are triggered by a single parameter value or by one pair. Three-way and higher interactions exist but are a small tail.
graph TD
D[Interaction defects] --> S["Single value: the largest share"]
D --> P["Two-value interaction: most of the remainder"]
D --> T["Three-way and higher: a small tail"]
So pairwise is not a compromise on principle, it is aimed at where the defects actually are. Where the tail matters, safety-critical or high-value paths, raise the strength to 3-way for the parameters involved rather than for all of them.
Producing the set¶
Do not build the array by hand. Generators exist for every language and produce a covering array in seconds. The work that stays human is:
| Input to the generator | Why it matters |
|---|---|
| Parameters and values | Values usually come from equivalence partitioning, not from listing every possible value |
| Constraints | Impossible combinations, such as Safari on Linux, must be excluded or the suite tests nonsense |
| Seeded rows | Known-important configurations, such as the most common customer setup, should be forced into the set |
| Strength | 2 by default, higher for a critical subset |
Constraints are the step most often skipped, and skipping it produces a tidy array full of configurations that cannot exist.
What it does not do¶
- It is not an oracle. It selects configurations. Each still needs expected results.
- It ignores order. If behaviour depends on sequence, use state transition testing.
- It assumes parameters are independent. Where one parameter changes the meaning of another, model that with a decision table instead.
- It misses three-way defects by design. That is the accepted trade, and it should be a stated decision rather than an accident.
Where it pays off¶
| Good fit | Poor fit |
|---|---|
| Browser, OS and device matrices | Business rules with dependent conditions |
| Feature flag combinations | Behaviour that depends on history |
| Installation and configuration options | Single-input validation, where partitions and boundaries suffice |
| API parameters that are genuinely independent | Anything with fewer than three parameters, where full coverage is cheap |
The feature flag case is the modern one worth naming: a system with twenty independent flags has more than a million states, is shipped daily, and is almost never tested in combination.
Check Your Understanding¶
Why does covering all pairs find most interaction defects despite testing a small fraction of combinations?
Which step is most often skipped when generating a pairwise set, and what does it cost?