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

Facade Design Pattern in Automation Testing

5.00/5 (7 votes)
3 Aug 2015Ms-PL5 min read 14.3K  
Explains in details how to implement Facade Design Pattern. Use it to follow all SOLID principles and best programming practices.

Introduction

In my series of articles “Design Patterns in Automation Testing“, I am presenting you the most useful techniques for structuring the code of the automation tests. Today’s publication is going to be about the Facade Design Pattern. In my two previous posts, I have explained how to use the most famous pattern- Page Object Pattern. The Facade Design Pattern can bring even more abstraction over the page objects, so if you are not familiar with them, I advise you to read my articles on the matter.

Definition

An object that provides a simplified interface to a larger body of code, such as class library.

  • Make a software library easier to use, understand and more readable
  • Reduce dependencies of outside code
  • Keeps the Principle of least knowledge
  • Wrap a poorly designed APIs in a better one

UML Class Diagram

Participants

The classes and objects participating in this pattern are:

  • Facade – Holds methods that combine actions executed on multiple pages.
  • Page Objects (ItemPage)- Holds the actions that can be performed on the page like Search and Navigate. Exposes an easy access to the Page Validator though the Validate() method. The best implementations of the pattern hide the usage of the Element Map, wrapping it through all action methods.
  • UI Tests (EbayPurchaseTests) – This class contains a group of tests related to the above facade; it can hold only a single instance of the facade.

Facade Design Pattern C# Code

Test’s Test Case

The primary goal of the below tests is going to be to purchase different items from Ebay. They need to make sure that the correct prices are displayed on the different pages.

  1. Navigate to Item’s Page:

  2. Validate the price.
  3. Click Buy It Now button.
  4. On the SignIn page, click Continue as a guest.

  5. Fill Shipping Info:

  6. Validate Subtotal price.
  7. Click Continue button.
  8. Validate Total price.

The primary goal of the design of the test classes is going to be to enable us to reuse the code for all different test cases. For example, purchasing different items with a different combination of shipping data, thus different total and subtotal prices.

Facade Design Pattern C# Code

The following class structure is going to be used.

There is nothing unusual in the most of the page objects. Probably, the most interesting logic is located in the ShippingAddressPage.

C#
public class ShippingAddressPage : BasePage<ShippingAddressPageMap, ShippingAddressPageValidator>
{
    public void ClickContinueButton()
    {
        this.Map.ContinueButton.Click();
    }

    public void FillShippingInfo(ClientInfo clientInfo)
    {
        this.Map.SwitchToShippingFrame();
        this.Map.CountryDropDown.SelectByText(clientInfo.Country);
        this.Map.FirstName.SendKeys(clientInfo.FirstName);
        this.Map.LastName.SendKeys(clientInfo.LastName);
        this.Map.Address1.SendKeys(clientInfo.Address1);
        this.Map.City.SendKeys(clientInfo.City);
        this.Map.Zip.SendKeys(clientInfo.Zip);
        this.Map.Phone.SendKeys(clientInfo.Phone);
        this.Map.Email.SendKeys(clientInfo.Email);
        this.Map.SwitchToDefault();
    }
}

There are two public methods. The FillShippingInfo uses the data class ClientInfo to fill in the current client’s info.

The ClientInfo class holds only string properties.

C#
public class ClientInfo
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Country { get; set; }
    public string Address1 { get; set; }
    public string City { get; set; }
    public string Phone { get; set; }
    public string Zip { get; set; }
    public string Email { get; set; }
}

Before the engine can start typing the information, the shipping frame should be switched to first. Otherwise, our test is going to fail. This logic is located in the ShippingAddressMap class.

C#
public class ShippingAddressPageMap : BasePageElementMap
{
    public SelectElement CountryDropDown
    {
        get
        {
            this.browserWait.Until<IWebElement>((d) => 
            { return d.FindElement(By.Name("country")); });
            return new SelectElement(this.browser.FindElement(By.Name("country")));
        }
    }

    public IWebElement FirstName
    {
        get
        {
            return this.browser.FindElement(By.Id("firstName"));
        }
    }

    public IWebElement LastName
    {
        get
        {
            return this.browser.FindElement(By.Id("lastName"));
        }
    }

    public IWebElement Address1
    {
        get
        {
            return this.browser.FindElement(By.Id("address1"));
        }
    }

    public IWebElement City
    {
        get
        {
            return this.browser.FindElement(By.Id("city"));
        }
    }

    public IWebElement Zip
    {
        get
        {
            return this.browser.FindElement(By.Id("zip"));
        }
    }

    public IWebElement Phone
    {
        get
        {
            return this.browser.FindElement(By.Id("dayphone1"));
        }
    }

    public IWebElement Email
    {
        get
        {
            return this.browser.FindElement(By.Id("email"));
        }
    }

    public IWebElement Subtotal
    {
        get
        {
            return this.browser.FindElement(By.Id("xo_tot_amt"));
        }
    }

    public IWebElement ContinueButton
    {
        get
        {
            return this.browser.FindElement(By.Id("but_address_continue"));
        }
    }

    public void SwitchToShippingFrame()
    {
        this.WaitForLogo();
        this.browser.SwitchTo().Frame("shpFrame");
    }

    private void WaitForLogo()
    {
        this.browserWait.Until<IWebElement>((d) => { return d.FindElement(By.Id("gh-logo")); });
    }
}

In order for the switch frame command to be successful, a wait operation is performed. The logo of the page is located outside of the frame, so its waiting guarantees that the page is completely loaded.

Tests without Facade Design Pattern

If we desire to perform two different tests - buy two separate products with varying information. We can perform them only with the above classes without a Facade class.

C#
[TestClass]
public class EbayPurchase_Without_PurchaseFaceade_Tests
{       
    [TestInitialize]
    public void SetupTest()
    {
        Driver.StartBrowser();
    }

    [TestCleanup]
    public void TeardownTest()
    {
        Driver.StopBrowser();
    }

    [TestMethod]
    public void Purchase_Casio_GShock()
    {
        string itemUrl = "Casio-G-Shock-Standard-GA-100-1A2-Mens-Watch-Brand-New-/
                          161209550414?pt=LH_DefaultDomain_15&hash=item2588d6864e";
        string itemPrice = "AU $168.00";
        ClientInfo currentClientInfo = new ClientInfo()
        {
            FirstName = "Anton",
            LastName = "Angelov",
            Country = "Bulgaria",
            Address1 = "33 Alexander Malinov Blvd.",
            City = "Sofia",
            Zip = "1729",
            Phone = "0035964644885",
            Email = "aangelov@yahoo.com"
        };
        ItemPage itemPage = new ItemPage();
        CheckoutPage checkoutPage = new CheckoutPage();
        ShippingAddressPage shippingAddressPage = new ShippingAddressPage();
        SignInPage signInPage = new SignInPage();

        itemPage.Navigate(itemUrl);
        itemPage.Validate().Price(itemPrice);
        itemPage.ClickBuyNowButton();
        signInPage.ClickContinueAsGuestButton();
        shippingAddressPage.FillShippingInfo(currentClientInfo);
        shippingAddressPage.Validate().Subtotal(itemPrice);
        shippingAddressPage.ClickContinueButton();
        checkoutPage.Validate().Subtotal(itemPrice);
    }

    [TestMethod]
    public void Purchase_WhiteOpticalKeyboard()
    {
        string itemUrl = "Wireless-White-2-4G-Optical-Keyboard-and-Mouse-USB-Receiver-Kit-For-PC-/
                          360649772948?pt=LH_DefaultDomain_2&hash=item53f866cf94";
        string itemPrice = "C $20.86";
        ClientInfo currentClientInfo = new ClientInfo()
        {
            FirstName = "Anton",
            LastName = "Angelov",
            Country = "Bulgaria",
            Address1 = "33 Alexander Malinov Blvd.",
            City = "Stara Zagora",
            Zip = "6000",
            Phone = "0035964644885",
            Email = "aangelov@yahoo.com"
        };
        ItemPage itemPage = new ItemPage();
        CheckoutPage checkoutPage = new CheckoutPage();
        ShippingAddressPage shippingAddressPage = new ShippingAddressPage();
        SignInPage signInPage = new SignInPage();

        itemPage.Navigate(itemUrl);
        itemPage.Validate().Price(itemPrice);
        itemPage.ClickBuyNowButton();
        signInPage.ClickContinueAsGuestButton();
        shippingAddressPage.FillShippingInfo(currentClientInfo);
        shippingAddressPage.Validate().Subtotal(itemPrice);
        shippingAddressPage.ClickContinueButton();
        checkoutPage.Validate().Subtotal(itemPrice);
    }
}

As you can see, the main problem in the examples is that we need to create instances of our pages for every test. Moreover, the whole workflow of the tests as method calls is copied. Practices mentioned above make our tests much harder to maintain. Also, it brakes one of the most important programming principles- DRY (Don’t-Repeat-Yourself).

By the way, during my research for the "Design Patterns in Automation Testing" series, I always first read about the presented pattern in several books. One of them that you might want to check is "Head First Design Patterns" by Eric Freeman. The author uses a very unique methodology for presenting the material that I haven't found anywhere else. Probably most of you will like it. For the more hardcore fans that might find the book too easy, I recommend the bible of the design patterns- "Design Patterns- Elements of Reusable Object-Oriented Software". It will change your way of thinking about object-oriented design.

Tests Using Facade Design Pattern

The solution of the above problems is to encapsulate our test’s logic/workflow in a Facade class.

C#
public class PurchaseFacade
{
    private ItemPage itemPage;
    private CheckoutPage checkoutPage;
    private ShippingAddressPage shippingAddressPage;
    private SignInPage signInPage;

    public ItemPage ItemPage 
    {
        get
        {
            if (itemPage == null)
            {
                itemPage = new ItemPage();
            }
            return itemPage;
        }
    }

    public SignInPage SignInPage
    {
        get
        {
            if (signInPage == null)
            {
                signInPage = new SignInPage();
            }
            return signInPage;
        }
    }

    public CheckoutPage CheckoutPage
    {
        get
        {
            if (checkoutPage == null)
            {
                checkoutPage = new CheckoutPage();
            }
            return checkoutPage;
        }
    }

    public ShippingAddressPage ShippingAddressPage
    {
        get
        {
            if (shippingAddressPage == null)
            {
                shippingAddressPage = new ShippingAddressPage();
            }
            return shippingAddressPage;
        }
    }

    public void PurchaseItem(string item, string itemPrice, ClientInfo clientInfo)
    {
        this.ItemPage.Navigate(item);
        this.ItemPage.Validate().Price(itemPrice);
        this.ItemPage.ClickBuyNowButton();
        this.SignInPage.ClickContinueAsGuestButton();
        this.ShippingAddressPage.FillShippingInfo(clientInfo);
        this.ShippingAddressPage.Validate().Subtotal(itemPrice);
        this.ShippingAddressPage.ClickContinueButton();
        this.CheckoutPage.Validate().Subtotal(itemPrice);
    }
}

In case the workflow of the test case is changed, it can be quickly updated only in a single place. Or if you want to add additional validations, they can be added to the PurchaseItem method.

Find below the code of the same tests refactored to use the Facade Design Pattern.

C#
[TestClass]
public class EbayPurchase_PurchaseFaceade_Tests
{       
    [TestInitialize]
    public void SetupTest()
    {
        Driver.StartBrowser();
    }

    [TestCleanup]
    public void TeardownTest()
    {
        Driver.StopBrowser();
    }

    [TestMethod]
    public void Purchase_Casio_GShock()
    {
        string itemUrl = "Casio-G-Shock-Standard-GA-100-1A2-Mens-Watch-Brand-New-/
                          161209550414?pt=LH_DefaultDomain_15&hash=item2588d6864e";
        string itemPrice = "AU $168.00";
        ClientInfo currentClientInfo = new ClientInfo()
        {
            FirstName = "Anton",
            LastName = "Angelov",
            Country = "Bulgaria",
            Address1 = "33 Alexander Malinov Blvd.",
            City = "Sofia",
            Zip = "1729",
            Phone = "0035964644885",
            Email = "aangelov@yahoo.com"
        };
        new PurchaseFacade().PurchaseItem(itemUrl, itemPrice, currentClientInfo);
    }

    [TestMethod]
    public void Purchase_WhiteOpticalKeyboard()
    {
        string itemUrl = "Wireless-White-2-4G-Optical-Keyboard-and-Mouse-USB-Receiver-Kit-For-PC-/
                          360649772948?pt=LH_DefaultDomain_2&hash=item53f866cf94";
        string itemPrice = "C $20.86";
        ClientInfo currentClientInfo = new ClientInfo()
        {
            FirstName = "Anton",
            LastName = "Angelov",
            Country = "Bulgaria",
            Address1 = "33 Alexander Malinov Blvd.",
            City = "Stara Zagora",
            Zip = "6000",
            Phone = "0035964644885",
            Email = "aangelov@yahoo.com"
        };
        new PurchaseFacade().PurchaseItem(itemUrl, itemPrice, currentClientInfo);
    }
}

So Far in the "Design Patterns in Automated Testing" Series

  1. Page Object Pattern
  2. Advanced Page Object Pattern
  3. Facade Design Pattern
  4. Singleton Design Pattern
  5. Fluent Page Object Pattern
  6. IoC Container and Page Objects
  7. Strategy Design Pattern
  8. Advanced Strategy Design Pattern
  9. Observer Design Pattern
  10. Observer Design Pattern via Events and Delegates
  11. Observer Design Pattern via IObservable and IObserver
  12. Decorator Design Pattern- Mixing Strategies
  13. Page Objects That Make Code More Maintainable
  14. Improved Facade Design Pattern in Automation Testing v.2.0
  15. Rules Design Pattern
  16. Specification Design Pattern
  17. Advanced Specification Design Pattern

If you enjoy my publications, feel free to SUBSCRIBE.
Also, hit these share buttons. Thank you!

Source Code

References

The post- Facade Design Pattern in Automation Testing appeared first on Automate The Planet.

License

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