Deconstruct Page Object Pattern

Page Object Pattern…Sounds pretty intimidating, isn’t it? Especially if you are new to automation field.

Relax, wait for me to show you how simple it is:

Then you are adopting Page Object Pattern already!

Figure 1: Page Object Pattern

Selenium’s support for Page Object Pattern

Selenium provides Annotations for element-locating and PageFactory for create page object.

Annotations for element-locating
@FindBy: to locate one single element.
@FindBys: to locate a group of elements

The annotations support all locators strategies that we use:
id, name, className, css, xpath, tagName, linkText and partialLinkText

Some examples to find a single element:
@FindBy(id=”userName”) private WebElement userName;
@FindBy(name=”password”) private WebElement password;
@FindBy(css=”.button”) private WebElement loginButton;
@FindBy(xpath=”//*[@id=’loginForm’]/div/div/div/div/header/h1″)  private WebElement hint;
@FindBy(tagName=”a”) private WebElement link;
@FindBy(linkText=”click here”) private WebElement theLink;
@FindBy(linkText=”click”) private WebElement theOtherLink;
To find a group of element:
//To find all itemizedelements whose class is ’tile’
@FindBys({@FindBy(css = “li.tile” }) protected List stationTile;

Another example:

//find all itemized play icons under ul element whose class is ‘station-tiles’
@FindBy(css = “ul.station-tiles”),
@FindBy(css = “li.tile”),
@FindBy(css = “i.icon-play”)
protected List stationPlayIcons;

By default, selenium locates element by its ID or name if no locator is defined for the element:

By default, selenium locates element by ID or NAME

Instead of creating  page object using ‘new’ key word like this:

LoginPage loginPage = new LoginPage(driver);

Selenium webdriver comes with class PageFactory for creating new pages:

//PageFactory.initElements(WebDriver driver, Class<?> clazz)
LoginPage loginPage = PageFactory.intiateElements(driver,  LoginPage.class);

To use PageFactory, either the page object class provides a constructor that takes a WebDriver as an argument, or it does have a default constructor.

The PageFactory.initElements method will look for any WebElement fields that are annotated with the @FindBy or @FindBys annotation, and initialize these using the driver to look up the according reference from the page itself.

So what is the benefit of creating   page object via PageFactory?
The major benefit of PageFactory is that PageFactory adopts Lazy Initiation, ie. it won’t initiate the element until it is first time needed (aka referred in the code). This will increase system responsiveness and speed startup by bypassing large-scale object pre-allocation.

Also, all elements tagged with FindBy(s) annotations are automatically cached once they are initialized. This will make our automation run faster.

Of course, creating pages via PageFactory giving us the benefit of falling back on default way of locating elements(First by ID, if not found, then by name). This means that if most or all your elements on the page have id or name attribute, then in your page class you don’t need to spell out ‘how to locate’ info at all if you create your object via PageFactory, as far as your variable name is identical to the element id or name.  This will save you some typing and make our code shorter.

Leave a Reply

Your email address will not be published. Required fields are marked *