In my last post “Page Object Pattern“, from the series “Design Patterns in Automated Testing“, I gave you examples how to use one of the most popular patterns in the Web Automation the Page Object Pattern. In this article, I am going to improve further the main idea of the pattern.

If you read the code from my last post, you will most probably notice that it brakes one of the most important programming principles- DRY (Don’t-Repeat-Yourself). The primary goal of the improvements of the pattern is going to be to create an OOP design of classes in order to limit the repetition of code blocks.

While ago we were working on the first version of the BELLATRIX test automation framework, I did this research so that we can find the most convenient way for creating page objects.

Base WebDriver Class

The main goal of the class below is to provide a direct way to initialize and access the web driver instance.

The driver is initialized through the StartBrowser method where the client is capable to set a particular browser type and timeout. The stop of the browser that is usually performed on TestCleanup is also an easy task via the static StopBrowser method. If the client tries to access the instance before the initialization, an exception is thrown.

Advanced Page Object Pattern OOP Design

The first class that needs improvement is the element map.

First Version

The main problem here is that every client of the class should pass to its constructor the current Web Driver instance. We can make it better with the help of the previously created static class Driver. We can create a base element map that all other element maps are going to derive.

Improved Version

As you can see in the new version, the class doesn’t have a constructor. So this code block is not going to be repeated in all other map classes.

The next step in the improving process is to create a base class for the validator classes.

First Version

In the first version of the class, the DRY design principle is again not followed. The Map property and the constructor need to be placed in every validator class.

Improved Version

When derived this generic class is going to provide direct access to the element map.

After the refactoring, we end up with more readable and cleaner solution.

The final step in the process of making a better page object pattern OOP design is to create a base class for all page classes.

First Version

There are a couple of items in the above class that is going to be repeated for every page class- the constructor, the Navigate method, the Validate method, and the Map property. As you can imagine, this is a lot of boilerplate code. In order to fix this problem, we can create the following two base classes.

The first one can be derived if you want to have a page without validator. The second one extends the first and adds to it the Validate method. Via the generic parameters and their constraints, we can use these classes for all of our pages.

Improved Version

Now the SearchEngineMainPage class consists only of a single constructor and the Search method, all of the boilerplate code is moved to the base class.

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

Advanced Page Object Pattern- Usage in Tests

If you compare this sample usage with the one presented in the previous solution, you will notice that they are completely identical.

There is also another benefit that comes from the usage of the BasePage object- you cannot use the Map property directly in your tests. In my opinion, the direct usage of element maps in the tests is not a good practice because it breaks the DRY principle.