Introduction

State-based testing is a diagnostic technique for OO design based on
state models. In state models, objects are characterized by states.
States are described by discrete state variables. The value of state
variables depend on the instance variables that contribute to the
state. The mapping from instance variables to state variables can be
expressed in terms of a logical expression. For example, suppose we
have a class of object called Water with the following instance
variable, temperature, and three states, ice, water, and steam, the
following define the mapping from instance variable to state variable

ice: temperature < 0

water: 0 <= temperature <= 100

steam: temperature > 100

To perform state-based testing for a class of objects, for each method
in the class, we specify the possible states that the object can be in
prior to the message send, known as the pre-condition. We also
specify the possible states that the object can be in after the
message send, known as the post-condition. A sequence of messages are
sent to the object to test all the possibilities specified in the pre
and post-conditions. The states prior to and after each message send
are retained so that we can check to see that each method altered the
states according to the pre-specified conditions.

Smalltalk Implementation

To implement state-based checking for a particular class in Smalltalk,
we start by defining binary states that are mutually exclusive and
collectively exhaustive. To store state definitions, we create a
class variable called StateDictionary, an instance of Dictionary. The
keys of the dictionary are state names; the values are blocks
containing logical expressions that map instance variables to state
names. When the expression evaluates to true, the corresponding state
is considered to be on; when the expression evaluates to false, the
corresponding state is considered to be off. Using our Water example,
the state dictionary would be as follows

To implement facilities for defining pre- and post-conditions for
methods, we introduce another class variable called
PreAndPostConditions, an instance of Dictionary, to store the
conditions. The keys are method names; the values are arrays
consisting of two blocks, the pre-condition block and the
post-condition block. States must be passed into each block as
arguments. The pre-condition block needs to know the state before the
execution of a method and the post-condition block needs to know both
the states before and after the execution of a method. Each block
evaluates to true when conditions are met and false when conditions
are not met.

Having defined the two storage dictionaries, we modify the method
dictionary of the class. First, for each method being tested, we
concatenate 'STATECHECKED' to the front of the method name. Using our
example, we define the following methods for Water

heat:

cool:

sublime

insulate

These methods would be renamed to be

STATECHECKEDheat:

STATECHECKEDcool:

STATECHECKEDsublime

STATECHECKEDinsulate

Second, we use the old method names to define new methods with hooks.
Using the sublime method as an example, the new method with ancillary
methods is as follows

Remarks

For clarity of presentation, we have greatly simplified the
implementation details. In practice, a separate class that handles
state testing would be created to minimize invasiveness. The class
would have both the state dictionary and the conditions dictionary as
class variables. The state dictionary would first be organized by
class, then by state variable names, then by state variable values and
corresponding mapping conditions. The test condition dictionary would
first be organized by class, then by method and corresponding pre and
post conditions.

Our state-based testing implementation draws ideas from an article by
Robert V. Binder entitled "State-Based Testing" published in
July-August issue of Object Magazine. The idea of altering method
dictionaries to query states was inspired by the use of tracers as a
testing tool from a paper by Heinz-Dieter Bocker and Jurgen Herczeg
entitled "What Tracers Are Made of" found in the ECOOP/OOPSLA '90
Proceedings.