Test Patterns


Test patterns are design patterns for test software. Design patterns [GHJV94] capture and reuse design knowledge that has gained widespread application in the object-oriented software development community. Each pattern is a specific configuration of interactions among a set of objects that form some cluster in the overall design. The pattern description explains the context within which the pattern should be considered, provides a set of forces that guide a trade-off analysis, and explains how to construct the objects. We use the same format for the pattern description as the design community, but we can place more specific meaning on certain sections of the description.

We have been successful with the concept of relating a test pattern to a particular design pattern. When a developer uses a specific design pattern to structure a portion of the system, a tester (who may be another developer) then knows which test pattern to use to structure the test code.

The Grid component is based on the Listener design pattern, which is related to the more general Observer design pattern to incorporate event handling into its GUI. In the next section, we will explain the associated test pattern.

Listener Test Pattern

Intent

There is a need to test the interactions among the Listener, ActionListener, and TargetObject objects that are participating in the Listener design pattern (Figure 6.21). The interactions need to be examined to ensure that:

  • each interaction correctly sets the state of each participating object

  • each interaction is complete in that all objects that should be affected are

  • each interaction is consistent with the specification of the participating objects

Figure 6.21. Conceptual interactions in the Listener pattern

graphics/06fig21.gif

A Listener object is passed to an object that receives events. A Listener is only "interested" in a certain set of event objects. The ActionListener object forwards to a registered Listener only those events for which the Listener is registered. Each Listener is associated with some instance of TargetObject. When the Listener receives an event, it performs some action on its target object. That action was defined as a method in the class Listener.

Context

The Listener design pattern has been heavily used in Java, but equivalent event-handling patterns are used in all object-oriented languages. The pattern is particularly used in the context of the user interface. Most Java programs contain a large number of instances of the Listener pattern.Very little original code is written in a Listener class. Developers usually define the original code using the anonymous class mechanism. This makes it more difficult to test the mechanism in isolation.

Forces

There are several forces that constrain the design of the test classes:

  • Modifying the production software to accommodate testing requires that additional tests be run after the production software is returned to its original state. Therefore, we prefer not to modify the application in order to test it.

  • The test class must know when events are received by the Listener object. This may be accomplished by having the test class produce the events, or by having the test class register for the same events as the Listener class being tested.

  • Participating objects have already been class tested. Therefore, the accessor and modifier methods of the individual objects will be trusted and used during this test.

  • The small size of each Listener subclass and the large number of Listener classes used in an application requires that the tests be easily created and ported to a new Listener class.

Solution

A TestListener class creates an environment in which the interactions between objects in the Listener design pattern are exercised and observed. The TestListener object instantiates the pattern. A TestListener object can generate any of the events for which a Listener object can register.

There is essentially one type of test case. An event is generated by the TestListener object and sent to the ActionListener object. If the ActionListener object is working correctly, the event is forwarded to all of the registered Listener objects. The Listeners invoke specific actions on their TargetObjects. The TestListener object registers with the ActionListener so that it receives the event at basically the same time as the Listener object being tested. The ListenerTest object then checks the TargetObject to determine whether the expected changes have occurred there.

Design

An instance of the TestListener class, after inheriting from the AbstractListener class, can register with the ActionListener object. It will then receive a notification of a specific event and will know to activate tests on the SpecializedListener object, Figure 6.22.

Figure 6.22. Conceptual interactions in the Listener pattern extended for testing.

graphics/06fig22.gif

Specific Example

The pattern can be applied to the Brickles TimerObserver class and those associated classes, Figure 6.23.

Figure 6.23. An instantiation of the Listener pattern extended for testing timer observers in Brickles

graphics/06fig23.gif

Resulting Context

The production classes participating in the Listener pattern have been tested relative to their interaction with each other. A series of test classes and test cases have been created that can be reused, with slight modifications, for a variety of types of events. By using the pattern approach, new events and new listeners can be tested cheaply.



A Practical Guide to Testing Object-Oriented Software
A Practical Guide to Testing Object-Oriented Software
ISBN: 0201325640
EAN: 2147483647
Year: 2005
Pages: 126

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net