My last two articles were dedicated to the Behaviours Design Pattern. It is a pattern that eases the creation of tests through a build process similar to LEGO. This article, part of the Design Patterns in Automated Testing Series, is going to suggest a new concept how to improve the behaviours driven tests even further. It is going to ease the actions' configuration through the introduction of behaviours' definitions.
UML Class Diagram
Participants
The classes and objects participating in the enhanced Behaviours Design Pattern are:
- IBehaviour- Defines the interfaces for all behaviours. Contains only a single Execute method.
- ActionBehaviour- The base class for all actions-only behaviours. Contains only two methods PerformAct and Execute.
- UnityContainerFactory- A class that creates and holds a single global instance to a Unity IoC container.
- ItemPageNavigationBehaviour- A concrete behaviour for the ItemPage class. It holds a logic for navigation. Its is an action behaviour.
- ItemPage- A concrete page object that provides different service operations that can be performed on the page. It is used in the specific behaviours.
- BehaviourEngine- It is the class that executes the list of behaviours' workflows.
- BehaviourDefinition- The base class for all behaviours' definitions. It holds the type of the definition's behaviour.
- NavigatePageBehaviourDefinition- The concrete definition for ItemPageNavigationBehaviour. It extends the BehaviourDefinition base class and contains the property for the navigation URL.
What Are the Problems That We Try to Solve?
The initial version of the behaviours had one major shortcoming- the inability to pass parameters to the behaviours. To do their job they needed a static test context class. Another considerable drawback was that the behaviours' executor was not flexible, it was hard to change its hard-coded workflow.
Enhanced Behaviours Design Pattern through Definitions
The new concept steps on the previously improved design. You can read more about it in my previous article- Advanced Behaviours Design Pattern in Automated Testing Part 1. The main difference compared to the earlier design is that the behaviours are split into two separate classes- behaviour and definition. The definition holds all parameters needed for the work of the workflow. The another change is that the engine now requires the definitions instead of behaviours.
BehaviorDefinition Base Class
public abstract class BehaviorDefinition
{
public BehaviorDefinition(Type behaviorType)
{
this.BehaviorType = behaviorType;
}
internal Type BehaviorType { get; private set; }
}
Nothing special about this class. It only holds a reference to its behaviour.
Navigate Page Behaviour Definition
public class NavigatePageBehaviorDefinition : BehaviorDefinition
{
public NavigatePageBehaviorDefinition(string expectedUrl) :
base(typeof(NavigatePageBehavior))
{
this.ExpectedUrl = expectedUrl;
}
internal string ExpectedUrl { get; private set; }
}
That is the class that holds all parameters required for the Navigation Page behaviour. It contains the navigation URL. Also, we pass the type of the NavigatePageBehaviour to the base constructor. It is necessary for the proper work of the engine.
Navigate Page Behaviour Changes
public class NavigatePageBehavior : ActionBehaviour
{
private readonly string expectedUrl;
public NavigatePageBehavior(NavigatePageBehaviorDefinition definition)
{
this.expectedUrl = definition.ExpectedUrl;
}
protected override void PerformAct()
{
Console.WriteLine(this.expectedUrl);
}
}
The difference compared to the earlier version is that the navigation URL now is got from the definition instead from the behaviour. The single responsibility principle is followed more closely.
Enhanced Behaviour Engine
public static class BehaviorEngine
{
public static void Execute(params BehaviorDefinition[] behaviorDefinitions)
{
foreach (var definition in behaviorDefinitions)
{
var behavior =
UnityContainerFactory.GetContainer().Resolve(
definition.BehaviorType,
new ResolverOverride[]
{
new ParameterOverride("definition", definition)
}) as Behavior;
behavior.Execute();
}
}
}
We pass the definitions to the Execute method. However, their behaviours are executed. They are resolved through the Unity IoC container that gets their instances based on the definitions' behaviour types. Unity injects the instance of the current definition as a parameter override of the 'definition' constructor's parameter.
Definition Behaviours in Tests
The usage in tests is straightforward.
[TestMethod]
public void Purchase_SimpleBehaviourEngine()
{
string itemUrl = "/Selenium-Testing-Cookbook-Gundecha-Unmesh/dp/1849515743";
BehaviorEngine.Execute(
new NavigatePageBehaviorDefinition(itemUrl));
}
Design Patterns in Automated Testing
The post Advanced Behaviours Design Pattern in Automated Testing Part 1 appeared first on Automate The Planet.
All images are purchased from DepositPhotos.com and cannot be downloaded and used for free.
License Agreement