XPlorations
Test StylesThere are two common styles of writing tests. One style might be called procedural: a test consists of a series of steps, each acting on or testing the state of the system. The second style might be called declarative: given a state of the system and some inputs, test the resulting state and the outputs. (These terms are from the theory of programming languages.) If we were using Ward Cunningham's fit testing framework, we might think of these as prototypically ActionFixtures vs. ColumnFixtures. Let's look at a small, concrete example: a simple login screen.
We'd like to test that the OK button is highlighted only if both a username and a password have been specified. Here's a test in the procedural style:
Here's a test of the same capability in a declarative style:
There's a sense in which the first test is more natural to write: it tells you what to do, step by step. But consider some advantages of the second style:
Keeping StateReal systems may involve hidden state: state that affects the system but is not directly set or seen. Consider this example:
This is an accumulator: it provides a running sum and average. Obviously, it must somehow keep track of n, the number of items entered, in order to compute the average. We can make a declarative test out of this by exposing the hidden state to the test:
The first two columns, n and sum, represent existing state. Data is the number entered on the screen, and sum' and avg' are the results. Getting to the hidden state can be a trick. Sometimes the programmers can explicitly expose it as part of a testing interface; other times the state can be accessed by a sequence of steps. In this case, we could setup the proper state for each row by doing this:
Then the rest of the row might be interpreted as:
This puts some burden on the test setup code. But if the setup is not done there, it's probably repeated in a bunch of scripts. When to Use the Procedural Style?Procedural style pays off best when the sequential nature of the feature is what's interesting: when how you got somewhere is as important as where you are. Consider the problem of multiple selection, using click, shift, control, and drag. For setup, imagine a vertical list of items, numbered 1 through 10. Consider this test:
Or this one:
You could perhaps develop a set of declarative tests for these, but the sequence of actions is what's interesting. What to do?Leverage procedural tests for the cases where the sequence of actions is paramount, and there's not a lot of commonality between scripts. Scenario tests can benefit from the procedural style. A declarative test is like a table you could put in a user manual: it concisely and concretely explains a function. Declarative tests sometimes require extra setup, especially when hidden state is involved, but they're often worth that extra trouble. Declarative tests are good for testing permutations of a business rule. If all else is equal, favor the declarative style. These guidelines can boost your test-writing efficiency: they move repetitive actions into the test setup, and let you focus on the interesting part of a test. [Written February, 2005. Brian Marick suggested the terms, though I'm not sure I picked the set he liked best.] |
|
Copyright 1994-2010, William C. Wake - William.Wake@acm.org |