Assessment System for Tests’ Architecture Design- Facade Based Tests

Assessment System for Tests’ Architecture Design- Facade 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 first type of tests that we will assess is the facade based tests. If you are not familiar with the Facade Design Pattern, you can check my article Improved Facade Design Pattern in Automated Testing v.2.0.

Facade Based Tests

The initial versions of our tests framework utilized the façade design pattern. This is the first design that we are going to evaluate through the proposed assessment system. A facade is an object that provides a simplified interface to a larger body of code, such as a class library. It makes the software library easier to use and understand, is more readable, and reduces dependencies on external or other code.

Regions in Facades

There are not any real drawbacks, as it provides a unified interface to a set of interfaces in a subsystem. However, the biggest problem for us was the size of the facade files. They got enormous, like thousands of lines of code. We had to use regions inside to separate the different parts of the code. Regions let you specify a block of code that you can expand or collapse when using the outlining feature of the Visual Studio Code Editor. As depicted in the image, in the Billing facade, four different regions were used for separating the element map properties, the private fields, and the rest of the methods.

Regions Facades

Improved Facade Design Pattern

This is the code of our shopping cart facade responsible for creating purchases. We decided to use the facade design pattern in a little different way. It combines the different pages’ methods to complete the wizard of the order. If there is a change in the order of the executed actions I can edit it only here. It will apply to tests that are using the facade. The different test cases are accomplished through the different parameters passed to the facade’s methods. These types of facades contain a much less code because most of the logic is held by the pages instead of the facade itself.

public class ShoppingCart
{
    private readonly ItemPage itemPage;
    private readonly PreviewShoppingCartPage previewShoppingCartPage;
    private readonly SignInPage signInPage;
    private readonly ShippingAddressPage shippingAddressPage;
    private readonly ShippingPaymentPage shippingPaymentPage;
    private readonly PlaceOrderPage placeOrderPage;
    public ShoppingCart(
    ItemPage itemPage,
    PreviewShoppingCartPage previewShoppingCartPage,
    SignInPage signInPage,
    ShippingAddressPage shippingAddressPage,
    ShippingPaymentPage shippingPaymentPage,
    PlaceOrderPage placeOrderPage)
    {
        this.itemPage = itemPage;
        this.previewShoppingCartPage = previewShoppingCartPage;
        this.signInPage = signInPage;
        this.shippingAddressPage = shippingAddressPage;
        this.shippingPaymentPage = shippingPaymentPage;
        this.placeOrderPage = placeOrderPage;
    }
    public void PurchaseItem(
    string itemUrl,
    string itemPrice,
    ClientLoginInfo clientLoginInfo,
    ClientPurchaseInfo clientPurchaseInfo)
    {
        this.itemPage.Navigate(itemUrl);
        this.itemPage.ClickBuyNowButton();
        this.previewShoppingCartPage.ClickProceedToCheckoutButton();
        this.signInPage.Login(clientLoginInfo.Email, clientLoginInfo.Password);
        this.shippingAddressPage.FillShippingInfo(clientPurchaseInfo);
        this.shippingAddressPage.ClickDifferentBillingCheckBox(clientPurchaseInfo);
        this.shippingAddressPage.ClickContinueButton();
        this.shippingPaymentPage.ClickBottomContinueButton();
        this.shippingAddressPage.FillBillingInfo(clientPurchaseInfo);
        this.shippingAddressPage.ClickContinueButton();
        this.shippingPaymentPage.ClickTopContinueButton();
        double totalPrice = double.Parse(itemPrice);
        this.placeOrderPage.AssertOrderTotalPrice(totalPrice);
    }
}

Usage in Tests

This is a sample usage of the facade in tests. First we need to initialize all required parameters. After that you simply call the main workflow’s method.


public void Purchase_ShoppingCartFacade()
{
    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"
    };
    var shoppingCart = container.Resolve<ShoppingCart>();
    shoppingCart.PurchaseItem(itemUrl, itemPrice, clientLoginInfo, clientPurchaseInfo);
}

Facade Design Pattern 

Pros and Cons

  • Hide complex logic
  • Simplify tests' creation
  • Workflow's changes- single place
  • Enormous files
  • Huge constructors
  • Not clear tests' workflow from test's body
  • Affect a large number of tests
  • Hard to orient- new people

Evaluate Facade Based Tests- Assessment System

Maintainability

public void PurchaseItem(
string itemUrl,
string itemPrice,
ClientLoginInfo clientLoginInfo,
ClientPurchaseInfo clientPurchaseInfo)
{
    this.itemPage.Navigate(itemUrl);
    this.itemPage.ClickBuyNowButton();
    this.previewShoppingCartPage.ClickProceedToCheckoutButton();
    this.signInPage.Login(clientLoginInfo.Email, clientLoginInfo.Password);
    this.shippingAddressPage.FillShippingInfo(clientPurchaseInfo);
    this.shippingAddressPage.ClickDifferentBillingCheckBox(clientPurchaseInfo);
    this.shippingAddressPage.ClickContinueButton();
    this.shippingPaymentPage.ClickBottomContinueButton();
    this.shippingAddressPage.FillBillingInfo(clientPurchaseInfo);
    this.shippingAddressPage.ClickContinueButton();
    this.shippingPaymentPage.ClickTopContinueButton();
    double totalPrice = double.Parse(itemPrice);
    this.placeOrderPage.AssertOrderTotalPrice(totalPrice);
}

The maintainability is Very Good (4). The troubleshooting and adding new features to the facades is straightforward. However, the rating is not marked as Excellent because you can easily introduce a regression in the existing tests with small changes in the facade.

Facade Based Tests
Maintainability4
Readability
Code Complexity Index
Usability
Flexibility
Learning Curve
Least Knowledge

Readability

var shoppingCart = container.Resolve<ShoppingCart>();
shoppingCart.PurchaseItem(itemUrl, itemPrice, clientLoginInfo, clientPurchaseInfo);

The readability is evaluated as Poor (2). The tests contain much less code compared to all other solutions. However, as you call only a single method from the facade in the tests, it is not clear to the user what this method is doing under the hood. Further, due to their large sizes, the facades are relatively unreadable and it is not an easy job to find something inside them.

Facade Based Tests
Maintainability4
Readability2
Code Complexity Index
Usability
Flexibility
Learning Curve
Least Knowledge

Code Complexity Index

The facade classes have a poor (3) index because they are large in size and they depend on lots of other classes such as other facades and lots of pages. On the opposite, the tests’ classes are fairly short in size and call only the facade itself.

Facade Based Tests
Maintainability4
Readability2
Code Complexity Index3
Usability
Flexibility
Learning Curve
Least Knowledge

Usability

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"
};

The usability is Very Good (4). The writing of new tests is straightforward. The rating is not Excellent just because the user has to initialize the tests context upfront.

Facade Based Tests
Maintainability4
Readability2
Code Complexity Index3
Usability4
Flexibility
Learning Curve
Least Knowledge

Flexibility

public void PurchaseItem(
string itemUrl,
string itemPrice,
ClientLoginInfo clientLoginInfo,
ClientPurchaseInfo clientPurchaseInfo)
{
    this.itemPage.Navigate(itemUrl);
    this.itemPage.ClickBuyNowButton();
    this.previewShoppingCartPage.ClickProceedToCheckoutButton();
    this.signInPage.Login(clientLoginInfo.Email, clientLoginInfo.Password);
    this.shippingAddressPage.FillShippingInfo(clientPurchaseInfo);
    this.shippingAddressPage.ClickDifferentBillingCheckBox(clientPurchaseInfo);
    this.shippingAddressPage.ClickContinueButton();
    this.shippingPaymentPage.ClickBottomContinueButton();
    this.shippingAddressPage.FillBillingInfo(clientPurchaseInfo);
    this.shippingAddressPage.ClickContinueButton();
    this.shippingPaymentPage.ClickTopContinueButton();
    double totalPrice = double.Parse(itemPrice);
    this.placeOrderPage.AssertOrderTotalPrice(totalPrice);
}

The flexibility is Very Poor (1). If you change some of the existing workflows, you will affect all existing tests and possibly create regression issues. If you need to create custom workflow you have to add custom public workflow method which makes the already large facade even bigger. You cannot change or customise the already constructed workflows on a test level.

Facade Based Tests
Maintainability4
Readability2
Code Complexity Index3
Usability4
Flexibility1
Learning Curve
Least Knowledge

Learning Curve

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"
};
var shoppingCart = container.Resolve<ShoppingCart>();
shoppingCart.PurchaseItem(itemUrl, itemPrice, clientLoginInfo, clientPurchaseInfo);

There are two tricky parts with the approach. First, you should know how to initialize the test context correctly. Secondly, if there are multiple public workflow methods, you should be aware which is the most appropriate to call.

Facade Based Tests
Maintainability4
Readability2
Code Complexity Index3
Usability4
Flexibility1
Learning Curve3
Least Knowledge

Least Knowledge

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"
};
var shoppingCart = container.Resolve<ShoppingCart>();
shoppingCart.PurchaseItem(itemUrl, itemPrice, clientLoginInfo, clientPurchaseInfo);

The facade has access to the whole test context which is usually enormous in size. Not all methods need all of the information present in the test context. Because of that the rating is marked as poor (2).

Facade Based Tests
Maintainability4
Readability2
Code Complexity Index3
Usability4
Flexibility1
Learning Curve3
Least Knowledge2

In my next article from the series, I will use the assessment system to evaluate the behavior 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

Benchmarking for Assessing Automated Test Components Performance

The evaluation of core quality attributes is not enough to finally decide which implementation is better or not. The test execution time should be a key compone

Benchmarking for Assessing Automated Test Components Performance

Design Architecture, Design Patterns

Highlight Elements on Action- Test Automation Framework Extensibility through Observer Design Pattern

As you know, in past articles from the Design and Architecture Series I wrote about the 5th generation test automation frameworks or as I like to call them Full

Highlight Elements on Action- Test Automation Framework Extensibility through Observer Design Pattern

Design Architecture

Full-Stack Test Automation Frameworks- API Usability Part 2

In the last article from the series, we talked about API usability, one of the must-have features of the full-stack test automation frameworks. Here I am going

Full-Stack Test Automation Frameworks- API Usability Part 2

Design Architecture

What Is a Test Automation Framework?

In the Design & Architecture Series, we usually discuss themes how you can make your test automation framework better. However, I realized that many people have

What Is a Test Automation Framework?

Design Architecture

Full-Stack Test Automation Frameworks- API Usability Part 1

In one of the last articles from the series, we talked about tons of problems that modern test automation frameworks should be able to solve. The full-stack tes

Full-Stack Test Automation Frameworks- API Usability Part 1

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.