How to Implement Page Object Model in Python with Selenium
To implement the
Page Object Model in Python with Selenium, create separate classes for each web page that contain locators and methods to interact with page elements. Then, write test scripts that use these classes to perform actions, keeping tests clean and easy to maintain.Syntax
The Page Object Model uses classes to represent web pages. Each class has:
- Locators: Variables that find elements on the page.
- Methods: Functions that perform actions on those elements.
- Constructor: Initializes the WebDriver instance.
This separates page details from test logic.
python
from selenium.webdriver.common.by import By class LoginPage: def __init__(self, driver): self.driver = driver self.username_input = (By.ID, 'username') self.password_input = (By.ID, 'password') self.login_button = (By.ID, 'loginBtn') def enter_username(self, username): self.driver.find_element(*self.username_input).send_keys(username) def enter_password(self, password): self.driver.find_element(*self.password_input).send_keys(password) def click_login(self): self.driver.find_element(*self.login_button).click()
Example
This example shows a simple login page object and a test that uses it to perform a login action.
python
from selenium import webdriver from selenium.webdriver.common.by import By import time class LoginPage: def __init__(self, driver): self.driver = driver self.username_input = (By.ID, 'username') self.password_input = (By.ID, 'password') self.login_button = (By.ID, 'loginBtn') def enter_username(self, username): self.driver.find_element(*self.username_input).send_keys(username) def enter_password(self, password): self.driver.find_element(*self.password_input).send_keys(password) def click_login(self): self.driver.find_element(*self.login_button).click() # Test script driver = webdriver.Chrome() driver.get('https://example.com/login') login_page = LoginPage(driver) login_page.enter_username('testuser') login_page.enter_password('password123') login_page.click_login() # Wait to see result (not for real tests) time.sleep(3) driver.quit()
Output
Test runs opening the browser, entering credentials, clicking login, then closing browser after 3 seconds.
Common Pitfalls
- Hardcoding locators inside test scripts instead of page classes makes maintenance hard.
- Not using
*to unpack locator tuples causes errors infind_element. - Mixing test logic and page actions reduces readability.
- Not waiting for elements to load can cause flaky tests.
Always keep locators and actions inside page classes and use explicit waits in real tests.
python
from selenium.webdriver.common.by import By # Wrong: locator used directly without unpacking class WrongPage: def __init__(self, driver): self.driver = driver self.button = (By.ID, 'btn') def click_button(self): # This will cause an error self.driver.find_element(self.button).click() # Right: unpack locator tuple with * class RightPage: def __init__(self, driver): self.driver = driver self.button = (By.ID, 'btn') def click_button(self): self.driver.find_element(*self.button).click()
Quick Reference
- Page Class: Represents a web page.
- Locators: Store element selectors as tuples.
- Methods: Perform actions on elements.
- Tests: Use page classes to keep tests clean.
- Use:
find_element(*locator)to unpack locator tuples.
Key Takeaways
Create separate classes for each page with locators and methods to interact with elements.
Use locator tuples unpacked with * in find_element calls to avoid errors.
Keep test scripts clean by calling page class methods instead of direct Selenium commands.
Avoid mixing test logic and page details to improve maintainability.
Use explicit waits in real tests to handle dynamic page loading.