If equivalence partitioning tells you which groups to test, boundary value analysis tells you which specific values within those groups are most likely to reveal defects. Decades of testing experience have shown that bugs cluster at the boundaries between partitions — the exact points where valid becomes invalid, where one price tier ends and another begins, where a counter resets. Off-by-one errors, incorrect comparison operators, and missing edge-case handling are all boundary defects, and they are among the most common bugs in software.
Boundary Value Analysis — Probing the Edges
BVA selects test values at the exact boundary and immediately adjacent to it on both sides. For a range of 18-65, the boundary values are 17, 18, 19 (lower boundary) and 64, 65, 66 (upper boundary). These six values catch the vast majority of boundary-related defects.
# BVA applied to the insurance age field (valid range 18-65)
# Combined with EP partitions from the previous lesson
def bva_values(min_val, max_val):
return [
{"value": min_val - 1, "label": "Just below min", "expected": "Invalid"},
{"value": min_val, "label": "At minimum", "expected": "Valid"},
{"value": min_val + 1, "label": "Just above min", "expected": "Valid"},
{"value": max_val - 1, "label": "Just below max", "expected": "Valid"},
{"value": max_val, "label": "At maximum", "expected": "Valid"},
{"value": max_val + 1, "label": "Just above max", "expected": "Invalid"},
]
age_boundaries = bva_values(18, 65)
print("Boundary Value Analysis — Age Field (Valid: 18-65)")
print("=" * 55)
print(f"{'Value':>6} {'Label':<20} {'Expected':<10}")
print("-" * 55)
for b in age_boundaries:
print(f"{b['value']:>6} {b['label']:<20} {b['expected']:<10}")
# Real-world example: applying BVA to a multi-tier discount system
# 0-99 items: no discount
# 100-499 items: 10% discount
# 500+ items: 25% discount
print("\n\nBVA — Quantity Discount System")
print("=" * 55)
tier_boundaries = [
# Tier 1 → Tier 2 boundary
{"value": 99, "label": "Below Tier 2 boundary", "expected": "0% discount"},
{"value": 100, "label": "At Tier 2 start", "expected": "10% discount"},
{"value": 101, "label": "Above Tier 2 start", "expected": "10% discount"},
# Tier 2 → Tier 3 boundary
{"value": 499, "label": "Below Tier 3 boundary", "expected": "10% discount"},
{"value": 500, "label": "At Tier 3 start", "expected": "25% discount"},
{"value": 501, "label": "Above Tier 3 start", "expected": "25% discount"},
# Lower edge
{"value": 0, "label": "Zero items", "expected": "0% / empty cart"},
{"value": 1, "label": "Minimum order", "expected": "0% discount"},
]
print(f"{'Qty':>5} {'Label':<25} {'Expected':<15}")
print("-" * 55)
for b in tier_boundaries:
print(f"{b['value']:>5} {b['label']:<25} {b['expected']:<15}")
# The classic off-by-one bug
print("\n\nWhy BVA catches bugs:")
print(" Developer writes: if quantity > 100: apply_discount(10)")
print(" Requirement says: 100+ items get 10% discount")
print(" Bug: quantity=100 gets NO discount (should get 10%)")
print(" BVA catches this: testing at value 100 (at boundary) reveals the defect")
if age > 18 instead of if age >= 18, rejecting 18-year-olds who should be eligible. Or they write if quantity > 100 instead of if quantity >= 100, denying the discount to customers ordering exactly 100 items. These subtle bugs pass every test that uses values in the middle of the range but fail at the exact boundary. BVA is specifically designed to catch this category of defect.Common Mistakes
Mistake 1 — Testing only at the boundaries and skipping values just outside
❌ Wrong: For range 18-65, testing only 18 and 65 — the minimum and maximum.
✅ Correct: Testing 17 (just below min), 18 (at min), 19 (just above min), 64 (just below max), 65 (at max), 66 (just above max) — six values that cover both edges completely.
Mistake 2 — Applying BVA only to numeric fields
❌ Wrong: “BVA is only for numbers — I cannot use it on text fields or dates.”
✅ Correct: BVA applies to any ordered set: string length (min/max characters), dates (start/end of valid range), file sizes (min/max upload), list counts (min/max items in a cart). Anywhere there is a defined boundary, BVA applies.