One of the automation test challenges is how to save effort in maintaining code, and this effort will depend on the way we organize our automation framework or apply best practices in writing test scripts or capturing robust locator. Embracing design patterns when building the automation framework can streamline maintenance by promoting organization and eliminating redundant code. However, implementing design patterns requires a solid understanding of programming and Object-Oriented Programming (OOP). In this article, I will elucidate how to incorporate several popular design patterns into automation testing to enhance efficiency and effectiveness.
1. Page object model

I believe that it’s the most popular design pattern with all automation tester. With this design pattern, all the elements and methods of a page will be stored in a class. The test case will use the page object methods instead of calling the method of the automation tool directly. It will help us to avoid duplicated code in test cases file. Moreover, when we divide the application pages into the page object classes, it’s much easier to maintain or adding new method related to a page. Please see the below picture for example of page object class.

This is how we utilize it in the test case, and you will find that the steps are straightforward to comprehend.

2. Factory
The Factory pattern is widely adopted as a design pattern for object creation. In automation testing, we can leverage the Factory pattern to initialize new WebDriver instances. Without applying the Factory design pattern, the function responsible for initializing a new WebDriver could become lengthy and challenging to extend. The sample code below demonstrates this scenario.

By implementing the Factory pattern in this context, we can enhance the code’s readability and extensibility.

Test case will initialize browser through the browser factory. We will define an interface for the browser with a method called CreateInstance. Additionally, we will create several classes, such as Chrome, Firefox, and Edge, which implement the browser interface. Here is the code for the interface.

Below is the sample code for the implementation of the IDriverSetUp interface, specifically for ChromeDriverSetup

With the implementation of the Factory pattern in the Browser Factory class, the code becomes much simpler, and adding a new kind of browser for testing becomes significantly easier.

3. Façade
The Façade design pattern is a popular structural pattern that aids in creating a simplified interface for a complex subsystem, encompassing numerous actions within it. In automation testing, we often encounter scenarios where multiple test cases share the same steps, leading to duplicated code. Consequently, any modification to these steps necessitates updates to all affected test cases. Applying Façade can help us save the effort for updating the test case.
Let’s say we have an e-commerce application, and we have a list of test cases related to order such as creating order, editing order, canceling order…To make sure all the test cases can be run independently, we need the steps to create an order for each test case. The script maybe looks like the below picture.

You can see a lot of test steps are duplicated here, so we can apply Factory pattern here to avoid this. All the steps related to create a new order will be implemented in the PurchaseItemFacade class.

The test cases are now simpler. If there is any change in the creating order flow, we only need to update the function purchaseItem of PurchaseItemFacade class.

4. Singleton
If you want to make sure that there is only 1 instance of a class in your project, Singleton can support us to do that. In automation test, we can apply this to manage the instance of page object class. If you’re testing database, we also can use it to make that only 1 connection to the database is establish. To implement this design pattern, in the page object class we can define a static variable and the getInstance method as below.

In the test case, we’ll use the page object as below.

It will help us avoid creating too many instances of a page object class in the test cases.
5. Conclusion
Apply design pattern supports us to save time for code maintenance, and we can also apply many other kinds of design patterns in your automation project. However, we need to care about the ability of our team in programming and OOP skill. If we’re not strong at these skills, the script will be complicated for us to understand.
Reference: https://refactoring.guru/design-patterns