Top

Tips for Healthy Page Object Classes

Tips for Healthy Page Object Classes

It’s the beginning of a new year and people all over the world have made resolutions to become healthier. That’s wonderful! In fact, your frontend tests want in on the action as well.

The most popular design pattern used in web UI test codebases is the Page Object Model (POM) design pattern. This pattern suggests modeling a class to represent a single page of your system under test. Using this model, the class would contain properties that represent the elements of the UI page and methods that interact with these elements.

Given this is the Login Page of our application, let’s discuss tips for building a class using POM.

The Class

We make a single class in our automation framework to represent this page. It’s recommended to ensure the name of the class is representative of the page in the application so that other developers can quickly find the class associated with a given UI page.

So, in this example, we’d make a class called LoginPage.

 

Properties

LoginPage should contain properties for each of the elements on the page that will be used within your tests. The value of these properties are locators to the elements on the actual page. By defining these locators in one place, you won’t need to hardcode them in every place that you use them – thus, eliminating duplication.

 

Methods

In addition to the properties, the class should also contain methods that enable a test to interact with the application, such as setting input fields and clicking buttons. Here are some tips on designing these methods to be optimally used by your tests.

 

Add Getter and Setters

The purpose of POM classes are to set and get the state of your application. So, you’ll need methods to do this.

For example, we definitely need to set the username and password fields, so set methods should be added.

We also need to know the content of the error message, so this will need a getter method.

 

Only Add What’s Currently Needed

Notice, we didn’t add getter and setter methods for every field, because we don’t have a need for them in our tests. Only add what’s currently needed. You can always add more if a new test requires such. This will prevent you from needing to maintain unused code.

 

Transitions Should Return New Objects

You’ll also need methods for clicking links and buttons. However, when your click results in a page change, your method should return a handle to the class representing the UI page you’ve transitioned to.

For example, if clicking the sign-in button will lead to the home page of your application, then your method should return a handle to the class representing that home page.

By providing this, all calling tests know that a transition will occur by calling this method, and the test has a handle to the necessary object to continue interacting with the application.

 

Don’t Be Afraid to Make Convenience Methods

Right now, logging into the application would take at least three method calls (setUsername, setPassword, and clickSignInButton). As these three are commonly used together, it makes sense for your class to also provide a connivence method so that your tests only need to call one method.

Notice we did not implement the logic within this method, but instead called the individual methods. It’s important to have those separate methods available, so that negative tests (e.g. set username but not password) can utilize them.

 

Be Mindful of State

For checkbox elements (or other toggles), simply clicking them may not satisfy the desired intent of the test. For example, what if your test wants the box to be checked, but it’s already checked? Calling a click method would give you the opposite of what you want. Instead, make your method more sophisticated by implementing logic that will only check the box if it’s needed to give the user their desired result. To do this, instead of blindly clicking, accept an argument that specifies intent (i.e. do they want it selected or deselected) and act accordingly.

 

Keep POM Classes Neutral

Your POM class should be a neutral entity that interacts with and gathers information about your application. Be careful to keep your methods neutral and ensure they are generic enough to be used by any test that wishes to interact with the page. This basically means do not include assertions within these methods.

By keeping the methods neutral, they can be used in both positive and negative tests. The test can use the information returned from the class for its own purposes in determining whether that information warrants a pass or fail.

For example, what if our method that gets the error message also fails the test if the message is visible?

I cannot reuse this method for tests where I want to make sure an error message is shown when the username or password is incorrect or not provided. This is because the POM class has taken it upon itself to determine that the display of an error message is a failure; when in these cases, that’s not so. Instead, just return the state and allow the test to determine what that means.

 

 

Healthy Code Makes Healthy Tests

These tips should help you design healthy classes that implement the Page Object Model design pattern. The use of this pattern promotes separation of concerns (e.g. tests vs managing state), reduces code duplication, and provides reusable methods. Happy testing!

Angie Jones
6 Comments
  • Tom
    Thanks for the great article!
    I can see in your code snippets that your properties are By types. What are your thoughts on having these as WebElements? Any preferences?
    I quite like using WebElements as it reduces the need to write driver.findElement in lots of other places. I think this can also improve readability of code as you can have signInButton.click() etc.
    February 6, 2020 at 1:31 am Reply
    • Angie Jones

      If you instantiate at declaration, wouldn’t it look for all those elements at that time? Sometimes those elements are not there yet, as they can be dynamic based on other interactions on the page.

      February 19, 2020 at 8:13 am Reply
  • Cesar M

    This is a great article and very eye-opening. I have been doing it wrong all this time!! Thank you, Angie.

    February 19, 2020 at 6:52 am Reply
  • John

    This is great! I’m just starting and will be good to know.

    February 22, 2020 at 6:13 am Reply
  • Roman
    Hi Angie,
    I would like to ask:
    Why did you recommend to use Page Object without PageFactory without elements and FindBy annotations?
    February 24, 2020 at 8:19 am Reply

Post a Reply to Roman Cancel Reply