« Design Patterns in Test Automation: Navigate Handler | Quest 2017 » |
In the a previous post, we discussed how design patterns can be used in test automation to reduce the level of effort to develop and maintain automated tests. Here is another useful design pattern:
Pattern Name: Test Class
Problem: An automated test is typically built upon the assumption that it will start from some known state, often referred to as the ‘base’ state. This must be so, because when the action of a test begins, it will manipulate objects that it expects to exist in an enabled state. For example, a test might start by invoking some window from the AUT’s main menu. If, because of the current application context, the menu item does not exist or is disabled, the test will fail. Furthermore a well-designed test should, upon completion, return the application to the ‘base’ state. A classic problem ensues when a test fails or loses context and is unable to run to completion. Subsequent tests fail due to what is referred to as the ‘domino effect’. These cascading failures render the test results invalid at the expense of time and resources.
Solution:
TestClass is implemented as a class with a number of virtual methods. Each test derives from this class and may define any of the virtual methods. The user may also subclass TestClass and then derive tests from the subclass so that methods can be shared amongst a group of tests. OnStart executes before a test is run. It includes steps which are needed to ensure that the AUT is at the ‘base’ state. Main is typically defined for each test as it includes the steps needed for navigation and verification. OnFinish is responsible for returning the application to the ‘base’ state. OnException and Run are not modified by the user. They control the execution of the test and report any application failures should they be found. This control structure ensures that the AUT is at the base state before the first test begins and is brought back to the base state between each test if a test is unable to run to completion or is not properly designed to return the AUT to the ‘base’ state.
Consequences: It may be argued that such a pattern is inefficient in that steps are taken between each test to return the AUT to the ‘base’ state, where fewer actions would be required to start from the state achieved by a previous test. Yet, that approach relies on the false premise that the previous test will succeed at achieving that state. It builds dependencies between tests and sets the stage for the cascading failures that this pattern is designed to avoid. Another argument might pose that a group of tests start and stop from some other application state that requires many steps to achieve. The pattern allows for this alternative in that it does not limit the entire system to a single ‘base’ state. Subclasses of TestClass can be defined for any number of ‘starting’ states that might be required.