Colonel Cleatus Yorbville had been one seriously bored astronaut for the first few months of his diplomatic mission on the third planet of the Frangelicus XIV system, but all that had changed on the day he'd discovered that his tiny, multipedal and infinitely hospitable alien hosts were not only edible but tasted remarkably like that stuff that's left on the pan after you've made cinnamon buns and burned them a little.
— Mark Silcox
State-Transition diagrams, like decision tables, are another excellent tool to capture certain types of system requirements and to document internal system design. These diagrams document the events that come into and are processed by a system as well as the system's responses. Unlike decision tables, they specify very little in terms of processing rules. When a system must remember something about what has happened before or when valid and invalid orders of operations exist, state-transition diagrams are excellent tools to record this information.
These diagrams are also vital tools in the tester's personal toolbox. Unfortunately, many analysts, designers, programmers, and testers are not familiar with this technique.
It is easier to introduce state-transition diagrams by example rather than by formal definition. Since neither Brown & Donaldson nor the Stateless University Registration System has substantial state-transition based requirements let's consider a different example. To get to Stateless U, we need an airline reservation. Let's call our favorite carrier (Grace L. Ferguson Airline & Storm Door Company) to make a reservation. We provide some information including departure and destination cities, dates, and times. A reservation agent, acting as our interface to the airline's reservation system, uses that information to make a reservation. At that point, the Reservation is in the Made state. In addition, the system creates and starts a timer. Each reservation has certain rules about when the reservation must be paid for. These rules are based on destination, class of service, dates, etc. If this timer expires before the reservation is paid for, the reservation is cancelled by the system. In state-transition notation this information is recorded as:
Figure 7-1: The Reservation is Made.
The circle represents one state of the Reservation—in this case the Made state. The arrow shows the transition into the Made state. The description on the arrow, giveInfo, is an event that comes into the system from the outside world. The command after the "/" denotes an action of the system; in this case startPayTimer. The black dot indicates the starting point of the diagram.
Sometime after the Reservation is made, but (hopefully) before the PayTimer expires, the Reservation is paid for. This is represented by the arrow labeled PayMoney. When the Reservation is paid it transitions from the Made state to the Paid state.
Figure 7-2: The Reservation transitions to the Paid state.
Before we proceed let's define the terms more formally:
This notation was created by Mealy. An alternate notation has been defined by Moore but is less frequently used. For a much more in-depth discussion of state-transition diagrams see Fowler and Scott's book, UML Distilled: A Brief Guide To The Standard Object Modeling Language. It discusses more complex issues such as partitioned and nested state-transition diagrams.
Note that the state-transition diagram represents one specific entity (in this case a Reservation). It describes the states of a reservation, the events that affect the reservation, the transitions of the reservation from one state to another, and actions that are initiated by the reservation. A common mistake is to mix different entities into one state-transition diagram. An example might be mixing Reservation and Passenger with events and actions corresponding to each.
From the Paid state the Reservation transitions to the Ticketed state when the print command (an event) is issued. Note that in addition to entering the Ticketed state, a Ticket is output by the system.
Figure 7-3: The Reservation transitions to the Ticketed state.
From the Ticketed state we giveTicket to the gate agent to board the plane.
Figure 7-4: The Reservation transitions to the Used state.
After some other action or period of time, not indicated on this diagram, the state-transition path ends at the bulls-eye symbol.
Figure 7-5: The path ends.
Does this diagram show all the possible states, events, and transitions in the life of a Reservation? No. If the Reservation is not paid for in the time allotted (the PayTimer expires), it is cancelled for non-payment.
Figure 7-6: The PayTimer expires and the Reservation is cancelled for nonpayment.
Finished yet? No. Customers sometimes cancel their reservations. From the Made state the customer (through the reservation agent) asks to cancel the Reservation. A new state, Cancelled By Customer, is required.
Figure 7-7: Cancel the Reservation from the Made state.
In addition, a Reservation can be cancelled from the Paid state. In this case a Refund should be generated and leave the system. The resulting state again is Cancelled By Customer.
Figure 7-8: Cancellation from the Paid state.
One final addition. From the Ticketed state the customer can cancel the Reservation. In that case a Refund should be generated and the next state should be Cancelled by Customer. But this is not sufficient. The airline will generate a refund but only when it receives the printed Ticket from the customer. This introduces one new notational element—square brackets [] that contain a conditional that can be evaluated either True or False. This conditional acts as a guard allowing the transition only if the condition is true.
Figure 7-9: Cancellation from the Ticketed state.
Note that the diagram is still incomplete. No arrows and bulls-eyes emerge from the Cancelled states. Perhaps we could reinstate a reservation from the Cancelled NonPay state. We could continue expanding the diagram to include seat selection, flight cancellation, and other significant events affecting the reservation but this is sufficient to illustrate the technique.
As described, state-transition diagrams express complex system rules and interactions in a very compact notation. Hopefully, when this complexity exists, analysts and designers will have created state-transition diagrams to document system requirements and to guide their design.
A state-transition diagram is not the only way to document system behavior. The diagrams may be easier to comprehend, but state-transition tables may be easier to use in a complete and systematic manner. State-transition tables consist of four columns—Current State, Event, Action, and Next State.
Current State |
Event |
Action |
Next State |
---|---|---|---|
null |
giveInfo |
startPayTimer |
Made |
null |
payMoney |
-- |
null |
null |
|
-- |
null |
null |
giveTicket |
-- |
null |
null |
cancel |
-- |
null |
null |
PayTimerExpires |
-- |
null |
Made |
giveInfo |
-- |
Made |
Made |
payMoney |
-- |
Paid |
Made |
|
-- |
Made |
Made |
giveTicket |
-- |
Made |
Made |
cancel |
-- |
Can-Cust |
Made |
PayTimerExpires |
-- |
Can-NonPay |
Paid |
giveInfo |
-- |
Paid |
Paid |
payMoney |
-- |
Paid |
Paid |
|
Ticket |
Ticketed |
Paid |
giveTicket |
-- |
Paid |
Paid |
cancel |
Refund |
Can-Cust |
Paid |
PayTimerExpires |
-- |
Paid |
Ticketed |
giveInfo |
-- |
Ticketed |
Ticketed |
payMoney |
-- |
Ticketed |
Ticketed |
|
-- |
Ticketed |
Ticketed |
giveTicket |
-- |
Used |
Ticketed |
cancel |
Refund |
Can-Cust |
Ticketed |
PayTimerExpires |
-- |
Ticketed |
Used |
giveInfo |
-- |
Used |
Used |
payMoney |
-- |
Used |
Used |
|
-- |
Used |
Used |
giveTicket |
-- |
Used |
Used |
cancel |
-- |
Used |
Used |
PayTimerExpires |
-- |
Used |
Can-NonPay |
giveInfo |
-- |
Can-NonPay |
Can-NonPay |
payMoney |
-- |
Can-NonPay |
Can-NonPay |
|
-- |
Can-NonPay |
Can-NonPay |
giveTicket |
-- |
Can-NonPay |
Can-NonPay |
cancel |
-- |
Can-NonPay |
Can-NonPay |
PayTimerExpires |
-- |
Can-NonPay |
Can-Cust |
givelnfo |
-- |
Can-Cust |
Can-Cust |
payMoney |
-- |
Can-Cust |
Can-Cust |
|
-- |
Can-Cust |
Can-Cust |
giveTicket |
-- |
Can-Cust |
Can-Cust |
cancel |
-- |
Can-Cust |
Can-Cust |
PayTimerExpires |
-- |
Can-Cust |
The advantage of a state-transition table is that it lists all possible state-transition combinations, not just the valid ones. When testing critical, high-risk systems such as avionics or medical devices, testing every state-transition pair may be required, including those that are not valid. In addition, creating a state-transition table often unearths combinations that were not identified, documented, or dealt with in the requirements. It is highly beneficial to discover these defects before coding begins.
Key Point |
The advantage of a state-transition table is that it lists all possible state-transition combinations, not just the valid ones. |
Using a state-transition table can help detect defects in implementation that enable invalid paths from one state to another. The disadvantage of such tables is that they become very large very quickly as the number of states and events increases. In addition, the tables are generally sparse; that is, most of the cells are empty.
Information in the state-transition diagrams can easily be used to create test cases. Four different levels of coverage can be defined:
Figure 7-10: A set of test cases that "visit" each state.
Figure 7-11: A set of test cases that trigger all events at least once.
A→B
A→B→A
A→B→A→B→A→B
A→B→A→B→A→B→A
A→B→A→B→A→B→A→B→A→B
...
and so on forever. Testing of loops such as this can be important if they may result in accumulating computational errors or resource loss (locks without corresponding releases, memory leaks, etc.).
Key Point |
Testing every transition is usually the recommended level of coverage for a state-transition diagram. |
Figure 7-12: A set of test cases that trigger all transitions at least once.
Test cases can also be read directly from the state-transition table. The gray rows in the following table show all the valid transitions.
Current State |
Event |
Action |
Next State |
---|---|---|---|
null |
giveInfo |
startPayTimer |
Made |
null |
payMoney |
-- |
null |
null |
|
-- |
null |
null |
giveTicket |
-- |
null |
null |
cancel |
-- |
null |
null |
PayTimerExpires |
-- |
null |
Made |
giveInfo |
-- |
Made |
Made |
payMoney |
-- |
Paid |
Made |
|
-- |
Made |
Made |
giveTicket |
-- |
Made |
Made |
cancel |
-- |
Can-Cust |
Made |
PayTimerExpires |
-- |
Can-NonPay |
Paid |
giveInfo |
-- |
Paid |
Paid |
payMoney |
-- |
Paid |
Paid |
|
Ticket |
Ticketed |
Paid |
giveTicket |
-- |
Paid |
Paid |
cancel |
Refund |
Can-Cust |
Paid |
PayTimerExpires |
-- |
Paid |
Ticketed |
giveInfo |
-- |
Ticketed |
Ticketed |
payMoney |
-- |
Ticketed |
Ticketed |
|
-- |
Ticketed |
Ticketed |
giveTicket |
-- |
Used |
Ticketed |
cancel |
Refund |
Can-Cust |
Ticketed |
PayTimerExpires |
-- |
Ticketed |
Used |
giveInfo |
-- |
Used |
Used |
payMoney |
-- |
Used |
Used |
|
-- |
Used |
Used |
giveTicket |
-- |
Used |
Used |
cancel |
-- |
Used |
Used |
PayTimerExpires |
-- |
Used |
Can-NonPay |
giveInfo |
-- |
Can-NonPay |
Can-NonPay |
payMoney |
-- |
Can-NonPay |
Can-NonPay |
|
-- |
Can-NonPay |
Can-NonPay |
giveTicket |
-- |
Can-NonPay |
Can-NonPay |
cancel |
-- |
Can-NonPay |
Can-NonPay |
PayTimerExpires |
-- |
Can-NonPay |
Can-Cust |
givelnfo |
-- |
Can-Cust |
Can-Cust |
payMoney |
-- |
Can-Cust |
Can-Cust |
|
-- |
Can-Cust |
Can-Cust |
giveTicket |
-- |
Can-Cust |
Can-Cust |
cancel |
-- |
Can-Cust |
Can-Cust |
PayTimerExpires |
-- |
Can-Cust |
In addition, depending on the system risk, you may want to create test cases for some or all of the invalid state/event pairs to make sure the system has not implemented invalid paths.
State-Transition diagrams are excellent tools to capture certain system requirements, namely those that describe states and their associated transitions. These diagrams then can be used to direct our testing efforts by identifying the states, events, and transitions that should be tested.
State-Transition diagrams are not applicable when the system has no state or does not need to respond to real-time events from outside of the system. An example is a payroll program that reads an employee's time record, computes pay, subtracts deductions, saves the record, prints a paycheck, and repeats the process.
The following terms are used in the diagram:
Events
Attributes
Tests
Lists
Symbols
Figure 7-13: State-transition diagram for enroll and drop a course at Stateless U.
Binder, Robert V. (1999). Testing Object-Oriented Systems: Models, Patterns, and Tools. Addison-Wesley.
Fowler, Martin and Kendall Scott (1999). UML Distilled: A Brief Guide to the Standard Object Modeling Language (2nd Edition). Addison-Wesley.
Harel, David. "Statecharts: a visual formalism for complex systems." Science of Computer Programming 8, 1987, pp 231–274.
Mealy, G.H. "A method for synthesizing sequential circuits." Bell System Technical Journal, 34(5): 1045–1079, 1955.
Moore, E.F. "Gedanken-experiments on sequential machines," Automata Studies (C. E. Shannon and J. McCarthy, eds.), pp. 129–153, Princeton, New Jersey: Princeton University Press, 1956.
Rumbaugh, James, et al. (1991). Object-Oriented Modeling and Design. Prentice-Hall.
Preface
Section I - Black Box Testing Techniques
Section II - White Box Testing Techniques
Section III - Testing Paradigms
Section IV - Supporting Technologies
Section V - Some Final Thoughts