info@brightest.be
+32 3 450 88 42

Technical Thursday

Page Object Model: Healthy code makes healthy tests

Posted by: Berte Verhoeven
Category: Test automation
Automation frameworks are gaining popularity as a solution for automating complex applications. One of the main problems using a scripted automation framework is maintenance. The Page Object Model (POM) creates a layer of abstraction between the automated tests and the page under test.

The idea behind this pattern is to create several classes where each class represents a single page of your application under test. These classes contain properties which represent the elements on the page and methods to interact with these elements.

Let’s use the login page below as an example and discuss some tips on how to implement the page class using the Page Object Model.

Class structure

Create a single class within the framework to represent our login page. One of the first decisions to make is how to name the class. All classes should have a clear name so other automation engineers can easily find the class associated with a given UI page. The class name should make it 100% clear what’s inside the page object. If not, your page object probably does too much. Also, be consistent with the naming of your classes. When you decide to let your page object class end with the word “Page”, make sure that you do this for every page object class.

Properties

A next step is adding properties to the class. It’s important to only add properties for the UI elements that will be used within your tests. Behind these properties are locators used to find the elements on the actual page. By defining these locators in one place, you don’t need to hardcode them in every place you want to use them. This way we are eliminating code duplication and lowering the maintenance.

In addition to the properties, the class must also contain methods to interact with the application. For example setting input fields, clicking buttons, checking radiobuttons, … What are the best approaches for creating these methods?

Getters and setters

The idea of using the Page Object Model is to set and get the state of your application, therefore you need methods to do this. For example, we need to set the username and password and we need to get the possible error message. Be careful and don’t add getters and setters for all the available fields but only add those which are currently needed within your tests. It’s very easy to add more getters and setters if a new test requires such. This will prevent you from having to maintain unused code.

Return new objects

There is a difference between getters and setters and methods. Getters and setters result in a page change and methods return or manipulate the state of an element on the page. Methods that trigger clicking a button or link, need a different approach. For this type of methods, it’s better to return an instance of the class representing the page you’ve transitioned to. For example, clicking the Log In button will lead you to the Home page of the application. When implementing this, you should create a method which returns an instance to the class representing that Home page.

By working like this, the test knows that a transition will occur by calling this method. Thereby the test has an instance to the necessary page object to continue interacting with the application and continue the test.

Making keyword methods

Logging into the application takes three method calls:

setUsername
setPassword
clickLogInButton)

These three actions are used together very often. It might be good for the page object class to provide one single method to log in, a keyword method.

We did not implement any logic within this method, but instead we called each method individually. It is important to have these separate methods available. In that way they can be used within negative tests, e.g. set the username but not the password and click on the log in button.

Be aware that the only public methods allowed in the page object class are the ones that can perform an end use on your application – nothing more.

Stateful elements

Sometimes clicking an object just isn’t enough. Let’s take a checkbox as example: to satisfy the desired intent of the test, the checkbox must be checked.
What if it’s already checked? Calling the Click method would give you the opposite of what you want. We need more sophisticated methods, implementing logic that will only check the checkbox if it’s needed to. So, instead of blindly clicking the checkbox, accept a parameter which will specify the intent. In case of our checkbox, we verify the status, checked or unchecked, and act accordingly.

Assertions

A Page Object Model class should be a neutral entity that interacts with and gathers information about the application under test. It’s important to keep your methods neutral and generic so you can use them by any test that wants to interact with the page. Do not include any assertions within the page object class. By keeping the methods neutral, they can be used in both positive and negative tests. It’s up to the test to determine whether the information returned from the page object class will result in a pass or a fail.

Composition

A page object doesn’t have to be an entire page. It can also be a small component, this is what developers call composition. The idea is to push pages toward composition rather than having to use inheritance. Composition creates cleaner and tighter page objects. Assume that you have a page with a header menu and a footer, we can create a HeaderComponent and a FooterComponent. Those are both page objects. Instead of using inheritance, we use composition to have these page objects living inside another page object.

Healthy code makes healthy tests

Simple page objects are an underrated technique but they are highly effective and easy to use. The tips above will help you design healthy page object classes. This will result in a code which is easy to use and maintain. It’s a design pattern that works – but only when properly followed.