Great work!

XP to next level

BugEater

Valid vs. Invalid Transitions

Learning Objectives

By the end of this lesson you will be able to:

  • Build a state transition table from a state diagram
  • Identify all invalid transitions in the table
  • Write test cases targeting invalid transitions

The State Transition Table

A state diagram is visual and intuitive — great for communication. But for test design, a state transition table is more rigorous. It's a matrix where:

  • Rows = current states
  • Columns = events
  • Cells = next state (if valid) or "–" / "Error" (if invalid)

Building the Table

From our task management example:

Current State Start Work Submit for Review Approve Request Changes Cancel
Draft In Progress Cancelled
In Progress In Review Cancelled
In Review Done In Progress Cancelled
Done
Cancelled

The "–" cells are the gold: these are the invalid transitions. There are 14 invalid combinations in this table. Most test suites test 0 of them.

Why Invalid Transitions Are Critical

"It will never happen in practice" is not a defense. Users click back buttons. Data gets imported from external systems. APIs are called in unexpected orders. Scripts are run by developers against the database. Invalid state transitions happen — and when they do, the system either:

  • Rejects gracefully with a clear error
  • Silently ignores the event (and data becomes inconsistent)
  • Crashes

Only the first is acceptable. The other two are bugs that state transition testing catches.

Test Cases for Invalid Transitions

For each "–" cell, write a test case that attempts the invalid transition and verifies the correct response:

  • TC-001: Task in state Done + "Cancel" event → Expect: error or rejection, task remains Done
  • TC-002: Task in state Draft + "Approve" event → Expect: error or rejection, task remains Draft
  • TC-003: Task in state Cancelled + "Start Work" event → Expect: error or rejection, task remains Cancelled

Pro Tip: Invalid transitions often reveal the "feature/bug" category: behavior that was never specified but affects real users. When you find that Cancelled → Start Work is silently accepted, that's a conversation to have with the product team — is it a bug or a feature?

Combining with Guard Testing

When a transition has a guard condition (e.g., "Cancel is only allowed if status != Shipped"), add test cases for both sides of the guard:

  • Guard passes: cancel a non-shipped order → should succeed
  • Guard fails: cancel a shipped order → should be blocked

This is not just an invalid transition — it's a conditional transition, and both the true and false guard paths need separate tests.

All-Pairs on State Transitions

For systems with many states and events, testing every invalid transition is expensive. Apply the pairwise principle (Module 5): select a subset of invalid transitions that covers every (state × invalid event) pair at least once.

Summary

The state transition table converts a visual state diagram into a structured test design artifact. Every "–" cell is a test case waiting to be written. Testing invalid transitions — the ones nobody thinks to test — is the highest-value practice in state transition testing, because that's where the assumption "this can never happen" meets the reality "this just happened in production."

Quiz

An order lifecycle has states: Draft → Submitted → Approved → Shipped. A user tries to move directly from Draft to Shipped. This is:

Which coverage criterion requires testing every state AND every valid transition at least once?

"Sneak path" bugs occur when:

What is the minimum test strategy to expose a "missing transition" defect?