Session 3.2 - Equivalence & State Table Testing

Module 3: Dynamic & Static Testing | Duration: 1 hour

Learning Objectives
  • Design efficient suites using equivalence classes and finite state tables.
  • Reduce redundant test cases while preserving defect-detection power.
  • Trace test cases from partitions and states to expected outcomes.

Concept Overview

Equivalence testing groups many similar inputs into partitions so one representative test can stand for each group. State table testing models system behavior across states and events to validate legal and illegal transitions.

Equivalence focus
Input/output domain coverage with minimum redundancy.
State table focus
Behavior over time: current state + event + condition = next state + action.
Why together
One handles data variation; the other handles sequence and lifecycle variation.

Why Efficient Test Suites Matter

Consider a simple form with three input fields. If each field accepts values in a range of 1 to 50, testing every possible combination would require 50 × 50 × 50 = 125,000 test cases. This is clearly impractical. The challenge in software testing is to find defects with the minimum number of well-chosen test cases.

The core problem: Exhaustive testing is impossible for most real systems. We need systematic methods to select a small subset of inputs that still has a high probability of finding defects.

Equivalence class testing solves this by recognizing that many input values are equivalent from the software's perspective — they exercise the same logic path and should produce the same type of result. Instead of testing every value, we test one representative from each group.

Without partitioning
A naive suite might have 30+ test cases that all exercise the same code path, wasting time without finding new defects.
With partitioning
The same coverage can be achieved with 5-8 tests by choosing one value from each distinct equivalence class.
The trade-off
Fewer tests mean faster execution, but each test must be carefully chosen to represent an entire class of behavior.

Equivalence Class Testing

Equivalence class testing (also called equivalence partitioning) divides the input domain into classes where the system is expected to behave identically for all members of a class. The key insight is: if the software handles one value in a class correctly, it will likely handle all values in that class correctly.

Formal definition: An equivalence class is a subset of the input domain such that testing any one value from the subset is equivalent to testing all values in the subset. If one test case in a class detects a defect, all other cases in the same class are expected to detect the same defect.
Design Steps
  1. Identify each input condition from the requirement (range, set of values, format, type, mandatory/optional).
  2. Create valid equivalence classes — groups of inputs that satisfy the requirement.
  3. Create invalid equivalence classes — groups of inputs that violate the requirement in a specific way.
  4. Pick one representative from each class. This single value stands for the entire class.
  5. Define expected result for each representative before execution.
  6. Execute and refine — if a class is too broad and hides internal boundaries, split it further.

Types of Equivalence Classes

Understanding how to identify valid and invalid classes is the most important skill in this technique.

Guidelines for forming equivalence classes:
Input Condition TypeValid ClassesInvalid Classes
Range (e.g., 1 to 100)One class: values within [1, 100]Two classes: values < 1, and values > 100
Specific set (e.g., Red, Green, Blue)One class for each valid valueOne class: any value not in the set
Boolean (e.g., Yes/No)One class: YesOne class: No
Format (e.g., email address)One class: correctly formatted inputsMultiple classes: missing @, missing domain, special chars, etc.
Data type (e.g., integer expected)One class: valid integersMultiple classes: floats, strings, blank, special chars
Valid class
Input obeys the requirement and should be accepted or processed normally. The system should produce correct output.
Invalid class
Input violates exactly one rule and should be rejected with a proper error message. Each invalid class should violate a different rule.
Efficiency rule
Do not test many values from the same class — they add effort without increasing defect-detection power. One representative per class is sufficient.
Important note on combining BVA with equivalence testing: After creating equivalence classes, you can strengthen the suite by adding boundary values from Session 3.1 at the edges of each class. This keeps suites compact without losing critical edge checks.

Equivalence Example: Exam Score Input

Requirement: Score must be an integer from 0 to 100 inclusive.

Class ID Class Description Representative Expected
V1Integer in [0..100]56Accept
I1Integer < 0-3Reject
I2Integer > 100101Reject
I3Non-integer numeric72.5Reject
I4Non-numeric text"A+"Reject
I5Blank input""Reject
Why 6 tests are enough: Instead of testing dozens of values, these 6 tests cover every type of input the system might receive. If the system correctly accepts 56, it will likely accept 23, 78, or any other valid integer. If it correctly rejects -3, it will likely reject -100 or -1 as well.

Worked Example: Largest of Three Numbers

Requirement (from textbook): A program reads three numbers A, B, and C with range [1, 50] and prints the largest number.

Step 1: Identify input conditions
  • A must be an integer in [1, 50]
  • B must be an integer in [1, 50]
  • C must be an integer in [1, 50]
Step 2: Form equivalence classes for each variable
VariableValid ClassInvalid Class 1Invalid Class 2
AV1: 1 ≤ A ≤ 50I1: A < 1I2: A > 50
BV2: 1 ≤ B ≤ 50I3: B < 1I4: B > 50
CV3: 1 ≤ C ≤ 50I5: C < 1I6: C > 50
Step 3: Also consider output-based equivalence classes

Since the program prints the largest number, we should also partition based on which variable is largest:

ClassConditionTest Values (A, B, C)Expected Output
O1A is largest(45, 20, 30)45
O2B is largest(10, 48, 25)48
O3C is largest(15, 22, 40)40
O4A = B = C (all equal)(25, 25, 25)25
O5A = B > C (tie for largest)(30, 30, 10)30
Key learning: This example shows that equivalence classes can be formed based on output behavior, not just input ranges. The program might have a defect that only shows when B is the largest, or when two inputs are tied. Output-based partitioning catches these.

State Table Based Testing

Some software behaviors depend not only on the current input but also on the history of previous inputs — that is, on the current state of the system. State table testing uses the concept of a Finite State Machine (FSM) to model and test such behavior.

When to use state table testing: Use this technique whenever the system's response to an input depends on what happened before. Common examples include login attempts, shopping cart workflows, order processing, ATM transactions, and game logic.
State Table Structure

(Current State, Event, Guard/Condition) → (Action, Next State)

  • State: the current mode or situation of the system (e.g., Idle, Locked, Active, Blocked).
  • Event: an input or trigger that occurs (e.g., Enter PIN, Click Submit, Timeout).
  • Guard/Condition: an optional condition that must be true for the transition to happen (e.g., PIN is correct).
  • Action: the system's response when the transition occurs (e.g., display message, update record, send alert).
  • Next State: the state the system moves to after the transition.

State Graphs & Diagrams

States are represented by nodes (circles). With the help of nodes and transition links between them, a state transition diagram (or state graph) is prepared. A state graph is the pictorial representation of a Finite State Machine (FSM).

Purpose of a state graph: It depicts the states that a system or its components can assume. It shows the events or circumstances that cause or result from a change from one state to another.
Nodes
Each circle represents a distinct state of the system (e.g., Idle, Authenticated, Blocked).
Arrows (transitions)
Each arrow shows a possible transition, labeled with the event/condition that triggers it and the action performed.
Initial & final states
The starting state is usually marked with an incoming arrow from nowhere. Terminal states may be double-circled.
How to derive test cases from a state graph:
  1. Identify all states and list them.
  2. Identify all transitions (arrows) and list event + condition for each.
  3. Write at least one test case that traverses each transition (transition coverage).
  4. Write tests for illegal transitions — events that should NOT cause a state change.
  5. Test sequences of transitions to cover common workflows (path coverage).

State Table Conventions

State graphs of larger systems may not be easy to understand visually. Therefore, state graphs are converted into tabular form for convenience. The following conventions are used:

ConventionMeaning
Each row of the tableCorresponds to one state of the system
Each column of the tableCorresponds to one input condition or event
The cell at row-column intersectionSpecifies the next state (transition) and the output/action, if any
Empty or — cellThe event is not valid in this state (illegal transition)
Advantage of tabular form: A state table makes it immediately visible which transitions are defined and which are not. Empty cells highlight potential illegal transitions that should be tested to ensure the system handles unexpected events gracefully.
Positive transition tests
Verify each defined cell: the system moves to the correct next state and performs the expected action.
Negative transition tests
Verify each empty cell: the system rejects the event and the state remains unchanged.
Recovery tests
Validate that the system can return from error or blocked states through proper reset/unlock flows.

State Table Example: ATM PIN Attempts

Scenario: Card session starts in Idle. After 3 wrong PIN entries, account goes to Blocked.

Current State Event Condition Action Next State
IdleInsert CardCard validPrompt PINAuth-1
Auth-1Enter PINPIN correctShow menuAuthenticated
Auth-1Enter PINPIN wrongError + retryAuth-2
Auth-2Enter PINPIN wrongError + retryAuth-3
Auth-3Enter PINPIN wrongBlock accountBlocked
BlockedEnter PINAnyDeny accessBlocked
Minimum transition-focused tests
  1. Happy path: Idle -> Authenticated with correct PIN first try.
  2. Lock path: three wrong PIN attempts lead to Blocked.
  3. Blocked persistence: additional attempts remain in Blocked.
  4. Invalid transition: transaction request before authentication should be denied.

Combining Both Techniques

For realistic systems, first choose data representatives through equivalence classes, then execute them across critical state transitions.

Integration Pattern
  1. Model workflow states and transitions.
  2. Create equivalence classes for each event input field.
  3. Select representative values for each class.
  4. Map representatives to highest-risk transitions.
  5. Build a compact matrix: transition x representative class.
Example

In login flow, test valid username class, invalid format class, and locked-account class specifically on transitions LoginSubmitted and RetryAfterFailure to avoid large redundant suites.

Common Mistakes

Too many tests per class
Multiple tests from same class increase effort without new coverage.
Missing invalid classes
Students often define only valid inputs and forget rejection behavior.
No illegal transition checks
State testing is incomplete if only happy transitions are tested.
Ignoring output/action
Verify not only next state, but also message, log, and side effects.

Class Activity

  1. Pick one feature with input rules and lifecycle behavior (login, booking, cart checkout).
  2. Create at least 5 equivalence classes (valid + invalid).
  3. Draw state table with at least 4 states and 6 transitions.
  4. Design 8-10 tests combining representatives and transitions.
  5. Execute or dry-run and classify defects as data-rule vs state-rule failures.
Evaluation Rubric (10 marks)
  • 3 marks: Correct and complete equivalence classes.
  • 3 marks: Accurate state table with valid/invalid transitions.
  • 2 marks: Efficient non-redundant combined suite.
  • 2 marks: Clear expected results and defect reasoning.

Exit Ticket

  1. For amount input 100-5000, list one valid and two invalid equivalence classes.
  2. Why is "wrong OTP 3 times" a state problem and not only an input problem?
  3. Name one test that checks an illegal transition in a library issue-return system.

Summary & Assignment

Equivalence partitioning reduces unnecessary input combinations, while state table testing ensures behavior remains correct through sequences of events. Together, they form efficient and high-impact dynamic test suites.

Assignment: Choose one mini-project feature and submit (1) equivalence class table, (2) finite state table, and (3) a combined suite of at least 10 tests with expected outputs and next-state checks.