Patterns, as described by the architect and theorist Christopher Alexander and his colleagues over the last thirty-five years, are a way of describing problems and customizable solutions. Patterns became popular in the software development field, and they've been applied to testing. Here, Brian Marick explores patterns and problem solving.
You probably brush your teeth the same way every day. The next time you pay bills, you'll probably pay them essentially the same way as last time. In both cases, you have a recurrent problem—keeping cavities at bay, keeping your creditors at bay—and a solution that works well enough that you don't need to fiddle with it.
Other problems are so wicked that you can’t solve them at all unless you think deeply. You might use a repertoire of habits of thought—divide and conquer, solve the simplest problem first, and so on—but every solution is fundamentally different from every other.
This article is about the problems in the middle. They're not unique, but each time they recur, they’re different in important ways. To be a good solver of such problems, you must be able to customize stock solutions. It's as if your mouth and teeth changed shape every day—the idea of brushing away the gunk would be the same, but the approach would be different.
That's where patterns come in. Patterns, as described by the architect and theorist Christopher Alexander and his colleagues over the last thirtyfive years, are a way of describing problems and customizable solutions. Patterns became popular in the software field with the publication of Design Patterns , by Gamma, Helm, Johnson, and Vlissides. They've also been applied to testing. For example, Linda Rising and David DeLano's online article "Patterns for System Testing" and Robert Binder's book Testing Object-Oriented Systems: Models, Patterns, and Tools contain a number of test design and implementation patterns. In fact, I'm part of a group of people now trying to collect many more testing patterns, and with this article I hope to encourage you to join us in the effort.
Patterns help people customize solutions in two ways. The first is that they use a notion of forces to explain the "why" behind a solution. Let me illustrate with an example.
Suppose you're using domain experts to test a product. You might be using nurses to test a medical information system, or accountants to test an accounting package. Suppose, too, that you'll be using an automated test execution tool, and the testers are to create the tests in advance, rather than by capturing mouse movements with the tool. The problem: in what format should these domain experts/testers write their tests?
- On the one hand, the tool has non-negotiable notions of what tests should look like. A test must be written in the tool's scripting language, which is essentially a programming language like any other.
- On the other hand, the domain experts are probably not programmers. Learning a tool's scripting language is really rather different from anything they want to do with their lives.
The needs of the tool and the desires of the domain experts are like two different forces pushing in opposite directions. The tool is pushing for a programming language; the domain experts are pushing for something much more like regular human language. Their conflict can be resolved with a "bridge" program. The domain experts/testers are allowed to write tests in some format they're comfortable with, and the bridge program then translates those tests into the tool's scripting language. That solution would look like Figure 1.
This scenario includes the basic elements of a pattern. There is a particular context (domain experts writing tests in advance), and within that context there is a problem (what the format should be). The solution must resolve some conflict between identified forces (in this case, the domain experts' and the tool's differing needs). These elements are given a memorable name, like Bridge