Equivalence partitioning and boundary value analysis exist to cut the number of test cases without losing the places where defects actually appear. They are used as a pair.

What matters more in practice is using them during specification review rather than during test execution. Writing out the boundaries reliably surfaces values whose behaviour the specification never defines. Removing those before implementation changes how much rework you face later.

This article covers both techniques and the boundaries teams most often miss—character counts, dates, and full-width digits.

Equivalence partitioning

Group inputs that should produce the same result, then pick one representative from each group.

For an age field accepting 0 to 120:

Class Range Representative
Valid 0–120 30
Invalid (below) −1 and lower −5
Invalid (above) 121 and higher 130

The justification is that any value within a class exercises the same code path. If 30 passes, 31 and 32 will too.

When that assumption breaks, split the class again. Add a rule such as “under 20 cannot purchase” and the valid class must divide into 0–19 and 20–120.

 

Boundary value analysis

Target the edges of each class. Defects cluster at boundaries, not in the middle of ranges—< written where <= belonged, or i < n confused with i <= n.

-1 | 0 ... 120 | 121
   ↑            ↑
lower bound  upper bound

 

Two-value or three-value?

There are two conventions. Agree on one as a team, or case counts vary by author.

Values taken For 0–120 Cases
Two-value The boundary and its outside neighbour −1, 0, 120, 121 4
Three-value The boundary and both neighbours −1, 0, 1, 119, 120, 121 6

Two-value is normally sufficient. Reserve three-value for boundaries with unusually complex logic, or where a mistake is very costly—payment limits, for instance.

 

How the two fit together

Partitioning decides where to look; boundary analysis decides which values to enter. Never the other way round.

  • Equivalence partitioning: divides the input space → identifies what needs testing
  • Boundary value analysis: locates each class edge → fixes the actual values

Together, one representative plus the boundaries covers the whole range. You never need all 121 values.

 

Example 1: an age field

Specification: age accepted between 0 and 120.

Value Expected Technique
−1 Error Boundary
0 OK Boundary
30 OK Partitioning (representative)
120 OK Boundary
121 Error Boundary

Do not stop here. Numeric boundaries alone leave these gaps in production:

Input Is it in the specification?
Empty Is the field required or optional?
Full-width digits “30” Accept, convert, or reject?
Decimal “30.5” Integers only?
Surrounding spaces ” 30 “ Trimmed?
Text “abc” What is the error message?

Show this table to a developer and several rows will turn out to be undecided. Resolving them before implementation is the real value of the technique.

 

Example 2: a coupon threshold

Specification: apply the coupon when the order total is 1,000 yen or more.

Value Expected
999 Not applied
1,000 Applied
1,001 Applied

“1,000 or more” includes exactly 1,000. “More than 1,000” does not. That distinction becomes >= versus > in the implementation.

For money, there is more hiding in that one sentence:

  • Is the comparison before or after tax? Very often unstated
  • Does it include shipping?
  • Is it the total before or after other discounts?

 

Example 3: password length

Specification: passwords are 8 to 16 characters.

Length Expected
7 Error
8 OK
16 OK
17 Error

With character counts, the question becomes what counts as one character. This is the most frequently missed area in practice.

  • Emoji: JavaScript’s length counts many emoji as two (surrogate pairs)
  • Combining characters: a base letter plus a diacritic counts as two
  • Newlines: \r\n is two characters, and which is sent varies by OS
  • Non-ASCII: with a byte-based limit, a CJK character is three bytes in UTF-8

When the front end and the server define “16 characters” differently, input passes validation and then fails on save. Always include one test case containing an emoji.

 

Dates need special attention

Dates have boundaries in places numbers do not. Checking only the ends of the range misses them.

Boundary Example
End of month 31 January, 30 April
Leap day 2024-02-29 (2100 is not a leap year)
Year rollover 31 December → 1 January
Midnight 23:59:59 → 00:00:00
Time zones Hours where UTC and local date differ

A relative rule such as “30 days from today” produces different results depending on when you run it. Write those tests with a fixed clock.

 

Change one invalid value at a time

This is about how you write cases, not the technique itself. Never combine several invalid values.

Bad:  age = -1, name empty, email malformed, all in one case
      → it errors, but you cannot tell which field caught it

Good: keep every other field valid and set only age to -1
      → confirms the age validation is actually running

 

Combine invalid values and the first failure short-circuits the rest, so you cannot tell whether the other checks exist. A missing age validation goes unnoticed.

Valid values, by contrast, can be combined freely—one all-valid case is the norm.

 

Partition the output too

Looking only at inputs hides output branches.

If shipping is “0, 300 or 550 yen depending on the order total”, there are three output classes. Beyond the input boundaries, confirm all three shipping values actually occur.

Where several conditions interact, decision table testing organises the combinations more reliably.

 

Cautions

Do not create too many cases

The point of partitioning is reduction. Taking two or three values from the same class means either the classes are wrong or you have lost sight of the goal.

Get the boundaries right

For “display up to 100 items”, the boundaries are 100 and 101—and also 0 and 1. The empty-list state is one of the most commonly unimplemented cases.

Know what these techniques do not cover

Situation Technique
Business logic with interacting conditions Decision table testing
Screens and states that transition State transition testing
Too many configuration combinations Pairwise testing

These two techniques address the range of a single input. Relationships between fields belong elsewhere.

 

Summary

  • Partitioning decides where to look; boundary analysis decides which values
  • Two-value boundaries are usually enough. Agree as a team whether to use three
  • Do not stop at numeric boundaries. Check empty, full-width digits, decimals and surrounding spaces
  • “1,000 or more” includes 1,000. Whether it is pre- or post-tax is usually unstated
  • Character counts change with emoji and combining characters. Include one such case
  • Date boundaries: month end, leap day, year rollover, time zones
  • One invalid value per case. Valid values may be combined
  • Partition outputs as well as inputs
  • Zero-item and empty-list states are boundaries, and frequently unimplemented

The real payoff is finding gaps in the specification, not executing tests. Using these upstream is covered in QA in waterfall development.

ABOUT ME
りん
On this blog, I mainly share information about web development and programming, along with my daily thoughts and what I’ve learned. I aim to create a blog that lets readers enjoy both technology and everyday life, so I also include topics about daily experiences, books, and gourmet. I’d be delighted if you could drop by casually and find something useful or enjoyable here.