Theory is valuable, but the real test of your EP and BVA skills is applying them to a complete, realistic feature. In this lesson, you will work through a full case study — designing a test matrix for a user registration form with five fields, each with its own validation rules. The result is a professional-grade test matrix that you could present in a sprint planning meeting, use as the basis for test automation, or include in a test plan as evidence of systematic test design.
Case Study — Complete EP + BVA Test Matrix for a Registration Form
The registration form has five fields with the following requirements:
# Registration form requirements
requirements = {
"Username": "3-20 alphanumeric characters, must start with a letter, unique",
"Email": "Valid RFC 5322 format, unique in the system",
"Age": "Integer, 18-120",
"Password": "8-64 characters, 1 uppercase, 1 lowercase, 1 digit, 1 special (!@#$%)",
"Country": "Must select from list of 195 countries",
}
# ── EP + BVA for each field ──
username_tests = [
{"id": "U01", "value": "ab", "type": "BVA", "expected": "Error: min 3 chars"},
{"id": "U02", "value": "abc", "type": "BVA", "expected": "Valid (at minimum)"},
{"id": "U03", "value": "abcd", "type": "BVA", "expected": "Valid"},
{"id": "U04", "value": "a" * 19, "type": "BVA", "expected": "Valid"},
{"id": "U05", "value": "a" * 20, "type": "BVA", "expected": "Valid (at maximum)"},
{"id": "U06", "value": "a" * 21, "type": "BVA", "expected": "Error: max 20 chars"},
{"id": "U07", "value": "1alice", "type": "EP-neg", "expected": "Error: must start with letter"},
{"id": "U08", "value": "alice bob", "type": "EP-neg", "expected": "Error: alphanumeric only"},
{"id": "U09", "value": "", "type": "EP-neg", "expected": "Error: required"},
{"id": "U10", "value": "existinguser","type": "EP-neg", "expected": "Error: username taken"},
]
age_tests = [
{"id": "A01", "value": 17, "type": "BVA", "expected": "Error: must be 18+"},
{"id": "A02", "value": 18, "type": "BVA", "expected": "Valid (at minimum)"},
{"id": "A03", "value": 19, "type": "BVA", "expected": "Valid"},
{"id": "A04", "value": 119, "type": "BVA", "expected": "Valid"},
{"id": "A05", "value": 120, "type": "BVA", "expected": "Valid (at maximum)"},
{"id": "A06", "value": 121, "type": "BVA", "expected": "Error: max 120"},
{"id": "A07", "value": "", "type": "EP-neg", "expected": "Error: required"},
{"id": "A08", "value": "abc", "type": "EP-neg", "expected": "Error: enter a number"},
{"id": "A09", "value": -1, "type": "EP-neg", "expected": "Error: must be 18+"},
{"id": "A10", "value": 25.5, "type": "EP-neg", "expected": "Error: whole number"},
]
password_tests = [
{"id": "P01", "value": "Abcde1!", "type": "BVA", "expected": "Error: min 8 chars"},
{"id": "P02", "value": "Abcdef1!", "type": "BVA", "expected": "Valid (at minimum 8)"},
{"id": "P03", "value": "A"*58 + "bcde1!", "type": "BVA", "expected": "Valid (at maximum 64)"},
{"id": "P04", "value": "A"*59 + "bcde1!", "type": "BVA", "expected": "Error: max 64 chars"},
{"id": "P05", "value": "abcdef1!", "type": "EP-neg", "expected": "Error: need uppercase"},
{"id": "P06", "value": "ABCDEF1!", "type": "EP-neg", "expected": "Error: need lowercase"},
{"id": "P07", "value": "Abcdefg!", "type": "EP-neg", "expected": "Error: need digit"},
{"id": "P08", "value": "Abcdefg1", "type": "EP-neg", "expected": "Error: need special char"},
]
# Summary
total_tests = len(username_tests) + len(age_tests) + len(password_tests)
# (email and country tests would add ~10 more each)
print("Registration Form — EP + BVA Test Matrix")
print("=" * 70)
for field_name, tests in [("Username", username_tests),
("Age", age_tests), ("Password", password_tests)]:
print(f"\n {field_name} ({len(tests)} tests)")
print(f" {'ID':<5} {'Type':<8} {'Value':<22} {'Expected'}")
print(f" {'-'*65}")
for t in tests:
val_str = str(t['value'])
if len(val_str) > 20:
val_str = val_str[:17] + "..."
print(f" {t['id']:<5} {t['type']:<8} {val_str:<22} {t['expected']}")
print(f"\n\nTotal single-field tests: {total_tests} (+ ~20 for email and country)")
print(f"Multi-field pairwise combinations: ~15-20 additional tests")
print(f"Grand total: approximately {total_tests + 20 + 18} test cases for full coverage")
Common Mistakes
Mistake 1 — Creating the test matrix but not reviewing it with the team
❌ Wrong: Designing 70 test cases in isolation and executing them without showing the matrix to developers or the product owner.
✅ Correct: Sharing the matrix in sprint planning or the Three Amigos session. Developers can proactively add validation for boundary cases they see in the matrix. Product owners can confirm expected error messages. The matrix becomes a shared quality contract.
Mistake 2 — Treating the matrix as static after initial creation
❌ Wrong: Creating the matrix once and never updating it when requirements change.
✅ Correct: Updating the matrix whenever a requirement changes, a new validation rule is added, or a production defect reveals a gap. The matrix is a living document that evolves with the feature.