We implement the test automation using Selenium to ease the process of website testing. But what if test automation scripts are not written in a structured way? It would make the testing process inefficient and ambiguous. To maintain the efficient performance and project structure of the automation scripts, it is necessary to have different pages/scripts for each task. To ease the access of distributing codes across different files and maintain a clean project structure, the Page object model and Page Factory come to the rescue.
In this article, we will walk you through some of the core concepts of the Page object model and Page Factory in Selenium with the help of appropriate examples.
What is the Page Object Model in Selenium?
Page Object Model (POM) is a design pattern in Selenium that is used to create an object repository to store all web elements. It helps improve the code reusability and test case maintenance.
In this design pattern, each web page in the web application will have a corresponding Page Class in the automation script. This Page class will identify the various WebElements of that web page and also includes methods to perform testing on those WebElements.
Note: The name methods inside a Page class should be given to represent the task they are performing. For example, if a loader is waiting for the order to be confirmed, the POM method name can be waitForOrderConfirmation().
Why do We Need Page Object Mode?
The below-mentioned points depict the need for a Page Object Model in Selenium.
The below-mentioned steps depict the need for a Page Object Model in Selenium.
- Code Duplication: Without proper management of locators, automation test projects can become unwieldy due to duplicated code or excessive repetition of locator usage.
- Time Efficiency: Maintaining scripts becomes cumbersome when multiple scripts rely on the same page element. Any change in that element necessitates updates across all affected scripts, consuming valuable time and risking errors.
- Code Maintenance: POM mitigates code maintenance challenges by centralizing element identification and interaction in separate class files. When a web element changes, updating its locator in one class file propagates the change across all associated scripts, ensuring code remains reusable, readable, and maintainable.
- Adaptability to UI Changes: When UI elements are restructured or relocated, existing automation tests may fail due to outdated locators. Manual updates to numerous scripts can be time-intensive. However, with POM, locating and updating element locators is centralized, streamlining the process and allowing testers to focus on enhancing test coverage rather than manual adjustments.
By implementing POM, automation frameworks gain flexibility, efficiency, and resilience to UI modifications, ultimately enhancing the effectiveness of test automation efforts.
Advantages of Page Object Model in Selenium
The advantages of using the Page object model in Selenium are:
- Reusability: The same Page object class can be used in several test cases, which reduces code duplication and improves code reuse. This saves time and effort when writing new tests because the same Page object class may be used several times.
- Easy Maintenance: The page object model improves the UI test management by organizing code logically. It helps identify which page or screen needs modification when UI elements or actions change.
- Readability of Scripts: POM makes the test scripts more readable and understandable by separating the script files for each screen and using the logical names for methods.
- Increases test coverage: POM allows testers to create additional tests with less effort. This increases test coverage and helps to uncover more faults, resulting in software with greater quality.
- Functional encapsulation: Using POM, all probable testing operations on a page may be described and included within the same class built for each page. This enables a clear definition and defines the scope of each page’s operation.
What is Page Factory in Selenium?
Page Factory is an in-built Selenium design pattern for web automation testing that simplifies the creation of Page Objects. It reduces the amount of boilerplate code required to build Page Objects, making the automation code easier to maintain and read.
In Page Factory, testers utilize the @FindBy annotation alongside the initElements method to initialize web elements.
The @FindBy annotation accepts various attributes such as tagName, partialLinkText, name, linkText, id, CSS, className, and XPath, enabling testers to locate and interact with elements on the web page precisely.
Advantages of Page Factory in Selenium
Using the Page Factory along with the Page Object Model in Selenium brings a lot of advantages. Listed below are a few advantages of Page Factory:
- Easy Initialization: PageFactory simplifies web element initialization by allowing the use of annotations like @FindBy directly within the page object class. These annotations specify locators (e.g., id, name, XPath), and PageFactory automatically initializes elements upon instantiation of the page object.
- Lazy Initialization: PageFactory employs lazy initialization, meaning elements are initialized only when accessed or interacted with in the test code. This optimizes performance by avoiding unnecessary element lookup and initialization when elements are not needed.
- Improved Code Readability: Separating web element initialization from test code enhances code readability. With Page Factory, it’s clearer to understand code intent and interactions with the web page.
- Enhanced Test Performance: Page Factory can boost test performance by reducing the overhead of locating web elements. Initializing the Page Object once per test, rather than per test method, minimizes redundant operations, improving overall efficiency.
How to Create a Page Object Model with Page Factory in Selenium
Now that we know the basics of Page object model and Page Factory let’s try to implement it in a real example to open Google’s home page and search for TestGrid.
Test Scenario:
- Open the Google Chrome browser.
- Visit Google’s homepage “https://google.com”.
- Write “TestGrid” in the text box.
- Click Search.
- Quit the browser session.
Step 1: Create Packages
In the Page object model with page factory in Selenium, it’s advisable to organize projects into recommended packages: one for the webpages and the other for the tests. For this project, we will create the two packages with the names com.testgrid.google.page and com.testgrid.google.tests.
Example of a recommended project structure:
com.testgrid.google.page
│
├── webpages
│ ├── LoginPage.java
│ └── GoogleHomePage.java
│ └── ...
│
└── tests
├── LoginTests.java
└── GoogleHomePageTests.java
└── ...
Step 2: Create Class For Webpage
Now that we have our project structure ready, let’s create a class for the webpage (page) package. Here, we will create a class named GoogleHomePage. This is where we will write all the web element locators and methods to handle different operations.
package com.testgrid.google.webpages;
import org.openqa.selenium.WebDriver; // Import WebDriver to interact with the browser.
import org.openqa.selenium.WebElement; // Import WebElement to locate elements.
import org.openqa.selenium.support.FindBy; // Import FindBy to locate elements.
import org.openqa.selenium.support.How; // Import How to specify the locator strategy.
import org.openqa.selenium.support.PageFactory; // Import PageFactory to initialize elements.
/**
* This class represents the Google Home Page.
*/
public class GoogleHomePage {
// WebDriver reference variable.
private WebDriver driver;
/**
* Constructor for the GoogleHomePage class.
* @param driver The WebDriver instance.
*/
public GoogleHomePage( WebDriver driver ) {
// Assign the WebDriver instance to the 'driver' variable.
this.driver = driver;
// Initialize the WebElements using the PageFactory.
PageFactory.initElements( driver, this);
}
// Locate the search box element using the NAME locator strategy.
@FindBy(how = How.NAME, using = "q")
WebElement searchBox;
// Locate the submit button element using the NAME locator strategy.
@FindBy(how = How.NAME, using = "btnK")
WebElement submit;
/**
* Method to handle seach box inputs.
*/
public void search()
{
searchBox.sendKeys("TestGrid");
}
/**
* Method to perform submit operation.
*/
public void submit()
{
// Click the submit button.
submit.click();
}
}
The above code, code represents the GoogleHomePage Class using the Page Object Model with Page Factory in Selenium. It utilizes annotations like @FindBy to locate web elements such as the search box and submit button. The constructor initializes the WebDriver instance and elements using Page Factory. Methods like search() and submit() perform actions on the respective elements, demonstrating the page’s functionality. This structured approach enhances code maintainability and readability. By encapsulating page-specific logic, it facilitates easier test automation and maintenance.
Step 3: Create a Class For Testing
Next, we need to create the GoogleHomeTest Class. This is where we will write all the logic to open a web browser, wait for the URL to load, perform testing, and close the browser.
package com.testgrid.google.tests;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.webpages.GoogleHomePage;
/*
This class contains the test methods for Google Home Page.
*/
public class GoogleHomeTest
{
// Declaring the WebDriver
static WebDriver driver;
/*
This method is used to set up the test environment.
It initializes the WebDriver and opens the Google Home Page.
*/
@BeforeTest
public void setUp()
{
// Creating an instance of ChromeDriver.
driver = new ChromeDriver();
// Maximizing the browser window.
driver.manage().window().maximize();
// Navigating to the Google Home Page.
String url = "https://www.google.com";
driver.get(url);
// Setting the implicit wait time.
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
/*
This method contains the actual test steps.
It creates an object of GoogleHomePage class and calls its respective methods.
*/
@Test(priority = 0)
public void googleSearch()
{
// Creating an object of GoogleHomePage class.
GoogleHomePage gs = new GoogleHomePage(driver);
// Calling the title method.
gs.title();
// Calling the search method.
gs.search();
// Calling the submit method.
gs.submit();
}
/*
This method is used to close the browser after the test execution.
*/
@AfterTest
public void closing()
{
// Quitting the WebDriver.
driver.quit();
}
}
The above code demonstrates a test class, GoogleHomeTest, for testing the Google Home Page.
- @BeforeTest method initializes the WebDriver, maximizes the browser window, navigates to the Google Home Page, and sets implicit wait time.
- @Test method googleSearch() performs the actual test steps. It creates an object of the GoogleHomePage class, and calls its methods for title verification, searching, and submitting.
- @AfterTest method closes the browser after test execution.
This structure ensures systematic test setup, execution, and teardown.
Difference Between Page Object Model and Page Factory
Below are the primary differences between the Page Object Model and Page Factory in Selenium:
Aspect | Page Object Model | Page Factory |
Implementation | A design pattern | An annotation-based approach |
Usage | Used for representing web pages as Java classes | Used for initializing WebElements |
Constructor | A default constructor is required | A default constructor is not required |
Locators | Locators are defined in a separate class | Locators are defined inside the page class |
Maintainability | Easier to maintain due to separate locator class | Requires frequent updates for element changes |
Performance | Slightly faster due to compile-time initialization | Slightly slower due to runtime initialization |
Code readability | Can be more verbose and repetitive | Can be more concise and readable |
Code Reusability | More code reusability due to loose coupling | Less code reusability due to tight coupling |
Conclusion
In Selenium, the Page Object Model and Page Factory design patterns are used to improve test script efficiency, readability, and maintainability. Both patterns seek to isolate page elements from test code and encapsulate interactions with those components within page classes.
The Page Object Model pattern entails establishing a unique class for each page or component of the application under test. Page Factory extends the Page Object Model paradigm by using annotations to locate and initialize page items.
Start your smart continuous testing journey today with TestGrid.
FAQs
1. What is the difference between the Page object model and the Page factory in Selenium?
The Page Object Model is a code design pattern that creates an object repository for web items that can be accessed via a web page. It uses the By annotation to describe page objects, and each object must be initialized. POM also supports cache storage. Page Factory, on the other hand, is a class that only implements the POM.
2. Why do we use POM in Selenium?
POM is a Selenium design pattern that builds an object repository to hold all web elements. It reduces code duplication and enhances test case management.
3. Can we use POM without Page Factory in Selenium?
Yes, you can use Page Object Model (POM) in Selenium without using Page Factory.