Introduction
As Selenium automation projects grow, writing all the locators and test logic inside the same test file becomes difficult to manage. If the application’s user interface changes, every test script that uses those locators must also be updated. This leads to duplicate code, poor maintainability, and increased effort.
To solve this problem, Selenium follows a design pattern called the Page Object Model (POM).
The Page Object Model organizes the automation framework by separating the web page elements and page actions from the actual test cases. Each web page is represented by its own Python class, making the framework cleaner, reusable, and easier to maintain.
In this tutorial, you’ll learn what the Page Object Model is, why it is widely used in Selenium automation, how it works, its advantages, and how to create your first Page Object class.
What is Page Object Model (POM)?
The Page Object Model (POM) is a design pattern used in Selenium automation that represents each web page as a separate Python class.
Instead of writing Selenium commands directly inside the test cases, all locators and page-specific methods are stored inside dedicated page classes.
The test case simply calls these methods to interact with the application.
This separation makes the automation framework more organized and significantly reduces code duplication.
Why Use Page Object Model?
Using the Page Object Model provides several advantages:
Separates test logic from page implementation.
Keeps locators in one central location.
Reduces duplicate code.
Makes scripts easier to read.
Simplifies maintenance when the UI changes.
Encourages reusable page methods.
Supports scalable automation frameworks.
Improves collaboration among automation engineers.
Without POM vs With POM
Without Page Object Model, every test contains Selenium locators and browser actions.
Test Case
│
├── find_element()
├── click()
├── send_keys()
└── assertions
With Page Object Model, the test interacts only with the page class.
Test Case
│
▼
Page Object
│
▼
Selenium WebDriver
│
▼
Browser
This keeps test cases short, clean, and focused on validation rather than implementation details.
How Does POM Work?
The Page Object Model follows a simple workflow.
Create a separate class for each webpage.
Store all web element locators inside that class.
Create methods that perform actions on the page.
Call those methods from the test case.
Keep assertions inside the test whenever possible.
This approach allows page changes to be handled by updating only the corresponding page class.
Main Components of POM
A typical Page Object contains:
Web element locators
Page actions
Navigation methods
Helper methods
The test class contains:
Test scenarios
Assertions
Test data
Validation logic
This clear separation makes the automation framework easier to maintain.
Example
from selenium import webdriver
from selenium.webdriver.common.by import By
# Topic: 44. Page Object Model (POM) - Introduction to POM
# Practice site: https://www.testmuai.com/selenium-playground/simple-form-demo
# Run: pytest -s 44_examples/test_01_introduction_to_pom.py
#
# POM keeps locators and page actions in page classes so tests stay readable
# and locators are updated in one place.
class SimpleFormPage:
URL = "https://www.testmuai.com/selenium-playground/simple-form-demo"
def __init__(self, driver):
self.driver = driver
def open(self):
self.driver.get(self.URL)
def enter_message(self, text):
self.driver.find_element(By.ID, "user-message").send_keys(text)
def click_show_message(self):
self.driver.find_element(By.ID, "showInput").click()
def get_displayed_message(self):
return self.driver.find_element(By.ID, "message").text
def test_introduction_to_pom():
driver = webdriver.Chrome()
try:
page = SimpleFormPage(driver)
page.open()
page.enter_message("POM Intro")
page.click_show_message()
assert page.get_displayed_message() == "POM Intro"
finally:
driver.quit()
Understanding the Code
Import Required Libraries
from selenium import webdriver
from selenium.webdriver.common.by import By
These modules are required to launch the browser and locate web elements.
Create the Page Object Class
class SimpleFormPage:
A separate Page Object class named SimpleFormPage is created.
This class represents the Simple Form Demo page and contains everything related to that page.
Store the Page URL
URL = "https://www.testmuai.com/selenium-playground/simple-form-demo"
Instead of hardcoding the URL inside every test, it is stored once as a class variable.
This makes future maintenance much easier.
Create the Constructor
def __init__(self, driver):
self.driver = driver
The constructor receives the WebDriver instance and stores it inside the class.
This allows every method in the page object to use the same browser session.
Open the Webpage
def open(self):
self.driver.get(self.URL)
The open() method navigates to the page.
Instead of writing driver.get() inside every test, the test simply calls:
page.open()
Enter the Message
def enter_message(self, text):
This method enters text into the input field.
All Selenium code remains inside the page object, while the test only passes the required message.
Click the Button
def click_show_message(self):
This method clicks the Show Message button.
The test does not need to know how the button is located.
Read the Displayed Message
def get_displayed_message(self):
This method returns the text displayed on the webpage.
Keeping page interactions inside methods improves readability and reusability.
Create the Page Object
page = SimpleFormPage(driver)
An object of the SimpleFormPage class is created.
The test will now interact with the page through this object instead of directly using Selenium commands.
Perform Page Actions
page.open()
page.enter_message("POM Intro")
page.click_show_message()
The test calls reusable page methods to perform all required actions.
This makes the test easy to read and understand.
Verify the Result
assert page.get_displayed_message() == "POM Intro"
The assertion verifies that the displayed message matches the expected value.
The validation remains inside the test case, while the page object simply returns the data.
Close the Browser
driver.quit()
Closes the browser and ends the WebDriver session.
Practical Example
Suppose an application has a Login Page used by hundreds of automated tests.
Instead of storing the login locators in every test, a LoginPage class is created with methods such as:
Enter username
Enter password
Click Login
Every test simply reuses these methods.
Automation Testing Example
Consider an e-commerce website.
The automation framework creates separate page classes for:
Home Page
Login Page
Product Page
Cart Page
Checkout Page
Each page contains only its own locators and actions, while the test cases combine these page objects to complete end-to-end workflows.
Real-World Example
The Page Object Model is widely used in:
Banking applications
E-commerce websites
Healthcare systems
CRM applications
ERP software
Insurance portals
Government websites
Enterprise web applications
Nearly every professional Selenium automation framework uses POM because it simplifies maintenance and supports large-scale projects.
Advantages of Using POM
Improves code organization.
Reduces duplicate Selenium code.
Keeps locators centralized.
Makes maintenance easier.
Encourages reusable methods.
Simplifies framework scalability.
Produces cleaner and more readable test scripts.
Supports team collaboration.
Common Mistakes Beginners Make
Mixing Test Logic and Page Logic
Keep Selenium interactions inside the Page Object and assertions inside the test case.
Creating One Large Page Class
Each webpage should have its own dedicated page class.
Avoid combining multiple pages into a single class.
Duplicating Locators
Store each locator only once inside the corresponding page object.
Hardcoding Values
Avoid hardcoding URLs, locators, and repeated values throughout the project.
Centralize them wherever possible.
Best Practices
Create one Page Object class for each webpage.
Keep locators inside the page class.
Create meaningful page methods.
Keep assertions inside test cases.
Use descriptive class and method names.
Keep page objects focused on page interactions only.
Reuse page methods across multiple tests.
Conclusion
The Page Object Model (POM) is one of the most important design patterns in Selenium automation. By separating page elements and actions from test logic, POM creates automation frameworks that are cleaner, reusable, easier to maintain, and scalable. It is widely adopted in professional automation projects and forms the foundation of most modern Selenium frameworks.
Frequently Asked Questions (FAQs)
What is the Page Object Model?
The Page Object Model (POM) is a Selenium design pattern where each webpage is represented by a separate class containing its locators and page actions.
Why is POM used?
POM improves code organization, reduces duplication, simplifies maintenance, and promotes code reuse.
Should assertions be written inside Page Objects?
Generally, no.
Page Objects should perform page interactions, while assertions should remain inside the test cases.
Can one Page Object represent multiple webpages?
No.
Each webpage should have its own dedicated Page Object class.
Is POM suitable for small projects?
Yes.
Although POM is especially beneficial for medium and large automation projects, using it even in small projects helps establish good automation practices.
Key Takeaways
Page Object Model (POM) is a design pattern for Selenium automation.
Each webpage is represented by a separate Python class.
Page Objects contain locators and page-specific methods.
Test cases call Page Object methods instead of directly interacting with Selenium.
POM improves maintainability, readability, reusability, and scalability.
Most professional Selenium automation frameworks are built using the Page Object Model.
