Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Assessment System for Tests Architecture Design- Behaviour Based Tests

5.00/5 (3 votes)
26 Mar 2017Ms-PL5 min read 5K  
We will use the previously presented assessment framework to evaluate tests that use the Behaviour Pattern. Find the ratings and reasoning behind them.

Introduction

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 behavior based tests (lego based tests). If you are not familiar with the Behavior Design Pattern (Lego Design Pattern), you can check my article Advanced Behaviors Design Pattern in Automated Testing Part 2.

Behavior Based Tests

Abstract Behavior

C#
public abstract class WaitableActionBehaviour : IBehaviour
{
    public void Execute()
    {
        this.PerformAct();
        this.PerformPostActWait();
    }

    protected abstract void PerformAct();

    protected abstract void PerformPostActWait();
}

In general, one behavior executes a page specific workflow- performs actions and waits for a condition. There are different types of behaviors- 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 behaviors that first execute an action and then wait for something to happen.

Concrete Behavior

C#
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 behavior 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 behaviors hold private instances of all dependent pages or other services. There are initialized in the behaviors constructors through Unity IoC container.

Behavior with Parameters

C#
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 behaviors can accept custom parameters if needed.

Behaviors Usage in Tests

C#
[TestMethod]
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 behaviors are added as a list to a special behaviors executor that is responsible for executing them in the appropriate way. If the behavior depends on any data, it is passed to its constructor.

Behaviors Design Pattern Pros

  • Readable
  • See granularly workflow's steps

If you do not want to perform some of the asserts mini-workflows, you just do not include its behavior in the list. The principle of least knowledge is followed because you pass only the required data to the behaviors' constructors.

Behaviors Design Pattern Cons

A lot of new classes are introduced. The writing of new tests is slower because now you have to initialize all required behaviors. The process of test writing is more error prompt because you can mistake the steps' order or assign wrong values to some of the behaviors' parameters.

Evaluate Behavior Based Tests- Assessment System

Maintainability

C#
[Binding]
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 behaviors are mini-workflows for some use cases. If the use case should be changed, it is edited only here. As the behaviors are added only on demand, there are not executed for every case. If you fix one behavior, the change will affect only the tests that are using it.

 Behavior Based Tests
Maintainability5
Readability 
Code Complexity Index 
Usability 
Flexibility 
Learning Curve 
Least Knowledge 

Readability

C#
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 behaviors are self-describing, you can guess their use case. Moreover, as you list multiple behaviors to define the bigger workflow, the order of the steps is directly visible to the reader.

 Behavior Based Tests
Maintainability5
Readability4
Code Complexity Index 
Usability 
Flexibility 
Learning Curve 
Least Knowledge 

Code Complexity Index

The behavior classes are small and simple. However, the tests classes are more complex because you need to initialize the whole behaviors' execution chain.

 Behavior Based Tests
Maintainability5
Readability4
Code Complexity Index4
Usability 
Flexibility 
Learning Curve 
Least Knowledge 

Usability

C#
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 test framework API is not so complicated to be used. However, you should know the exact name of the behaviors 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.

 Behavior Based Tests
Maintainability5
Readability4
Code Complexity Index4
Usability 
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 behavior and add it to the list of behaviors for this particular case.

 Behavior 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 behaviors. Moreover, he/she should be familiar with the correct names of all behaviors and which exact implementation want to call. There might be more than one implementation where it is slightly different.

 Behavior Based Tests
Maintainability5
Readability4
Code Complexity Index4
Usability4
Flexibility5
Learning Curve4
Least Knowledge 

Least Knowledge

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

 Behavior 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.

Design & Architecture

The post Assessment System for Tests - Architecture Design - Behavior Based Tests appeared first on Automate The Planet.

All images are purchased from DepositPhotos.com and cannot be downloaded and used for free.
License Agreement

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)