Equivalence Partitioning

4 min read

Equivalence partitioning is the most foundational test design technique you will use. It takes the infinite space of possible inputs and chops it into a small number of buckets that, for testing purposes, behave identically. Once you understand the buckets, you only need to test one input from each — and you can stop guessing whether you have "tested enough."

The core idea

Imagine a form field that accepts integers between 1 and 100. The input space is technically infinite — every number, every string, every emoji. But for the purpose of testing, all valid integers in that range will be handled by the same code path. So will all integers above 100. So will all integers below 1. So will all non-numeric input.

Each of those groups is an equivalence class. The whole point of partitioning is to identify them and then test one representative from each, instead of trying to enumerate every possible input.

For our 1-to-100 field, three classes are obvious:

  • Below the range (e.g., -5, 0)
  • Inside the range (e.g., 50)
  • Above the range (e.g., 101, 999999)

A real test plan would also include an "invalid type" class — letters, symbols, empty input, very long strings. That makes four classes. With four well-chosen test cases you can be confident you have covered the meaningful behaviour of this field, instead of writing forty cases that all live in the "valid" bucket.

A worked example: a discount code field

Consider a discount field that accepts:

  • A code 6 to 12 characters long, alphanumeric only.
  • An empty value (no discount).

The equivalence classes might be:

ClassExample
Empty (valid: no discount)(blank)
Valid alphanumeric, in length rangeSPRING10
Too shortABC
Too longSUPERLONGCODE
Non-alphanumeric charactersSPRING-10
Whitespace insideSPR ING
Pure whitespace
Leading/trailing whitespace on a valid codeSPRING10

Each row deserves at least one test case. Notice we are not enumerating every length — we have one "too short" case and one "too long" case, because all overlong strings should behave the same way.

Why this is more efficient than ad-hoc testing

Without partitioning, testers fall into two patterns:

  • Over-testing. Writing dozens of cases that all belong to the same class — three different valid alphanumeric codes, four different "too short" inputs. This bloats the test suite without catching new bugs.
  • Under-testing. Forgetting whole classes — testing valid inputs and "obviously invalid" ones, but missing whitespace, special characters, or boundary conditions.

Partitioning forces the tester to explicitly enumerate the categories, which makes both gaps visible. It also makes tests easy to review: someone else can ask, "where is the test for the empty-valid class?" and the answer should be one specific test case.

Combining classes

Many features have multiple inputs that each have their own classes. A login form has username classes (valid, empty, too long, special characters) and password classes (correct, wrong, empty, expired). The full test space is the cross product, but you do not have to test every combination — usually one representative pair from each "interesting" combination is enough. Decision tables (covered later in this chapter) help when the combinations get complex.

Where it falls short

Equivalence partitioning assumes that every input in a class is genuinely equivalent. In practice, boundary values — inputs right at the edge of a class — are far more likely to break than middle-of-the-class inputs. The number 100 (the maximum allowed) is more likely to expose a bug than 47. That is why the very next lesson covers boundary value analysis, which is almost always paired with partitioning.

What you should walk away with

Partitioning turns infinite input spaces into a small, defensible set of test cases. Identify the classes, pick one example from each, and stop. The next lesson — boundary value analysis — addresses the one place this technique systematically misses bugs: the borders between classes.

// tip to track lessons you complete and pick up where you left off across devices.