Page Object Model concept in Testing Fundamentals - Build an Automation Script
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class LoginPage: def __init__(self, driver): self.driver = driver self.email_input = (By.ID, 'email') self.password_input = (By.ID, 'password') self.login_button = (By.ID, 'loginBtn') def open(self, url): self.driver.get(url) def enter_email(self, email): WebDriverWait(self.driver, 10).until( EC.visibility_of_element_located(self.email_input) ).send_keys(email) def enter_password(self, password): WebDriverWait(self.driver, 10).until( EC.visibility_of_element_located(self.password_input) ).send_keys(password) def click_login(self): WebDriverWait(self.driver, 10).until( EC.element_to_be_clickable(self.login_button) ).click() class DashboardPage: def __init__(self, driver): self.driver = driver self.welcome_message = (By.ID, 'welcomeMsg') def is_welcome_message_displayed(self): return WebDriverWait(self.driver, 10).until( EC.visibility_of_element_located(self.welcome_message) ) is not None def test_login(): driver = webdriver.Chrome() login_page = LoginPage(driver) dashboard_page = DashboardPage(driver) try: login_page.open('https://example.com/login') login_page.enter_email('testuser@example.com') login_page.enter_password('Password123') login_page.click_login() WebDriverWait(driver, 10).until( EC.url_contains('/dashboard') ) assert '/dashboard' in driver.current_url, 'URL after login is incorrect' assert dashboard_page.is_welcome_message_displayed(), 'Welcome message not found on dashboard' finally: driver.quit() if __name__ == '__main__': test_login()
This code uses the Page Object Model to organize the test.
The LoginPage class holds locators and actions for the login page. It has methods to open the page, enter email, enter password, and click login. Each method waits explicitly for the element to be ready before interacting.
The DashboardPage class holds the locator and method to check if the welcome message is visible on the dashboard.
The test_login function creates a browser driver, uses the page objects to perform the login steps, waits for the dashboard URL, and asserts the URL and welcome message presence.
Explicit waits ensure the test does not fail due to slow loading. Separating page details from test logic makes the code easier to maintain and read.
Now add data-driven testing with 3 different sets of login credentials (valid and invalid).
Practice
Page Object Model in software testing?Solution
Step 1: Understand the role of Page Object Model
The Page Object Model (POM) is designed to separate the page details like locators and actions from the test scripts.Step 2: Identify the benefit of separation
This separation makes tests easier to read, write, and maintain because changes in the UI only affect the page objects, not the test logic.Final Answer:
To separate page structure from test logic for easier maintenance -> Option CQuick Check:
Separation of concerns = A [OK]
- Thinking POM combines all tests into one script
- Believing POM avoids using classes and methods
- Confusing POM with writing test steps directly in scripts
Solution
Step 1: Check Python class syntax for page object
In Python, a page object is a class with an __init__ method that accepts the driver and assigns it to self.driver.Step 2: Identify correct syntax
class LoginPage: def __init__(self, driver): self.driver = driver correctly defines a class with __init__ and assigns driver properly. Options A, B, and D have syntax errors or misuse of class variables. LoginPage = function(driver) { this.driver = driver; } is JavaScript syntax, not Python.Final Answer:
class LoginPage: def __init__(self, driver): self.driver = driver -> Option AQuick Check:
Python class with __init__ = C [OK]
- Using function instead of class for page object
- Assigning driver outside __init__ method
- Mixing JavaScript syntax in Python code
login_page.get_title() return if the page title is "Welcome"?
class LoginPage:
def __init__(self, driver):
self.driver = driver
def get_title(self):
return self.driver.titleSolution
Step 1: Understand the get_title method
The method returns self.driver.title, which is the page title property from the driver object.Step 2: Determine the returned value
If the page title is "Welcome", calling get_title() returns the string "Welcome".Final Answer:
"Welcome" -> Option AQuick Check:
Method returns driver.title = "Welcome" [OK]
- Confusing method return with driver object itself
- Assuming method returns None without explicit return
- Thinking method causes error due to missing return
class LoginPage:
def __init__(self, driver):
self.driver = driver
def click_login(self):
self.driver.find_element_by_id('loginBtn').click()Solution
Step 1: Check Selenium locator method usage
In recent Selenium versions, find_element_by_id is deprecated. The correct usage is find_element(By.ID, 'loginBtn') with proper import.Step 2: Identify the fix
Use correct locator method: replace find_element_by_id with find_element(By.ID, 'loginBtn') correctly updates the locator method. Other options do not fix the locator error or are unrelated.Final Answer:
Use correct locator method: replace find_element_by_id with find_element(By.ID, 'loginBtn') -> Option BQuick Check:
Update deprecated locator method = D [OK]
- Ignoring deprecated locator methods
- Adding unnecessary return statements
- Changing method names without reason
Solution
Step 1: Check for proper driver initialization
class SearchPage: def __init__(self, driver): self.driver = driver def search(self, text): box = self.driver.find_element(By.NAME, 'q') box.clear() box.send_keys(text) box.submit() correctly initializes the driver in __init__, so the page object has access to it.Step 2: Verify method encapsulates actions
The search method finds the input box, clears it, sends keys, and submits, all encapsulated in one method, following POM principles.Final Answer:
class SearchPage: def __init__(self, driver): self.driver = driver def search(self, text): box = self.driver.find_element(By.NAME, 'q') box.clear() box.send_keys(text) box.submit() -> Option DQuick Check:
Driver init + encapsulated method = A [OK]
- Not initializing driver in constructor
- Using global driver without passing it
- Splitting one action into multiple unrelated methods
Ready to prove it?
Pass the test and this pattern moves unknown
