The latest post of the Huddle Selenium series.
Each month on the first Tuesday of the month, we will post a new blog post to take you through a step-by-step guide on how to address a particular aspect of using Selenium as part of our How To series. This post continues Anton’s guide on using Page Objects with Selenium.
This is the seventh article from the WebDriver Page Objects Series. I am going to share with you how to create only once your pages and afterwards reuse them. To do that we are going to use the Singleton Design Pattern.
If you are using WebDriver often, you may find useful my Most Complete Selenium WebDriver C# Cheat Sheet. All you need to know- the most basic operations to the most advanced configurations.
Test Case
We will once again automate the main Bing page. All of the code is placed inside the BingMainPage class.
Initial Version Non-Singleton Page Objects
First, let us see how a regular non-singleton page object looks like and how we use it in tests. Then we are going to refactor it and make it singleton.
BingMainPage.Actions Non-Singleton Version
BingMainPage.Elements Non-Singleton Version
BingMainPage.Asserts Non-Singleton Version
BingMainPage Non-Singleton Version in Tests
The drawback of this approach is that we need every time to initialise our pages. Here the constructor of the page takes only a single parameter, but sometimes there are more parameters. If we use this kind of initialisation in lots of tests, later changes in the tests will be harder and more error prompt. Moreover, since the pages are stateless, we do not need to initialise them multiple times since the elements are always located in the current browser instance.
Second Version Singleton Page Objects
BingMainPage.Actions Singleton Version
The only change compared to the previous version is that BingMainPage derive now from the WebPage generic abstract base class. The whole Singleton magic is hidden there.
WebPage
To learn more about the basics of the Singleton design pattern you can read my article- Singleton Design Pattern in Automated Testing.
We hold here a static instance of our page. We create it only once, afterwards each time we request the instance we return the already created value. The built-in .NET framework generic class Lazy<T> saves some code for implementing the lazy initialization. In addition, it is thread-safe.
To follow the singleton design pattern more closely we can add a private constructor to the page and instead of using the new keyword to create the instance we can use Reflection.
Driver
Below you can find a static utility class that we use to create a single instance of WebDriver. It comes handy instead of copy-paste the same code repeatedly in the TestInitialize methods.
BingMainPage Singleton Version in Tests
Now we do not have the WebDriver initialization logic in the TestInitialize method. In addition, the usage of the page object in the test is changed. We use the Instance static property to get the instance of the page.
In future articles, I will share with you other modifications of the design pattern that can make your tests even more maintainable. You can find even more articles dedicated to the design patterns in automated testing on my site- Automate The Planet.
About Anton Angelov
I am the Founder and Editor in Chief of Automate The Planet. My passion is taking software quality to new heights through the integration of the best practices in the Quality Assurance and Automated Testing. I have considerable professional experience (6+ years) as a Senior Automated Testing Architect. Currently, as QA Architect and IT Consultant, I am improving the tooling and processes in a company named Innovative Lab. I am ardent about technologies such as .NET Framework, Azure, Bot Framework, SQL Server, Selenium WebDriver, and Jenkins. Outside my work as a consultant, I am an IT trainer leading training related to high-quality code, design patterns and automated testing.
Images: