Chapter 3: Test Design Techniques

Introduction

Test design techniques help create effective test cases systematically. This chapter covers both black-box (specification-based) and white-box (structure-based) techniques.

Black-Box Testing Techniques

Testing based on specifications without knowledge of internal code.

1. Equivalence Partitioning (EP)

Divide input domain into partitions where all values should behave similarly.

Example: Age Validation

Valid age: 18-65
Invalid: <18, >65

Partitions:
1. Invalid (< 18): e.g., 10
2. Valid (18-65): e.g., 30
3. Invalid (> 65): e.g., 70
def test_age_validation():
    # Test one value from each partition
    assert validate_age(10) == False  # Partition 1
    assert validate_age(30) == True   # Partition 2
    assert validate_age(70) == False  # Partition 3

2. Boundary Value Analysis (BVA)

Test at the boundaries between partitions.

For range 18-65:
Boundaries: 17, 18, 65, 66

Test cases:
- 17 (just below min)
- 18 (min valid)
- 65 (max valid)
- 66 (just above max)
def test_age_boundaries():
    assert validate_age(17) == False  # Below minimum
    assert validate_age(18) == True   # At minimum
    assert validate_age(65) == True   # At maximum
    assert validate_age(66) == False  # Above maximum

3. Decision Tables

Test different combinations of conditions.

Example: Discount Calculator

Conditions:
- Is Member? (Y/N)
- Purchase > $100? (Y/N)

Actions:
- 20% discount (Member + >$100)
- 10% discount (Member + ≤$100)
- 5% discount (Not Member + >$100)
- 0% discount (Not Member + ≤$100)
def test_discount_decision_table():
    # Rule 1: Member + >$100 → 20%
    assert calculate_discount(is_member=True, amount=150) == 20
    
    # Rule 2: Member + ≤$100 → 10%
    assert calculate_discount(is_member=True, amount=50) == 10
    
    # Rule 3: Not Member + >$100 → 5%
    assert calculate_discount(is_member=False, amount=150) == 5
    
    # Rule 4: Not Member + ≤$100 → 0%
    assert calculate_discount(is_member=False, amount=50) == 0

4. State Transition Testing

Test system behavior across different states.

stateDiagram-v2
    [*] --> Idle
    Idle --> Playing: Play
    Playing --> Paused: Pause
    Paused --> Playing: Resume
    Playing --> Stopped: Stop
    Paused --> Stopped: Stop
    Stopped --> [*]
def test_media_player_states():
    player = MediaPlayer()
    
    # Initial state
    assert player.state == "Idle"
    
    # Idle → Playing
    player.play()
    assert player.state == "Playing"
    
    # Playing → Paused
    player.pause()
    assert player.state == "Paused"
    
    # Paused → Playing
    player.resume()
    assert player.state == "Playing"

White-Box Testing Techniques

Testing based on internal code structure.

Statement Coverage

Execute every line of code at least once.

def calculate_price(quantity, is_wholesale):
    price = quantity * 10  # Line 1
    if is_wholesale:       # Line 2
        price *= 0.8       # Line 3
    return price           # Line 4

# Test for 100% statement coverage
def test_statement_coverage():
    # Test case 1: Execute lines 1, 2 (false), 4
    calculate_price(5, False)
    
    # Test case 2: Execute lines 1, 2 (true), 3, 4
    calculate_price(5, True)
    # All statements covered!

Branch/Decision Coverage

Test all possible outcomes of decisions (if/else, loops).

def process_order(amount, has_coupon):
    if amount > 100:           # Decision 1
        discount = 10
    else:
        discount = 0
        
    if has_coupon:             # Decision 2
        discount += 5
    
    return amount - discount

# Test for 100% branch coverage
def test_branch_coverage():
    # D1: True, D2: True
    assert process_order(150, True) == 135
    
    # D1: True, D2: False
    assert process_order(150, False) == 140
    
    # D1: False, D2: True
    assert process_order(50, True) == 45
    
    # D1: False, D2: False
    assert process_order(50, False) == 50

Choosing the Right Technique

Situation Recommended Technique
Testing inputs Equivalence Partitioning + BVA
Complex business rules Decision Tables
Sequential processes State Transition
Code coverage goals White-box techniques
Unknown internals Black-box techniques

Key Takeaways

  1. āœ… Black-box: Test without knowing code internals
  2. āœ… White-box: Test based on code structure
  3. āœ… Combine techniques for thorough testing
  4. āœ… BVA finds many defects at boundaries
  5. āœ… 100% code coverage ≠ bug-free code

Complete Lab 3 to practice these techniques!