Assessment System for Tests’ Architecture Design- Behaviour Based Tests

Assessment System for Tests’ Architecture Design- Behaviour Based Tests

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
Maintainability5
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
Maintainability5
Readability4
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
Maintainability5
Readability4
Code Complexity Index4
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
Maintainability5
Readability4
Code Complexity Index4
Usability4
Flexibility
Learning Curve
Least Knowledge

Flexibility

Behaviour Based Tests Classes

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
Maintainability5
Readability4
Code Complexity Index4
Usability4
Flexibility5
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
Maintainability5
Readability4
Code Complexity Index4
Usability4
Flexibility5
Learning Curve4
Least Knowledge

Least Knowledge

You pass only the required parameters to the concrete behaviours. So the rating is marked as excellent.

Behaviour Based Tests
Maintainability5
Readability4
Code Complexity Index4
Usability4
Flexibility5
Learning Curve4
Least Knowledge5

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

Related Articles

Design Architecture

Handling Test Environments Data in Automated Tests

In this article part of the Design & Architecture Series, we will talk about handling environments' test data in automated tests. We will discuss why hard-codin

Handling Test Environments Data in Automated Tests

Design Architecture

Assessment System for Evaluating Test Automation Solutions

What is the primary task of many software engineers in test nowadays? It is to develop or find the right test automation solution for achieving fast, reliable,

Assessment System for Evaluating Test Automation Solutions

Design Architecture

Defining High-Quality Test Attributes for Automated Tests

To be able to write high-quality automated tests, more knowledge is needed than just knowing how to program in a certain language or use a specific framework. T

Defining High-Quality Test Attributes for Automated Tests

Design Architecture

How to Write Good Bug Reports And Gather Quality Metrics Data

One of the essential tasks every QA engineer should master is how to log bug reports properly. Many people are confused about what information to include in suc

How to Write Good Bug Reports And Gather Quality Metrics Data

Design Architecture

Assessment System for Tests&#8217; Architecture Design

Usually, people want to improve their tests but do not have quality metrics to determine which version of their improvements is most beneficial to their project

Assessment System for Tests&#8217; Architecture Design

Design Architecture

Generations of Test Automation Frameworks- Past and Future

In the last publication from the Design & Architecture Series, we talked about what is a test automation framework and discussed all related terms. Here, we wil

Generations of Test Automation Frameworks- Past and Future
Anton Angelov

About the author

Anton Angelov is Managing Director, Co-Founder, and Chief Test Automation Architect at Automate The Planet — a boutique consulting firm specializing in AI-augmented test automation strategy, implementation, and enablement. He is the creator of BELLATRIX, a cross-platform framework for web, mobile, desktop, and API testing, and the author of 8 bestselling books on test automation. A speaker at 60+ international conferences and researcher in AI-driven testing and LLM-based automation, he has been recognized as QA of the Decade and Webit Changemaker 2025.