In my series of articles “Design Patterns in Automated Testing“, I am presenting you the most useful techniques for structuring the code of the automation tests. The today’s publication is about the Singleton Design Pattern. In my previous posts, I have explained how to use the Page Object and Facade Design Patterns. If you are not familiar with them, I advise you to read my articles on the matter. The Singleton Design Pattern can be used in the automation tests to build up easier access to page objects and facades. Its usage can speed up the tests writing process dramatically. In this article, I am going to show you the best and most straightforward approaches to integrating the Singleton Design Pattern in your test automation framework.



Definition Instance control – prevents other objects from instantiating their own copies of the Singleton object, ensuring that all objects access the single instance.

– prevents other objects from instantiating their own copies of the Singleton object, ensuring that all objects access the single instance. Flexibility – since the class controls the instantiation process, the class has the flexibility to change the instantiation process.

– since the class controls the instantiation process, the class has the flexibility to change the instantiation process. Lazy initialization– defers the object’s creation until it is first used. Ensure a class has only one instance and provide a global point of access to it.

UML Class Diagram

Participants

The classes and objects participating in this pattern are:

Page Objects (SearchEngineMainPage)- Holds the actions that can be performed on the page like Search and Navigate. Exposes an easy access to the Page Validator through the Validate () method. The best implementations of the pattern hide the usage of the Element Map, wrapping it through all action methods.

(SearchEngineMainPage)- Holds the actions that can be performed on the page like Search and Navigate. Exposes an easy access to the Page Validator through the () method. The best implementations of the pattern hide the usage of the wrapping it through all action methods. BasePage<S, M> – Gives access to the child’s page element map class and defines a standard navigation operation.

– Gives access to the child’s page element map class and defines a standard navigation operation. BasePage<S, M, V> – Adds an instance to the child page’s validator class through the Validate method.

– Adds an instance to the child page’s validator class through the method. BaseSingleton – This is an abstract class that contains a static property of its child instance BaseSingleton – This is an abstract class that provides a static property of its child instance.

Singleton Design Pattern C# Code

Create Singleton in BasePage

The most straightforward way to integrate the Singleton Design Pattern in all of your existing page objects is to add a static variable and property in the BasePage class. If you are not familiar what the BasePage classes are, refer to my article- Advanced Page Object Pattern in Automation Testing.

The drawback of the above solution is that you cannot reuse the singleton implementation for your Facade classes. The answer to the mentioned problem is to create a base generic singleton class that can be derived from all pages and facades.

Non-thread-safe BaseSingleton Class

Find below, the most trivial implementation of the generic base class for the Singleton Design Pattern.

In most scenarios for automation tests, this solution should be sufficient. However, this implementation is not thread-safe. To be possible to execute tests in parallel, I am going to propose you other variations of the base class that are thread-safe.

For more detailed overview and usage of many more design patterns and best practices in automated testing, check my book “Design Patterns for High-Quality Automated Tests, C# Edition, High-Quality Tests Attributes, and Best Practices“. You can read part of three of the chapters:

Defining High-Quality Test Attributes for Automated Tests

Benchmarking for Assessing Automated Test Components Performance

Generic Repository Design Pattern- Test Data Preparation

Thread-safe BaseSingleton Class with Lock

Here, I am using a lock statement that ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block until the object is released. As you can see the code doesn’t lock the T instance, instead it locks its internal object. This is done to prevent deadlocks.

Thread-safe BaseSingleton Class with Lazy

The built-in .NET framework generic class Lazy<T> saves some code for implementing the lazy initialization. Also, it is thread-safe.

Thread-safe BaseSingleton Class with Nested Classes

The most complicated variation of the base class implementing Singleton Design Pattern uses nested classes and reflection.

The nested class contains static constructor to tell the C# compiler not to mark the type as before-field-init. Now the BasePage classes should not have constructors to follow the Singleton Design Pattern, because of that the new() class constraint is removed.

The structure of the base classes for the Page Object Pattern should be slightly changed due to the earlier mentioned reason.

One of the significant changes in the code is the new S generic parameter that represents the type of the child page which is going to be initialized. Also, you can notice the absence of constructors and that the both classes are marked as abstract.

The page object class that derives from these classes can look like the following.

I want to emphasize that the constructor of this class is marked as private, which prevents the creation of a default constructor.

Tests Using Singleton Design Pattern

Now you can use the page objects directly in your code without the keyword new, thanks to the singleton design pattern.