Ever struggled to keep your Selenium tests stable as the UI keeps changing?
Testers often face this issue and I’ve seen teams spend around 30–40% of their automation time just updating broken locators and fixing repetitive failures.
Small UI tweaks ripple through the test suite, slowing down releases, delaying feedback, and making automation feel more like a burden than a productivity boost.
That’s where structured design patterns like the Page Object Model (POM) and Page Factory help.
They simplify maintenance, reduce duplication, and make tests far more resilient to UI changes—especially as the application grows.
Overview
POM is a design pattern in Selenium that separates page-specific UI elements and actions into dedicated classes. It helps create clean, readable, and modular automation frameworks.
Purpose: The purpose of POM in Selenium is to organize UI elements and actions into dedicated page classes, making tests easier to maintain and protecting them from frequent UI changes.
Implementation
- Create one class per webpage (LoginPage, HomePage, etc.).
- Store web elements as variables and user actions as methods.
- Instantiate page classes inside test scripts.
- Keep locators and business logic separate from test logic.
Page Factory is an enhanced version of POM that uses annotations to initialize and manage UI elements more efficiently.
Purpose: The purpose of Page Factory is to simplify element initialization in POM using annotations like @FindBy, reducing boilerplate code and making page classes more readable and efficient.
Implementation
- Use @FindBy to define elements in the page class.
- Initialize elements using PageFactory.initElements(driver, this).
- Write action methods that interact with these elements.
- Call page methods directly in test scripts.
Example: LoginPage.java
import org.openqa.selenium.*;
import org.openqa.selenium.support.*;
public class LoginPage {
@FindBy(id = "username") WebElement user;
@FindBy(id = "password") WebElement pass;
@FindBy(id = "loginBtn") WebElement login;
public LoginPage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
public void login(String u, String p) {
user.sendKeys(u);
pass.sendKeys(p);
login.click();
}
}
This article explores how to use Page Object Model and Page Factory in Selenium automation projects to maintain test cases easily.
What is Page Object Model in Selenium?
Page Object Model (POM) is a design pattern in Selenium that creates an object repository to store all web elements of an application. It reduces code duplication and simplifies test case maintenance by organizing elements in separate classes.
In POM, each web page of the application is represented as a class file. These class files contain only the web elements specific to their corresponding pages, allowing testers to interact with elements and perform actions on the web application efficiently.
According to Crissy Joshua, Page Object Model brings long-term stability to Selenium automation by clearly separating test logic from page structure, making it easier to update locators and actions as the application evolves without impacting the test cases themselves.
Read More: Design Patterns in Automation Framework
Advantages of Page Object Model
The Page Object Model offers several benefits that make test automation more efficient and maintainable:
- Easy Maintenance: POM is useful when there is a change in a UI element or a change in action. An example would be: a drop-down menu is changed to a radio button. In this case, POM helps to identify the page or screen to be modified. As every screen will have different Java files, this identification is necessary to make changes in the right files. This makes test cases easy to maintain and reduces errors.
- Code Reusability: As already discussed, all screens are independent. By using POM, one can use the test code for one screen, and reuse it in another test case. There is no need to rewrite code, thus saving time and effort.
- Readability and Reliability of Scripts: When all screens have independent java files, one can quickly identify actions performed on a particular screen by navigating through the java file. If a change must be made to a specific code section, it can be efficiently done without affecting other files.
When combined with real-device and cross-browser testing, these advantages become even more impactful.
Running POM-based tests on platforms like BrowserStack Automate ensures they behave consistently across different browser versions and operating systems. systems.
With instant access to logs, videos, and debugging insights, teams can validate UI flows and maintain their POM framework with higher accuracy and reliability.
Key Concepts in POM
The Page Object Model follows a structured approach that revolves around key components such as Page Classes, Locators, and Methods. Understanding these concepts is essential for building efficient and maintainable test automation frameworks.
Page Classes
Each web page in the application is represented by a separate class file in the Page Object Model. This class acts as a container for the page’s web elements and related actions. By organizing pages into distinct classes, POM keeps the test code clean and easy to maintain.
Locators in POM
Locators define how to identify web elements on a page. POM uses locators such as ID, name, XPath, CSS selectors, or other strategies to map elements in the page classes. This centralized approach makes updating locators easier when the UI changes.
Methods in POM
Methods are functions within the page classes that perform actions on the page’s elements. These methods abstract user interactions such as clicking a button, entering text, or retrieving page data. Test scripts can call these methods to perform actions, improving code readability and reusability.
Platforms like BrowserStack further streamline POM-based automation by enabling testers to execute tests on real browsers and devices without the need for complex local setups.
This allows teams to focus on writing clean, maintainable code while ensuring cross-browser and cross-device compatibility at scale.
Implementing POM in Selenium Project
As already discussed, each java class will contain a corresponding page file. This tutorial will create 2-page files.
- BrowserStackHomePage
- BrowserStackSignUpPage
Each of these files will contain UI elements or Objects which are present on these screens. It will also contain the operations to be performed on these elements.
Also Read: How to Build and Execute Selenium Projects
Sample Project Structure for POM

BrowserStackHomePage Java File

Explanation of Code
- Code Line-10 to 11: Identifying elements present on BrowserStack Home Page such as header and Get Started button
- Code Line-17 to 24: Performing actions on identified objects on BrowserStack Home Page
Code Snippet
package browserStackPages;
import static org.testng.Assert.assertEquals;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class BrowserStackHomePage {
WebDriver driver;
By Header=By.xpath("//h1");
By getStarted=By.xpath("//*[@id='signupModalButton']");
public BrowserStackHomePage(WebDriver driver) {
this.driver=driver;
}
public void veryHeader() {
String getheadertext=driver.findElement(Header).getText();
assertEquals("App & Browser Testing Made Easy", getheadertext);
}
public void clickOnGetStarted() {
driver.findElement(getStarted).click();
}
}BrowserStackSignUpPage Java File

Explanation of Code
- Code Line-10 to 14: Identifying elements present on BrowserStack SignUp Page such as header and Get Started button
- Code Line-20 to 35: Performing actions on identified objects on the BrowserStack SignUp Page
Code Snippet
package browserStackPages;
import static org.testng.Assert.assertEquals;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class BrowserStackSignUpPage {
WebDriver driver;
By Header = By.xpath("//h1");
By userName = By.xpath("//*[@id='user_full_name']");
By businessEmail = By.xpath("//*[@id='user_email_login']");
By password = By.xpath("//*[@id='user_password']");
public BrowserStackSignUpPage(WebDriver driver) {
this.driver = driver;
}
public void veryHeader() {
String getheadertext = driver.findElement(Header).getText().trim();
assertEquals("Create a FREE Account", getheadertext);
}
public void enterFullName(String arg1) {
driver.findElement(userName).sendKeys(arg1);
}
public void enterBusinessEmail(String arg1) {
driver.findElement(businessEmail).sendKeys(arg1);
}
public void enterPasswrod(String arg1) {
driver.findElement(password).sendKeys(arg1);
}
}BrowserStackSetup Java File

Explanation of Code
- Code Line-21 to 27: Setting up browser and website to execute test scripts
- Code Line-29 to 43: Initializing driver object to BrowserStackHomePage & BrowserStackSignUpPage and performing actions on those pages
Code Snippet
package browserStackSetup;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import browserStackPages.BrowserStackHomePage;
import browserStackPages.BrowserStackSignUpPage;
public class BrowserStackSetup {
String driverPath = "C:\\geckodriver.exe";
WebDriver driver;
BrowserStackHomePage objBrowserStackHomePage;
BrowserStackSignUpPage objBrowserStackSignUpPage;
@BeforeTest
public void setup() {
System.setProperty("webdriver.chrome.driver", "C:\\BrowserStack\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://www.browserstack.com/");
}
@Test(priority = 1)
public void navigate_to_homepage_click_on_getstarted() {
objBrowserStackHomePage = new BrowserStackHomePage(driver);
objBrowserStackHomePage.veryHeader();
objBrowserStackHomePage.clickOnGetStarted();
}
@Test(priority = 2)
public void enter_userDetails() {
objBrowserStackSignUpPage = new BrowserStackSignUpPage(driver);
objBrowserStackSignUpPage.veryHeader();
objBrowserStackSignUpPage.enterFullName("TestUser");
objBrowserStackSignUpPage.enterBusinessEmail("TestUser@gmail.com");
objBrowserStackSignUpPage.enterPasswrod("TestUserPassword");
}
}What is Page Factory in Selenium?
Page Factory is a class provided by Selenium WebDriver to support Page Object Design patterns. In Page Factory, testers use @FindBy annotation. The initElements method is used to initialize web elements.
1. @FindBy: An annotation used in Page Factory to locate and declare web elements using different locators. Below is an example of declaring an element using @FindBy
@FindBy(id="elementId") WebElement element;
Similarly, one can use @FindBy with different location strategies to find web elements and perform actions on them. Below are locators that can be used:
2. initElements(): initElements is a static method in Page Factory class. Using the initElements method, one can initialize all the web elements located by @FindBy annotation.
3. lazy initialization: AjaxElementLocatorFactory is a lazy load concept in Page Factory. This only identifies web elements when used in any operation or activity. The timeout of a web element can be assigned to the object class with the help of the AjaxElementLocatorFactory.
Implementing Page Factory in Selenium Project
This will try to use the same project used for the POM Model. It will reuse the 2-page files and implement Page Factory.
- BrowserStackHomePage
- BrowserStackSignUpPage
As discussed earlier, each of these files will only contain UI elements or Objects present on these screens along with the operations to be performed on these elements.
Sample Project Structure for Page Factory
The project structure will not change as the same project is being used. As already mentioned, Page Factory supports Page Object Model design pattern.

BrowserStackHomePage Java File

Explanation of Code
- Code Line-13 to 17: Identifying elements present on BrowserStack Home Page such as header and Get Started button using Page Factory @FindBy annotation
- Code Line-23 to 30: Performing actions on identified objects on the BrowserStack Home Page
Code Snippet
package browserStackPages;
import static org.testng.Assert.assertEquals;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class BrowserStackHomePage {
WebDriver driver;
@FindBy(xpath = "//h1")
WebElement Header;
@FindBy(xpath = "//*[@id='signupModalButton']")
WebElement getStarted;
public BrowserStackHomePage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void veryHeader() {
String getheadertext = Header.getText();
assertEquals("App & Browser Testing Made Easy", getheadertext);
}
public void clickOnGetStarted() {
getStarted.click();
}
}BrowserStackSignUpPage Java File

Explanation of Code
- Code Line-14 to 24: Identifying elements on BrowserStack SignUp Page, such as the header and Get Started button, using Page Factory @FindBy annotation.
- Code Line-26 to 46: Performing actions on identified objects on the BrowserStack SignUp Page
Code Snippet
package browserStackPages;
import static org.testng.Assert.assertEquals;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class BrowserStackSignUpPage {
WebDriver driver;
@FindBy(xpath = "//h1")
WebElement Header;
@FindBy(xpath = "//*[@id='user_full_name']")
WebElement userName;
@FindBy(xpath = "//*[@id='user_email_login']")
WebElement businessEmail;
@FindBy(xpath = "//*[@id='user_password']")
WebElement password;
public BrowserStackSignUpPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void veryHeader() {
String getheadertext = Header.getText().trim();
assertEquals("Create a FREE Account", getheadertext);
}
public void enterFullName(String arg1) {
userName.sendKeys(arg1);
}
public void enterBusinessEmail(String arg1) {
businessEmail.sendKeys(arg1);
}
public void enterPasswrod(String arg1) {
password.sendKeys(arg1);
}
}BrowserStackSetup Java File

Explanation of Code
- Code Line-21 to 27: Setting up of browser and website to execute our scripts
- Code Line-29 to 43: Initializing driver objects to BrowserStackHomePage & BrowserStackSignUpPage and performing actions on those pages.
Code Snippet
package browserStackSetup;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import browserStackPages.BrowserStackHomePage;
import browserStackPages.BrowserStackSignUpPage;
public class BrowserStackSetup {
String driverPath = "C:\\geckodriver.exe";
WebDriver driver;
BrowserStackHomePage objBrowserStackHomePage;
BrowserStackSignUpPage objBrowserStackSignUpPage;
@BeforeTest
public void setup() {
System.setProperty("webdriver.chrome.driver", "C:\\BrowserStack\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("https://www.browserstack.com/");
}
@Test(priority = 1)
public void navigate_to_homepage_click_on_getstarted() {
objBrowserStackHomePage = new BrowserStackHomePage(driver);
objBrowserStackHomePage.veryHeader();
objBrowserStackHomePage.clickOnGetStarted();
}
@Test(priority = 2)
public void enter_userDetails() {
objBrowserStackSignUpPage = new BrowserStackSignUpPage(driver);
objBrowserStackSignUpPage.veryHeader();
objBrowserStackSignUpPage.enterFullName("TestUser");
objBrowserStackSignUpPage.enterBusinessEmail("TestUser@gmail.com");
objBrowserStackSignUpPage.enterPasswrod("TestUserPassword");
}
}Test Result

Difference between Page Object Model & Page Factory in Selenium
| Page Object Model | Page Factory |
|---|---|
| Finding web elements using By | Finding web elements using @FindBy |
| POM does not provide lazy initialization | Page Factory does provide lazy initialization |
| Page Object Model is a design pattern | PageFactory is a class that implements the Page Object Model design pattern. |
| In POM, one needs to initialize every page object individually | In PageFactory, all page objects are initialized by using the initElements() method |
Run the code to test the workings of the Page Object Model (POM) and Page Factory. Since these are important Selenium functions, testers need to be able to use them with ease and accuracy for Selenium automation. This will help them streamline automation testing efforts and get results quicker.
Optimize Your POM and Page Factory Framework with BrowserStack Automate
Using POM and Page Factory helps organize your Selenium framework, but ensuring that these tests run reliably across real user conditions requires consistent cross-browser execution.
BrowserStack Automate enables you to run your POM-based tests on a cloud of real desktop and mobile browsers, validating that your locators and workflows behave as expected across versions and operating systems.
Key Advantages of using BrowserStack Automate include:
- Real Browser Coverage: Execute tests on real Chrome, Firefox, Safari, and Edge versions, ensuring your Page Objects work in the same environments your users rely on.
- Reliable Debugging Tools: Access videos, screenshots, browser logs, console logs, and network logs to quickly identify locator mismatches, timing issues, and browser-specific inconsistencies.
- Faster Maintenance: Easily detect failing elements or outdated selectors using visual evidence and browser data, helping teams update Page Objects with better accuracy.
- Parallel Execution at Scale: Run multiple POM-based tests simultaneously, reducing overall execution time and accelerating CI/CD feedback cycles.
- Seamless CI Integration: Integrate your POM/Page Factory framework with Jenkins, GitHub Actions, CircleCI, Azure DevOps, and more to automate cross-browser testing in your pipeline.
By combining structured page models with BrowserStack’s real-browser infrastructure, teams achieve more stable automation, faster triaging, and greater confidence in their end-to-end workflows.
Other Design Patterns used in Selenium
Other Design Patterns used in Selenium
Design Patterns in Test Automation Framework are pivotal. There are different other design patterns that are used in Selenium such as:
- Singleton Design Pattern
- Fluent Page Object Model
- Factory Design Pattern
- Facade Design Pattern
Singleton Design Pattern: The Singleton design pattern ensures that no more than one instance of a class is created. It is often used when a single instance of an object is required to coordinate actions across the system. For example, in Selenium, the WebDriver object is typically a Singleton, as there should be only one instance of the browser for the entire test run.
Fluent Page Object Model: The Fluent Page Object Model is an extension of the Page Object Model, where methods are chained together to form a fluent interface. This makes the test code more readable and concise, as multiple actions can be performed on the page in a single line of code.
Factory Design Pattern: This is used to create instances of classes. It is often used when a single class is not enough to create the required objects, and multiple subclasses are required. This pattern provides a way to encapsulate the object creation process and makes it easier to change the object creation process without affecting the rest of the code.
Facade Design Pattern: The Facade design pattern provides a simplified interface to a complex system. It is used to make it easier to use the system by hiding its complexity behind a single interface. The Facade pattern can be used in Selenium to provide a simplified API for interacting with the browser, making it easier to write tests that are maintainable and easy to read.
Read More: Design Patterns in Selenium
Conclusion
Page Object Model (POM) and Page Factory are essential patterns for building scalable, maintainable, and efficient test automation frameworks in Selenium. By organizing web elements and actions into dedicated page classes and leveraging annotations for element initialization, these patterns simplify test code management and reduce duplication.
Incorporating platforms like BrowserStack into your testing strategy further enhances the effectiveness of POM and Page Factory by enabling seamless cross-browser and cross-device testing on real environments. Together, these approaches ensure more reliable test automation and faster release cycles for modern web applications.
Useful Resources for Automation Testing in Selenium
Methods, Classes, and Commands
- Selenium Commands every Developer or Tester must know
- Selenium WebElement Commands
- Desired Capabilities in Selenium Webdriver
- Assert and Verify Methods in Selenium
- Understanding System setProperty in Selenium
- Select Class in Selenium : How to select a value in dropdown list?
- SendKeys in Selenium WebDriver
- getAttribute() method in Selenium: What, Why, and How to use
- How does Selenium isDisplayed() method work?
- findElement vs findElements in Selenium
- Types of Listeners in Selenium (with Code Examples)
- How to set Proxy in Firefox using Selenium WebDriver?
Configuration
- How to set up Selenium on Visual Studio
- How to configure Selenium in Eclipse
- Maven Dependency Management with Selenium
- How to Build and Execute Selenium Projects
XPath
- How to use XPath in Selenium?
- How to find element by XPath in Selenium with Example
- Top Chrome Extensions to find Xpath in Selenium
Locators and Selectors
- Locators in Selenium: A Detailed Guide
- CSS Selector in Selenium: Locate Elements with Examples
- How to Create Object Repository in Selenium
Waits in Selenium
- Wait Commands in Selenium C and C#
- Selenium Wait Commands: Implicit, Explicit, and Fluent Wait
- Understanding Selenium Timeouts
- Understanding ExpectedConditions in Selenium
- Understanding Role of Thread.sleep() in Selenium
Frameworks in Selenium
- Data Driven Framework in Selenium
- Implementing a Keyword Driven Framework for Selenium: A Practical Guide
- Hybrid Framework in Selenium
Miscellaneous
- How to create Selenium test cases
- How to set Proxy in Selenium?
- Difference between Selenium Standalone server and Selenium server
- Exception Handling in Selenium WebDriver
- How to use JavascriptExecutor in Selenium
- How to run your first Selenium test script
- Parallel Testing with Selenium
Best Practices, Tips and Tricks
- Top 5 Challenges Faced During Automation Selenium Testing
- 5 Selenium tricks to make your life easier
- 6 Things to avoid when writing Selenium Test Scripts
- Best Practices for Selenium Test Automation
- Why you should pay attention to flaky Selenium tests
- How to start with Selenium Debugging
- How to make your Selenium test cases run faster
- How to upgrade from Selenium 3 to Selenium 4
- Why you should move your testing to a Selenium Cloud?
Design Patterns in Selenium: Page Object Model and Page Factory
- Design Patterns in Selenium
- Page Object Model and Page Factory in Selenium
- Page Object Model and Page Factory in Selenium C#
- Page Object Model in Selenium and JavaScript
- Page Object Model and Page Factory in Selenium Python
Action Class
- How to handle Action class in Selenium
- How to perform Mouse Hover Action in Selenium
- Understanding Click Command in Selenium
- How to perform Double Click in Selenium?
- How to Drag and Drop in Selenium?
- How to Scroll Down or Up using Selenium Webdriver
- How To verify Tooltip Using Selenium
TestNG and Selenium
- Database Testing using Selenium and TestNG
- How to use DataProvider in Selenium and TestNG?
- All about TestNG Listeners in Selenium
- How to run parallel test cases in TestNG
- How to use TestNG Reporter Log in Selenium: Tutorial
- Prioritizing tests in TestNG with Selenium
JUnit and Selenium
- Understanding JUnit assertions for Selenium Testing with Examples
- How to run JUnit Parameterized Test in Selenium
- How to write JUnit test cases
- JUnit Testing Tutorial: JUnit in Java
- How to create JUnit Test Suite? (with Examples)
Use Cases
- Handling Login Popups in Selenium WebDriver and Java
- How to Launch Browser in Selenium
- How to handle Alerts and Popups in Selenium?
- How to get Selenium to wait for a page to load
- How to Find Element by Text in Selenium: Tutorial
- How to Read/Write Excel Data using Apache POI Selenium
- How to handle Captcha in Selenium
- How to handle multiple windows in Selenium?
- How to handle Multiple Tabs in Selenium
- How to find broken links in Selenium
- How to handle Cookies in Selenium WebDriver
- How to handle iFrame in Selenium
- How to handle Web Tables in Selenium
- How To Validate Text in PDF Files Using Selenium Automation
- Get Current URL in Selenium using Python: Tutorial
Types of Testing with Selenium
- Different Testing Levels supported by Selenium
- How to perform UI Testing with Selenium
- Regression Testing with Selenium: Tutorial
- UI Automation using Python and Selenium: Tutorial
- How to Run Visual Tests with Selenium: Tutorial
- How to perform ETL Automation using Selenium
- Cross Browser Testing in Selenium : Tutorial



