What Is Equivalence Partitioning?
Equivalence Partitioning (EP) is one of the most fundamental black-box test design techniques. The core idea is simple but powerful: instead of testing every possible input, you divide the input domain into equivalence classes — groups of values that the system should treat identically.
If the system handles one value from a class correctly, it should handle all values in that class correctly. This assumption lets you reduce thousands of potential test cases to a manageable number.
Why It Matters
Consider a field that accepts integers from 1 to 10,000. Testing every value would require 10,000 test cases — plus invalid values. With equivalence partitioning, you need as few as 3 test cases:
| Class | Range | Representative | Expected |
|---|---|---|---|
| Invalid (low) | < 1 | -5 | Error |
| Valid | 1–10,000 | 4,500 | Accept |
| Invalid (high) | > 10,000 | 20,000 | Error |
You’ve gone from 10,000+ tests to 3, while still covering the core logic.
The Process
Step 1: Identify the input domain. Look at the specification to understand what the input field or parameter accepts.
Step 2: Divide into equivalence classes. Group values that should be processed identically. Each class should be mutually exclusive — a value belongs to exactly one class.
Step 3: Select representatives. Pick one value from each class. Avoid boundary values — those are covered by a separate technique (Boundary Value Analysis).
Step 4: Write test cases. Create one test case per representative value.
Types of Equivalence Classes
Valid classes contain values the system should accept and process normally.
Invalid classes contain values the system should reject or handle as errors.
A common mistake is to focus only on valid classes. Invalid classes often reveal more defects because error handling is frequently under-tested.
Applying EP to Different Data Types
Equivalence partitioning works with any input type:
Numeric ranges:
- Age field (18-65): classes are
<18,18-65,>65
String inputs:
- Username (3-20 chars, alphanumeric): classes include valid length + valid chars, too short, too long, special characters, empty string
Enumerations:
- Payment method (credit card, debit card, PayPal): each option is its own valid class; an unsupported method is an invalid class
Boolean:
- Checkbox (checked/unchecked): two valid classes
Real-World Example: E-Commerce Discount
A store applies discounts based on cart total:
| Cart Total | Discount |
|---|---|
| $0 – $49.99 | 0% |
| $50 – $99.99 | 5% |
| $100 – $199.99 | 10% |
| $200+ | 15% |
Equivalence classes:
| # | Class | Representative | Expected Discount |
|---|---|---|---|
| 1 | Negative values (invalid) | -$10 | Error |
| 2 | $0 – $49.99 | $25 | 0% |
| 3 | $50 – $99.99 | $75 | 5% |
| 4 | $100 – $199.99 | $150 | 10% |
| 5 | $200+ | $300 | 15% |
Five test cases cover the entire discount logic.
Advanced Equivalence Partitioning
Multi-Parameter Partitioning
Real applications rarely have a single input. When you have multiple parameters, each parameter has its own set of equivalence classes. The challenge is combining them effectively.
Example: User registration form
| Parameter | Valid Classes | Invalid Classes |
|---|---|---|
| Age | 18-120 | <18, >120, non-numeric |
| valid format | missing @, no domain, empty | |
| Password | 8-64 chars with uppercase, lowercase, digit | too short, too long, missing required chars |
For valid class testing, create a single test case that uses one valid representative from each parameter simultaneously:
Test Case 1: Age=30, Email=user@test.com, Password=Secure1pass
Expected: Registration succeeds
For invalid class testing, vary one parameter at a time while keeping others valid:
Test Case 2: Age=15, Email=user@test.com, Password=Secure1pass
Expected: Age validation error
Test Case 3: Age=30, Email=invalid-email, Password=Secure1pass
Expected: Email validation error
This approach is called the Single Fault Assumption — testing one invalid parameter at a time to isolate which validation triggers.
Handling Output-Based Partitioning
Sometimes it’s more effective to partition based on outputs rather than inputs. If a function returns different result types, work backward:
def categorize_bmi(bmi):
if bmi < 18.5:
return "Underweight"
elif bmi < 25:
return "Normal"
elif bmi < 30:
return "Overweight"
else:
return "Obese"
Output partitions: Underweight, Normal, Overweight, Obese. Pick one input that triggers each output.
Common Pitfalls
- Missing the “empty” class. Always consider empty string, null, or zero as a separate class.
- Ignoring data types. A numeric field might receive letters — that’s a separate invalid class.
- Overlapping classes. Each value must belong to exactly one class. If classes overlap, your partitioning is wrong.
- Too few invalid classes. There are usually more invalid classes than valid ones.
Exercise: Design Equivalence Classes
Scenario: A flight booking system accepts the following inputs:
- Passengers: 1–9 (integer)
- Class: Economy, Business, First
- Trip type: One-way, Round-trip
Task: Identify all equivalence classes for each parameter and write the minimum set of test cases needed.
Hint
For Passengers: think about what happens with 0, negative numbers, 10+, decimal numbers, and non-numeric input.
For Class and Trip type: each valid option is its own class. What about an option that doesn’t exist?
Solution
Passengers:
| # | Class | Representative | Valid? |
|---|---|---|---|
| 1 | 1–9 | 4 | Valid |
| 2 | < 1 | 0 | Invalid |
| 3 | > 9 | 15 | Invalid |
| 4 | Non-integer | 2.5 | Invalid |
| 5 | Non-numeric | “abc” | Invalid |
Class:
| # | Class | Representative | Valid? |
|---|---|---|---|
| 6 | Economy | Economy | Valid |
| 7 | Business | Business | Valid |
| 8 | First | First | Valid |
| 9 | Unsupported | “Premium” | Invalid |
Trip type:
| # | Class | Representative | Valid? |
|---|---|---|---|
| 10 | One-way | One-way | Valid |
| 11 | Round-trip | Round-trip | Valid |
| 12 | Unsupported | “Multi-city” | Invalid |
Minimum test cases:
Valid (all valid representatives combined):
TC1: Passengers=4, Class=Economy, Trip=One-way → Success
TC2: Passengers=4, Class=Business, Trip=Round-trip → Success
TC3: Passengers=4, Class=First, Trip=One-way → Success
Invalid (one invalid at a time):
TC4: Passengers=0, Class=Economy, Trip=One-way → Error
TC5: Passengers=15, Class=Economy, Trip=One-way → Error
TC6: Passengers=2.5, Class=Economy, Trip=One-way → Error
TC7: Passengers="abc", Class=Economy, Trip=One-way → Error
TC8: Passengers=4, Class="Premium", Trip=One-way → Error
TC9: Passengers=4, Class=Economy, Trip="Multi-city" → Error
Total: 9 test cases covering 12 equivalence classes.
Pro Tips
- Combine EP with Boundary Value Analysis. EP reduces the input space; BVA then focuses on the edges of each class. Together, they form the backbone of specification-based testing.
- Document your partitions. Before writing test cases, list all equivalence classes in a table. This makes reviews easier and ensures completeness.
- Revisit partitions when specs change. A change in the valid range or a new input type means new equivalence classes.
- Use EP for API parameters too. Every API endpoint parameter has valid and invalid classes — apply the same technique to request bodies, query parameters, and headers.