In my previous article Assessment System for Tests’ Architecture Design, I presented to you eight criteria for system tests architecture design assessment. To understand the system fully, I am going to use it to evaluate a couple of real-world examples, assign ratings to them for each criterion and tell you my reasoning behind them. The second type of tests that we will assess is the behaviour based tests (lego based tests). If you are not familiar with the Behaviour Design Pattern (Lego Design Pattern), you can check my article Advanced Behaviours Design Pattern in Automated Testing Part 2.
Behaviour Based Tests
Abstract Behaviour
public abstract class WaitableActionBehaviour : IBehaviour
{
public void Execute()
{
this.PerformAct();
this.PerformPostActWait();
}
protected abstract void PerformAct();
protected abstract void PerformPostActWait();
}
In general, one behaviour executes a page specific workflow- performs actions and waits for a condition. There are different types of behaviours- actions only, asserts only, combining both or adding additional pre/post-wait conditions (wait for the page to load or wait for an element to be visible). Above you can find the base class for all behaviours that first execute an action and then wait for something to happen.
Concrete Behaviour
public class PreviewShoppingCartPageProceedBehaviour : WaitableActionBehaviour
{
private readonly PreviewShoppingCartPage previewShoppingCartPage;
private readonly SignInPage signInPage;
public PreviewShoppingCartPageProceedBehaviour()
{
this.previewShoppingCartPage =
UnityContainerFactory.GetContainer().Resolve<PreviewShoppingCartPage>();
this.signInPage =
UnityContainerFactory.GetContainer().Resolve<SignInPage>();
}
protected override void PerformAct()
{
this.previewShoppingCartPage.ClickProceedToCheckoutButton();
}
protected override void PerformPostActWait()
{
this.signInPage.WaitForPageToLoad();
}
}
The concrete implementation of a particular behaviour does not have to override all base class’ methods (if there are post/pre-wait and assert methods available, the class can override only one of them). The behaviours hold private instances of all dependent pages or other services. There are initialized in the behaviours constructors through Unity IoC container.
Behaviour with Parameters
public class ShippingAddressPageFillDifferentBillingBehaviour : ActionBehaviour
{
private readonly ShippingAddressPage shippingAddressPage;
private readonly ShippingPaymentPage shippingPaymentPage;
private readonly PerfectSystemTestsDesign.Data.ClientPurchaseInfo clientPurchaseInfo;
public ShippingAddressPageFillDifferentBillingBehaviour(ClientPurchaseInfo clientPurchaseInfo)
{
this.shippingAddressPage = UnityContainerFactory.GetContainer().Resolve<ShippingAddressPage>();
this.shippingPaymentPage = UnityContainerFactory.GetContainer().Resolve<ShippingPaymentPage>();
this.clientPurchaseInfo = clientPurchaseInfo;
}
protected override void PerformAct()
{
this.shippingAddressPage.ClickDifferentBillingCheckBox(this.clientPurchaseInfo);
this.shippingAddressPage.ClickContinueButton();
this.shippingPaymentPage.ClickBottomContinueButton();
this.shippingAddressPage.FillBillingInfo(this.clientPurchaseInfo);
}
}
The specific behaviours can accept custom parameters if needed.
Behaviours Usage in Tests
public void Purchase_SimpleBehaviourEngine()
{
var itemUrl = "/Selenium-Testing-Cookbook-Gundecha-Unmesh/dp/1849515743";
var itemPrice = "40.49";
var clientPurchaseInfo = new ClientPurchaseInfo(
new ClientAddressInfo()
{
FullName = "John Smith",
Country = "United States",
Address1 = "950 Avenue of the Americas",
State = "New York",
City = "New York City",
Zip = "10001-2121",
Phone = "00164644885569"
});
clientPurchaseInfo.CouponCode = "99PERDIS";
var clientLoginInfo = new ClientLoginInfo()
{
Email = "g3984159@trbvm.com",
Password = "ASDFG_12345"
};
PerfectSystemTestsDesign.Behaviours.Core.BehaviourExecutor.Execute(
new ItemPageNavigationBehaviour(itemUrl),
new ItemPageBuyBehaviour(),
new PreviewShoppingCartPageProceedBehaviour(),
new SignInPageLoginBehaviour(clientLoginInfo),
new ShippingAddressPageFillShippingBehaviour(clientPurchaseInfo),
new ShippingAddressPageFillDifferentBillingBehaviour(clientPurchaseInfo),
new ShippingAddressPageContinueBehaviour(),
new ShippingPaymentPageContinueBehaviour(),
new PlaceOrderPageAssertFinalAmountsBehaviour(itemPrice));
}
The behaviours are added as a list to a special behaviours executor that is responsible for executing them in the appropriate way. If the behaviour depends on any data, it is passed to its constructor.
Behaviours Design Pattern
Pros and Cons
-
Readable
-
See granularly workflow’s steps
-
A lot of new classes are introduced.
-
The writing of new tests is slower
-
The process of test writing is more error prompt ecause you can mistake the steps’ order or assign wrong values to some of the behaviours’ parameters.
Evaluate Behavour Based Tests- Assessment System
Maintainability
public class SignInPageLoginBehaviour : WaitableActionBehaviour
{
private readonly SignInPage signInPage;
private readonly ShippingAddressPage shippingAddressPage;
private ClientLoginInfo clientLoginInfo;
public SignInPageLoginBehaviour()
{
this.signInPage =
UnityContainerFactory.GetContainer().Resolve<SignInPage>();
this.shippingAddressPage =
UnityContainerFactory.GetContainer().Resolve<ShippingAddressPage>();
}
[When(@"I login with email = ""([^""]*)"" and pass = ""([^""]*)""")]
public void LoginWithEmailAndPass(string email, string password)
{
this.clientLoginInfo = new ClientLoginInfo
{
Email = email,
Password = password
};
base.Execute();
}
protected override void PerformPostActWait()
{
this.shippingAddressPage.WaitForPageToLoad();
}
protected override void PerformAct()
{
this.signInPage.Login(this.clientLoginInfo.Email, this.clientLoginInfo.Password);
}
}
The maintainability is marked as excellent (5). The behaviours are mini-workflows for some use cases. If the use case should be changed, it is edited only here. As the behaviours are added only on demand, there are not executed for every case. If you fix one behaviour, the change will affect only the tests that are using it.
| Behaviour Based Tests | |
|---|---|
| Maintainability | 5 |
| Readability | |
| Code Complexity Index | |
| Usability | |
| Flexibility | |
| Learning Curve | |
| Least Knowledge |
Readability
BehaviourExecutor.Execute(
new ItemPageNavigationBehaviour(itemUrl),
new ItemPageBuyBehaviour(),
new PreviewShoppingCartPageProceedBehaviour(),
new SignInPageLoginBehaviour(clientLoginInfo),
new ShippingAddressPageFillShippingBehaviour(clientPurchaseInfo),
new ShippingAddressPageFillDifferentBillingBehaviour(clientPurchaseInfo),
new ShippingAddressPageContinueBehaviour(),
new ShippingPaymentPageContinueBehaviour(),
new PlaceOrderPageAssertFinalAmountsBehaviour(itemPrice));
The readability is evaluated as Very Good (4). As the names of the behaviours are self-describing, you can guess their use case. Moreover, as you list multiple behaviours to define the bigger workflow, the order of the steps is directly visible to the reader.
| Behaviour Based Tests | |
|---|---|
| Maintainability | 5 |
| Readability | 4 |
| Code Complexity Index | |
| Usability | |
| Flexibility | |
| Learning Curve | |
| Least Knowledge |
Code Complexity Index
The behaviour classes are small and simple. However, the tests classes are more complex because you need to initialize the whole behaviours’ execution chain.
| Behaviour Based Tests | |
|---|---|
| Maintainability | 5 |
| Readability | 4 |
| Code Complexity Index | 4 |
| Usability | |
| Flexibility | |
| Learning Curve | |
| Least Knowledge |
Usability
ehaviourExecutor.Execute(
new ItemPageNavigationBehaviour(itemUrl),
new ItemPageBuyBehaviour(),
new PreviewShoppingCartPageProceedBehaviour(),
new SignInPageLoginBehaviour(clientLoginInfo),
new ShippingAddressPageFillShippingBehaviour(clientPurchaseInfo),
new ShippingAddressPageFillDifferentBillingBehaviour(clientPurchaseInfo),
new ShippingAddressPageContinueBehaviour(),
new ShippingPaymentPageContinueBehaviour(),
new PlaceOrderPageAssertFinalAmountsBehaviour(itemPrice));
The test framework API is not so complicated to be used. However, you should know the exact name of the behaviours that you want to specify in the large workflow. Moreover, you should be aware of their correct order. Mistaking the order of some of the steps is possible. The writing effort is bigger because here, you need to initialize multiple new classes.
| Behaviour Based Tests | |
|---|---|
| Maintainability | 5 |
| Readability | 4 |
| Code Complexity Index | 4 |
| Usability | 4 |
| Flexibility | |
| Learning Curve | |
| Least Knowledge |
Flexibility

If you want to skip some of the optional mini-workflows, you just don’t need to add them to the executer’s chain. The same is valid if you have to add some custom mini-workflow that is valid only for a small limited amount of use cases. You just need to create the behaviour and add it to the list of behaviours for this particular case.
| Behaviour Based Tests | |
|---|---|
| Maintainability | 5 |
| Readability | 4 |
| Code Complexity Index | 4 |
| Usability | 4 |
| Flexibility | 5 |
| Learning Curve | |
| Least Knowledge |
Learning Curve
The learning curve for the test framework API is average (4) because the user should know the exact order of the behaviours. Moreover, should be familiar with the correct names of all behaviours and which exact implementation want to call. There might be more than one implementation where it is slightly different.
| Behaviour Based Tests | |
|---|---|
| Maintainability | 5 |
| Readability | 4 |
| Code Complexity Index | 4 |
| Usability | 4 |
| Flexibility | 5 |
| Learning Curve | 4 |
| Least Knowledge |
Least Knowledge
You pass only the required parameters to the concrete behaviours. So the rating is marked as excellent.
| Behaviour Based Tests | |
|---|---|
| Maintainability | 5 |
| Readability | 4 |
| Code Complexity Index | 4 |
| Usability | 4 |
| Flexibility | 5 |
| Learning Curve | 4 |
| Least Knowledge | 5 |
In my next article from the series, I will use the assessment system to evaluate the SpecFlow based tests.
You can watch my conference talk dedicated to the system or download the [whole slide deck](/whitepapers/heros-journey-to-perfect-system-tests-eight-assessment-c
