Page Object Model & PageFactory in Selenium

✒️ What is Page Object Model?

POM is a design pattern in Selenium that creates an Object Repository to store web elements. In POM, we follow the principle of separation of Object Repository and Test Classes. Each object repository only contains the elements of the respective webpage.

✒️What are the advantages of POM?

Easy Maintenance: As every page is separate in POM, if there is any change in any webpage that is easy to identify and change. Changes in the object repository don't impact the code elsewhere.

Reusability: A single object repository can be used for different TestCases. Also, we can integrate the same POM in Selenium with different types of tests like functional and acceptance testing simultaneously.

Readability: Testers can quickly identify actions that will be performed on a particular webpage.

⚠️ verifications or assertions shouldn't belong to Object Repository ⚠️


✒️What is PageFactory in Selenium?

PageFactory is a very optimized way of implementing POM. It is a class provided by Selenium WebDriver which expands the functionality of plain POM.

1️⃣@FindBy: An annotation used in Page Factory to declare web elements. The @FindBy annotation supports :id, name, className, css, tagName, linkText, partialLinkText, xpath. Below is an example of declaring a webelement using @FindBy-

@FindBy(class="elementClass")
WebElement element;

2️⃣ initElements(): A static method in Page Factory class, it instantiates an instance of the given class. Also used to initialize all the web elements defined by @FindBy annotation.

public RegistrationPage(WebDriver driver) {           
         this.driver = driver; 
         PageFactory.initElements(driver, this);
}

3️⃣ AjaxElementLocatorFactory: AjaxElementLocatorFactory is Lazy Loading concept in PageFactory. It is used to deal with dynamic elements that change during runtime based on user actions, especially on Ajax-heavy applications. Timeout is also possible to set for a webelement using AjaxElementLocatorFactory.

AjaxElementLocatorFactory ajaxFactory = new AjaxElementLocatorFactory(driver, 30);
PageFactory.initElements(ajaxFactory, this);


✒️Default behavior of PageFactory:

  • Web elements declared using @FindBy are initialized at once and yet not searched in the browser DOM
  • WebDriver searches a particular webelement each and every time it is called or any action happened to it.
  • For static elements, it provides @CacheLookup annotation to cache web elements for future uses.

✒️Differences between POM and PageFactory:

Page Object ModelPageFactory
Page Object Model is a design pattern.PageFactory is a class that provides an implementation of POM .
In POM, individual initialization of every page object is needed.In PageFactory, all the page objects are initialized at once by using the initElements() method.
Define web elements using ByDefine web elements using @FindBy annotation.
POM is not optimal as it doesn't support lazy initialization.Supports lazy initialization and it is optimal.
POM is not capable of handling StaleElementReferenceException.It efficiently handles StaleElementReferenceException by searching everytime when any stale element is called.

✒️@CacheLookUp annotation:

@CacheLookUp annotation is used to keep a cache of WebElement on its first arrival on the webpage instead of searching over and over again, usually used for elements that never change.

A findElement() REST Request is sent to the WebDriver every time a WebElement is called from the page object repository. This satisfies one of the important Pagefactory benefits of looking for the newest version of webelements after page loading. But, it makes the process slow and time-consuming(a lot obviously!). Here, @CacheLookUp comes to solve the problem.


✒️When not to use @CacheLookUp?

It is not suitable for elements that are dynamic in nature. For AJAX based applications, it may not work where the DOM frequently changes based on user interaction. Upon using @CacheLookUp annotation, WebDriver may throw StaleElementExceptions.