What is PageFactory?

Context:

In the previous section on what is page-object, we talked about how to represent a web page into a page-object, initialize the elements using webdriver and then accessing them in step_definitions.

Since we had only one page-object, we really couldn’t see the issues we might face as code grows. In this section, lets see what is the problem when we define page-objects as we did and the code gets larger and larger. Yes sure, it works as is !

KISS principle:

But we do want to follow KISS (keep it simple stupid) right [Anyways, I have my own qualms about this KISS principle and where it doesn’t apply and how it can be masked into too much of abstraction, but that’s for a later discussion]

The Problem:

Let’s say hypothetically that I had 3 cucumber scenarios and each scenario would interact with the home page and do further steps. The scenarios from a high level perspective do the following. We will be using automationpractice website.

  1. Go to home page, click sign in, and further steps
  2. Go to home page, verify phone number is correct, then only click sign in
  3. Go to home page, click contact us and further steps

The home page looks as below [The corresponding html locator information is also posted.

element_html_map

Home page-object:

Cucumber Scenarios:

 

Step Definitions:

Do we see the issue now ?

Yes I am sure you must have figure it out. It is in the step_definitions code.

  1. We are repeatedly instantiating the AutomationHomePage object – as this code grows, we will lose track of which instance of AutomationHomePage we are interacting with [unless we go through Cucumber step by step, which is really a pain]
  2. As a script writer, instead of being able to write automation scenarios quickly and uncover the defects, I am lost in a maze of objects here and what is instantiated at what time [Of course, I can always dump the current state of object and inspect it and move on, but is it really worth the time when there is page-factory pattern;)]

Page Factory pattern:

The page factory pattern relieves this burden on the user of instantiating the page-objects and interacting with them in the step definitions.

In a nutshell, page factory pattern implementation has logic that will initialize the page objects at strategic points. One implementation that we will follow here does the following:

  • When I want to interact with a page, if the page is NOT already initialized with the html elements, then initialize it
  • When I want to interact with a page, if the page has been initialized with html elements, then re-use that page-object

 

An implementation:

The below module implements the pattern with the methods “visit” and “on“. We referred to the usage of this pattern and how it makes readable code on this website already on Why Ruby and Roadmap pages. I have also included the web links that might pique your interest on reading more as to giving due credit to the original idea generators.

  1. The visit method takes a page-object as argument [closure as optional parameters]. See below on how it is used
  2. The on method is very interesting, because it checks if page-object exists then uses it, otherwise creates a new instance

Obviously I am assuming that you are aware of the syntax for various constructs in Ruby. So the above code has many more concepts baked inside it and I would post a video at the bottom of this page and try my best to explain the code.

Apply page-factory pattern:

After applying the page-factory pattern, the step_definitions code would look as below, pretty , clean and KISS right 🙂

But Dude..

What about asynchronous behavior, where html elements detach from DOM and lose their reference with webdriver, that means my page-object that was used a while ago may have stale html elements right ?

Bingo! (You should feel like Neo in Matrix when he asks that question to Oracle…haha)

Right, so you would come across StaleElementReference exceptions in extremely ajax applications. There are strategies to handle this with page-objects and page-factory too. We will talk about some strategies in the closing pages of this section.

Next:

So we talked about page-factory pattern and how it might be useful to us. The next section is where we would take a concrete workflow on an e-commerce website and implement page-object and page-factory patterns.

Just as a reminder, we will be adhering to the Roadmap and Future section, so would request you to read that once again if you did not already.