Real-World Case Study — EP and BVA Applied to a Complete Registration Form

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")
Note: This case study produces approximately 50 single-field tests and 15-20 multi-field pairwise tests for a 5-field form — roughly 70 test cases total. This might seem like a lot, but consider the alternative: without systematic EP and BVA, a tester might write 15-20 ad hoc tests and miss critical boundaries, negative scenarios, and field interaction defects. The structured approach takes more planning time upfront but catches significantly more defects and provides traceable evidence that every requirement was tested.
Tip: Present your test matrix in a spreadsheet with columns for Test ID, Field, Input Value, Technique (EP/BVA/Pairwise), Expected Result, and Requirement Traced. This format is directly importable into test management tools like TestRail, Zephyr, or qTest. It also serves as documentation during code reviews — developers can see exactly which boundary values will be tested and proactively handle them in their validation code.
Warning: A test matrix is a plan, not a guarantee. Even a comprehensive EP + BVA matrix will not catch every defect — it catches the defects that structured techniques are designed to find (boundary errors, partition-related failures, type handling issues). Supplement your structured matrix with exploratory testing sessions that use creativity and domain knowledge to find the defects that no formula can predict.

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.

🧠 Test Yourself

After creating a complete EP + BVA test matrix for a 5-field registration form, what additional testing technique should you apply to catch defects the matrix cannot predict?