Today's article assumes a familiarity with ideas such as methods, privacy, JUnit tests and objects that was covered in my Java series.
The developer gurus I work with are really keen on design patterns, and often consider understanding them more important than knowing about the details of a language.
A design pattern is a set way of approaching a standard problem. There are a couple of them floating around for Selenium, but one of the most important ones I've heard about is the page object design pattern. There will be extensive references at the bottom of the page for further reading.
I'm going to go through an example of how I've analysed how to create automation. You might take a slightly different approach, but hopefully you'll find the discussion of my approach useful enough to understanding what you need to consider.
First of all, in page object design, you're going to create an object for every page in your application. This "page object" will know all about the which, what and how of the page,
- Which elements are on the page.
- What their state is.
- How to perform actions on the page
In addition, it's generally a good idea to have the checking that performs pass/fail in your automation separate to the page object itself. The page object will handle everything about doing things on the page, but will pass out information on the page to this test layer, so it's the test layer which performs the checks.
Our example ... Twitter
Okay, so we're back with Twitter again (I use this a lot). Every page on Twitter can be turned into a page object.
For simplicity we'll say for now that there's just two. The main feed page below,
And the login and registration page here,
You need to create objects for both, with a third layer to contain your JUnit tests. Again we covered JUnit tests extensively in our Java series.
To make life easier, we're going to focus in and do the analysis on login and registration, and focus on this part,
Which elements are on the page "LOCATORS"
Richard Bradshaw's article on page object design here calls the kind of functionality we're going to look at now "locators", and I just love that term for describing this.
We need to create function calls to define all the page elements on the page we'll want to use. We could do this by either defining WebElements inside the page object, or having methods which return the WebElement.
We need to choose one or the other, and stick to it. Most importantly we want these to be private. Only our page object should want to locate the WebElement directly. The "what" and "how" parts of the object we design will allow external parts of the system to interface with these elements as needed.
Lets do the analysis, we have the following ...
Text fields,
- Phone, email or username
- Password
- Full name
- Password
Buttons
- Log in
- Sign up for Twitter
Check boxes
- Remember me
Links
- Forgot password?
We need to define them all. There's also an additional one we might want to define, you can get an error message ...
What their state is "STATE"
This is a bit trickier, but you might want to return the state of the page. These methods should be public, and will be used by your JUnit tests. They are similar to the idea of "getters".
So examples might be,
- Get page content. Return the text on the entire page. So the JUnit test can check for certain content.
- Get error message box state. Return true if the error message box is displayed.
- Get error message box content. Return the text inside the error message box.
How to perform actions "ACTIONS"
My team call these flows. Rather than just a single action, they're a sequence of actions. Obviously these methods would need to be public.
If we look at our chosen page, there are three flows ...
Flow 1 - login
- Enter username
- Enter password
- Select/deselect remember me
- Select log in button
Flow 2 - register
- Enter full name
- Enter email
- Enter password
- Select sign up for Twitter
Flow 3 - forgot password
- Select forgot password link
Notice how if this was turned into a test script, all these flows relate to the "action" not "expected result" part of a test script table. This is intentional, as the part that checks expected result should be an assertion within the JUnit method.
And finally...
The JUnit method can string together sequences of these page object, to create a series of tests.
Let's look at login, we can call that perform login method in multiple tests. We can leave some fields blank, we can give it correct data, we can give it false data. Then we should use an assertion within our JUnit to find out if the system is right or now,
- If we give the correct data, we should find the words "Home", "Moments", "Notifications" on the page.
- If we give a field as blank, we should get an error message
- If we give wrong details, we should get an error message
This diagram should explain the relationship (and I'm so sorry, the colour scheme seemed a good idea at the time) ...
The key thing is this approach follows two key rules of software development. Using methods, which we discussed yesterday. But also encapsulation, only giving access to items that another level really needs.
Further reading
There's a lot to read about, so this section contains some useful next steps ...
- Selenium has a section on page object design here
- Test Detective's Selenium Design Patterns [I found this one really simple to follow]
- Richard Bradshaw's PageObject Pattern - Why, how and more
- Martin Fowler's PageObject
- Alan Ricahrdson's Page Objects Refactored
- Alan Richardson's Page Objects And Beyond



