Tips for Healthy Page Object Classes
Tips for Healthy Page Object Classes
These tips should help you design healthy classes that implement the Page Object Model design pattern
Join the DZone community and get the full member experience.Join For Free
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.
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 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.
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 Getters 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 connivance 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 that you should 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!
Published at DZone with permission of Angie Jones . See the original article here.
Opinions expressed by DZone contributors are their own.