Why partitions beat guesses
Guessing produces tests that cluster in the comfortable middle: 25, 30, 42, 50. Those four tests exercise one partition four times and no boundary at all. Equivalence partitioning starts from a different assumption, that the software treats all values within a class the same way, so one value per class is enough, and the effort saved goes into the edges. Boundary value analysis then targets the specific place where developers make errors: the comparison operator. A > that should be >= fails at exactly one value, and only a boundary test reaches it. The two techniques are the first pair in every testing techniques syllabus for a reason: they are cheap, teachable and they find real defects.
The worked example: an age field accepting 18 to 65
The rule, as written in the story: applicants must be between 18 and 65 to open an account. The field is a text box on a web form, posted as a string to an API that parses it to an integer. That last detail matters, because it means non-numeric and empty inputs are real partitions, not theoretical ones. Everything below builds this one example through to a case list you could hand to a developer.
Write the rule down exactly, with inclusivity
Ask whether 18 and 65 themselves are valid. The story says between, which is ambiguous. Confirm with the product owner and record it: 18 to 65 inclusive. Half of all boundary defects come from this question never being asked.
Identify the valid partition
Every integer from 18 to 65 should be accepted and behave identically. That is one class. If the system treats 18 to 20 differently (a youth product, say), that is a second valid class and you split it now.
Identify the invalid partitions
Integers below 18 (too low), integers above 65 (too high), input that is not an integer at all (letters, decimals, symbols), and empty or whitespace input. Four invalid classes. Some teams add a fifth for negative numbers when the parser treats a minus sign differently from a letter.
Pick one representative per partition
Choose values from the middle of each class so the test is clearly about the class, not the edge: 40 for valid, 10 for too low, 80 for too high, the string abc for non-numeric, and an empty string. Five tests so far.
Add the boundary values
For each edge between a valid and invalid class, test the last valid and first invalid value: 17 and 18 at the lower edge, 65 and 66 at the upper edge. That is the two-value approach, four tests. Add 19 and 64 for the three-value approach.
Write the expected result for every value
A test without an expected result is not a test. For each value record accept or reject, and for rejects the exact message the user should see. If the error message differs between too low and non-numeric, that difference is itself a check.
Combine with other inputs using a decision table
Age rarely stands alone. If the form also has a membership tier, list the age partitions against the tier values and mark which combinations matter. The section below shows how this keeps the case count small.
| Partition | Range | Representative | Boundary values | Expected result |
|---|---|---|---|---|
| Valid | 18 to 65 | 40 | 18, 65 (plus 19, 64 for three-value) | Accepted, account opens |
| Too low | 0 to 17 | 10 | 17 | Rejected, applicants must be at least 18 |
| Too high | 66 and above | 80 | 66 | Rejected, applicants must be 65 or under |
| Non-numeric | letters, decimals, symbols | abc | 18.5 (decimal at the edge) | Rejected, enter a whole number |
| Empty | empty or whitespace | (blank) | none | Rejected, age is required |
Two-value versus three-value boundaries
The two-value approach tests the boundary itself and the nearest value on the other side: 17 and 18, 65 and 66. It catches a comparison that is off by one in either direction. The three-value approach adds the nearest value on the same side: 19 and 64, so the pattern becomes 17, 18, 19 and 64, 65, 66. Its extra value catches the rarer defect where the boundary is right but the value beside it is handled by a different branch, which happens when a developer writes a special case for the boundary instead of a range check.
- Use two-value when the code is a simple range check and the build runs the tests in seconds anyway.
- Use three-value when the boundary is contractual or regulated (an age of consent, a tax threshold), or when the implementation is known to special-case the edge.
- Whichever you choose, apply it consistently across the suite so that reviewers know what a missing value means.
Combining with decision tables
Suppose the same form asks for a membership tier, standard or premium, and premium members over 60 get a lower fee. Testing every age value against every tier multiplies the count for no gain. Instead, take the age partitions (now six, because the rule splits the valid range at 60) as one condition and the tier as another, and build a decision table.
| Rule | Age partition | Tier | Action |
|---|---|---|---|
| R1 | below 18 | any | Reject |
| R2 | 18 to 60 | standard | Accept, standard fee |
| R3 | 18 to 60 | premium | Accept, premium fee |
| R4 | 61 to 65 | standard | Accept, standard fee |
| R5 | 61 to 65 | premium | Accept, reduced premium fee |
| R6 | above 65 | any | Reject |
How many cases you end up with, and why that is fewer than guessing
Count it. Five partitions give five representative tests. Two-value boundaries add 17, 18, 65 and 66, but 18 and 65 can double as the valid representative, so the honest total is 5 plus 4 minus overlap, or 9 to 11 tests. Three-value adds 19 and 64 for 13. The decision table adds two rules at the 60 to 61 split and the tier combinations, bringing a complete set for the whole form to roughly 18 tests. A tester guessing tends to produce 20 to 30 tests that repeat the valid middle and miss at least one of 17, 66 and 18.5. The technique gives fewer tests with more coverage, and every test has a reason you can defend in a review, which is what an auditor or a new team member needs.
In published field data on input-validation defects, roughly two thirds sit at a boundary rather than inside a partition. That is why boundary tests, not representative tests, are the ones you never cut when time is short.
Common mistakes
- Treating the specification's example values as the partitions. The spec says 18 to 65; the partitions are derived from that rule, not copied from the acceptance criteria.
- Forgetting the invalid partitions that are not numbers. Empty, whitespace, decimals and very long strings each have a path through the parser.
- Testing 18 and 65 but not 17 and 66. The valid boundary proves the range is wide enough; the invalid boundary proves it is not too wide.
- Picking a boundary value as the representative. If 18 fails you cannot tell whether the class or the edge is broken.
- Assuming output partitions match input partitions. A fee calculation may have its own boundaries at rounding points that no input value reveals until you look at the output.
- Never revisiting the partitions when the rule changes. A move from 65 to 67 invalidates four tests and creates four new ones; a suite that still passes is a suite nobody updated, a pattern discussed in flaky tests.
Common questions
Is equivalence partitioning only for numeric inputs?
No. Any input with classes of equivalent behavior partitions: file types, user roles, country codes, string lengths. Boundaries exist wherever there is an order, such as length 0, 1, 255 and 256 for a text field.
Do I test one value per partition or several?
One is the theory. In practice two per valid partition is a cheap insurance against a partition that was defined too broadly, but more than that is repetition.
Should invalid values be tested one at a time?
Yes. If you submit an invalid age and an invalid tier together, the first validation error masks the second. One invalid input per test, all other inputs valid.
What about output partitions?
Apply the same thinking to outputs: if a fee can be 0, 5 or 15 units, design inputs that produce each output and the boundaries between them. This often exposes rounding defects.
How do these techniques relate to ISTQB?
Both are core black-box techniques in the ISTQB Foundation syllabus, which describes two-value and three-value boundary analysis and expects candidates to derive partitions from a rule like the one in this example.
Can the technique be automated?
The test design is a human activity, but the resulting values make ideal parameterized tests in any unit or API test framework, one table row per test.
Sources
- ISO/IEC/IEEE 29119-4:2021, Software testing, Part 4: Test techniques
- ISTQB Certified Tester Foundation Level (CTFL) v4.0 syllabus and overview
- ISTQB Glossary of software testing terms
Further reading named in the text
- Lee Copeland, A Practitioner's Guide to Software Test Design (Artech House, 2004)
- Boris Beizer, Black-Box Testing: Techniques for Functional Testing of Software and Systems (Wiley, 1995)
- Glenford J. Myers, Corey Sandler, Tom Badgett, The Art of Software Testing, 3rd edition (Wiley, 2011)
This guide is part of the software testing techniques hub. It is best read alongside black box vs white box testing and test coverage, which cover the neighbouring questions.