Page Object Model (POM) in Selenium: Complete Guide with Java Examples
Introduction to Page Object Model in Selenium
Automated testing is an essential part of modern software development. As web applications become more complex, maintaining reliable test scripts can become challenging. The Page Object Model (POM) is a widely used design pattern that helps testers organize Selenium automation code into reusable and maintainable components.
POM separates the code responsible for interacting with a web page from the code responsible for testing application functionality. This separation makes test scripts easier to understand, update, and expand as an application evolves.
Whether you are a beginner learning Selenium WebDriver or an experienced QA engineer building a large automation framework, understanding POM can help you write cleaner and more structured automated tests.
What Is Page Object Model (POM) in Selenium?
The Page Object Model is a design pattern in which each significant page or component of a web application is represented by a separate class, known as a Page Object.
A Page Object contains information about the page’s web elements and provides methods for interacting with them. Test classes use these methods instead of repeatedly locating elements and performing browser actions directly.
For example, an application login page may contain username and password fields, a login button, and an error message. A LoginPage class can encapsulate these elements and provide methods such as enterUsername(), enterPassword(), and clickLogin().
The test class can then focus on verifying whether login succeeds or fails.
POM is a design pattern, not a separate testing tool. It works with Selenium WebDriver and can be combined with testing frameworks such as TestNG, JUnit, and NUnit.
Why Is POM Important in Selenium Automation?
As a test suite grows, the same elements and interactions often appear in multiple test cases. Without a structured approach, a small user-interface change may require updates to many scripts.
POM helps address this problem by centralizing page-specific interactions and separating them from test logic.
1. Improved Code Reusability
Common actions can be implemented once in a Page Object and reused across multiple test cases.
For example, several tests may need to log in before performing different operations. Instead of repeating the username, password, and button interaction code, each test can use the same login-page methods.
2. Easier Test Maintenance
When an element locator changes, the corresponding Page Object can usually be updated in one place.
This reduces the number of test files that need modification and makes maintenance more manageable.
3. Better Readability
POM allows test cases to describe business scenarios using meaningful method names instead of lengthy sequences of browser commands.
A test that calls loginPage.loginAs(username, password) is easier to understand than one that repeatedly locates fields and clicks buttons.
4. Greater Scalability
Page Objects help organize larger automation projects into logical components. Teams can add new pages and reusable workflows without placing every interaction inside one large test class.
5. Easier Collaboration
A consistent Page Object structure helps developers and testers understand how the framework is organized. This makes it easier for team members to review, maintain, and extend automated tests.
Main Components of a Selenium POM Framework
A Selenium automation framework using POM commonly contains the following components.
| Component | Purpose |
|---|---|
| Page Classes | Encapsulate page elements and user interactions |
| Test Classes | Contain test scenarios and assertions |
| Base Test or Driver Manager | Manages WebDriver setup and cleanup |
| Test Data | Supplies input values for test scenarios |
| Utilities | Provide reusable functions such as configuration loading and screenshots |
| Test Reports and Logging | Help track execution results and investigate failures |
These components are a common framework structure rather than mandatory requirements of the POM design pattern. Small projects may need only Page Objects and test classes, while larger projects can introduce additional layers as required.
How to Implement Page Object Model in Selenium Using Java
Let’s create a simple example using a login page.
The example assumes that a test application provides a login form with username and password fields and a submit button. The element locators and URL should be adjusted to match the actual application.
Step 1: Set Up the Selenium Project
Create a Java project using Maven or Gradle and add a compatible Selenium Java dependency. Select a test framework such as TestNG or JUnit for executing and organizing tests.
A basic Maven project might use this structure:
selenium-pom-project/
├── pom.xml
└── src/
└── test/
└── java/
├── pages/
│ └── LoginPage.java
└── tests/
└── LoginTest.java
For a larger framework, you can add separate packages for driver management, configuration, test data, utilities, and reporting.
Step 2: Create the Login Page Object
Create a class named LoginPage.java. This class defines the element locators and methods needed to interact with the login form.
package pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
public class LoginPage {
private final WebDriver driver;
private final By usernameField =
By.id("username");
private final By passwordField =
By.id("password");
private final By loginButton =
By.cssSelector("button[type='submit']");
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public void enterUsername(String username) {
driver.findElement(usernameField)
.sendKeys(username);
}
public void enterPassword(String password) {
driver.findElement(passwordField)
.sendKeys(password);
}
public void clickLogin() {
driver.findElement(loginButton).click();
}
public void loginAs(String username, String password) {
enterUsername(username);
enterPassword(password);
clickLogin();
}
}
How it works:
- The
WebDriverinstance is passed into the constructor. - The
Byobjects store the locators for the login-page elements. - Public methods provide reusable actions for interacting with the form.
- The
loginAs()method combines the individual actions into one convenient operation.
Notice that the Page Object does not contain the actual test assertion. This keeps page interactions separate from the test’s verification logic.
Step 3: Create the Test Class
Next, create LoginTest.java to verify the login workflow.
The following example uses TestNG and assumes the application redirects successful users to a dashboard URL containing /dashboard.
package tests;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import pages.LoginPage;
public class LoginTest {
private WebDriver driver;
@BeforeMethod
public void setUp() {
driver = new ChromeDriver();
driver.manage().window().maximize();
}
@Test
public void validLoginShouldOpenDashboard() {
driver.get("https://your-test-site.com/login");
LoginPage loginPage = new LoginPage(driver);
loginPage.loginAs(
"testUser",
"testPassword"
);
Assert.assertTrue(
driver.getCurrentUrl().contains("/dashboard"),
"Expected a successful login to open the dashboard"
);
}
@AfterMethod(alwaysRun = true)
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}
Replace the example URL, credentials, and dashboard path with values from your test environment. The test account must be valid for the application.
In a production framework, use explicit waits where appropriate, store credentials securely, and avoid hardcoding sensitive information in test source code.
Step 4: Understand the Execution Flow
When the test runs, it opens the login page, creates a LoginPage object, and calls its loginAs() method. The Page Object interacts with the form, after which the test verifies the expected result.
This approach separates the responsibilities of the test and the Page Object, making each component easier to maintain.
POM Architecture: How the Components Work Together
A typical POM workflow follows this sequence:
- The test framework starts the test.
- The driver-management layer creates a WebDriver instance.
- The test opens the target application.
- The test creates the required Page Object.
- The Page Object performs the requested browser interactions.
- The test checks the expected result using assertions.
- The framework closes the browser and records the test outcome.
This separation improves organization without requiring every project to follow the same directory structure.
Page Object Model vs. Page Factory
Page Object Model and Page Factory are related but different concepts.
Page Object Model is the design pattern used to separate page interactions from test logic.
Page Factory is a Selenium support mechanism historically used to initialize elements declared with annotations such as @FindBy.
For example:
@FindBy(id = "username")
private WebElement usernameField;
Page Factory can initialize this field using PageFactory.initElements(). However, Page Factory is optional and is not required to implement POM.
Many frameworks instead use By locators with driver.findElement() or explicit waits. The choice depends on the project’s needs, Selenium version, and team conventions.
Best Practices for Using POM in Selenium
Keep Page Objects Focused
Each Page Object should represent a meaningful page or reusable component. Avoid creating one oversized class containing interactions for the entire application.
Separate Assertions from Page Interactions
Keep most test-specific assertions in the test layer. Page Objects should primarily provide actions and access to relevant page state.
A Page Object can expose methods such as getErrorMessage() or isDashboardDisplayed() when those methods make the page interface clearer.
Use Reliable Element Locators
Prefer stable identifiers such as unique IDs or well-designed test attributes when available. Avoid fragile locators that depend on a page’s entire HTML structure.
Handle Synchronization Properly
Modern applications often load content asynchronously. Use explicit waits to ensure that elements are visible, clickable, or otherwise ready before interacting with them.
Avoid relying on arbitrary sleep statements as the main synchronization method.
Manage WebDriver Lifecycle Carefully
Initialize and close browser sessions consistently. For larger suites, a driver-management utility can help standardize setup and cleanup.
When running tests in parallel, ensure that each test receives an appropriately isolated WebDriver instance.
Use Meaningful Method Names
Names such as submitOrder(), searchProduct(), and enterUsername() communicate intent more clearly than generic names such as click1() or performAction().
Store Test Data Separately
Keep test data and environment-specific settings outside page-interaction methods where practical. Use secure configuration for passwords and other sensitive values.
Avoid Overengineering
POM does not require a large base class, Page Factory, or a utility class for every action. Introduce abstractions when they provide genuine reuse, clarity, or maintainability.
Real-World Applications of POM
POM is useful in a variety of browser-based testing scenarios.
E-commerce testing: Page Objects can represent product listings, search pages, shopping carts, checkout forms, and order confirmation pages.
Banking applications: Page Objects can organize account navigation, transaction forms, and other web workflows. Test data and access controls must be handled securely.
Enterprise applications: POM can organize complex web interfaces with many forms, tables, and navigation components.
Regression testing: Reusable page interactions allow teams to run the same workflows after application updates and check whether important functionality continues to work.
Cross-browser testing: The same Page Object methods can be reused when tests run against different supported browsers, provided the application and framework are configured appropriately.
POM improves code organization, but it does not automatically guarantee cross-browser compatibility or eliminate flaky tests. Reliable locators, synchronization, and test design remain important.
Skills Required to Learn POM in Selenium
To use POM effectively, build knowledge in the following areas:
- Java or another programming language supported by Selenium.
- Object-oriented programming, including classes, objects, constructors, and methods.
- Selenium WebDriver commands and element locators.
- Assertions, waits, and exception handling.
- A testing framework such as TestNG or JUnit.
- Maven or Gradle for dependency management.
- Git and basic CI/CD concepts for collaborative automation projects.
Beginners should first create simple WebDriver scripts, then refactor repeated interactions into Page Objects. This progression makes the purpose of POM easier to understand.
Frequently Asked Questions
1. What is Page Object Model in Selenium?
Page Object Model is a design pattern that organizes Selenium automation code by representing application pages or components as reusable classes. It separates page interactions from test logic.
2. What are the main benefits of POM?
POM improves code organization, reusability, readability, and maintainability. It also makes larger test suites easier to extend and update.
3. Is Page Object Model a Selenium tool?
No. POM is a design pattern that can be implemented using Selenium WebDriver. It does not require a separate installation.
4. What is the difference between POM and Page Factory?
POM is the overall design pattern. Page Factory is an optional Selenium mechanism for initializing page elements, commonly through annotations such as @FindBy.
5. Is a base class mandatory in POM?
No. A base class is optional. It can be useful for shared setup and teardown or common framework functionality, but smaller projects may not need one.
6. Can POM be used with TestNG and JUnit?
Yes. POM can be used with TestNG, JUnit, NUnit, and other compatible testing frameworks. The choice of framework does not change the fundamental POM concept.
7. Does POM support cross-browser testing?
POM can help reuse the same page-interaction logic across supported browsers. Cross-browser execution still requires suitable driver configuration and validation of application behaviour in each browser.
8. Is POM suitable for beginners?
Yes. Beginners can learn POM after understanding basic programming, Selenium WebDriver commands, and web element locators. Starting with a simple login-page example is a practical way to learn.
9. Is Page Object Model still useful in 2026?
Yes. POM remains a useful approach for structuring Selenium automation projects. Teams should adapt the pattern to their application’s complexity and avoid unnecessary abstractions.
Conclusion
The Page Object Model is a practical design pattern for building maintainable Selenium WebDriver automation frameworks. By separating page-specific interactions from test scenarios, it helps reduce code duplication, improve readability, and simplify changes when an application’s interface evolves.
To get started, create a simple Page Object, write a test that uses its methods, and add reliable assertions and synchronization. As your framework grows, introduce shared utilities, test data management, reporting, and CI/CD integration where they provide clear benefits.
For more tutorials on Selenium WebDriver, automation testing, Java, and other IT skills, explore the learning resources available at Technical Gyan Guru.



