Bird
Raised Fist0
Selenium Pythontesting~15 mins

Page factory pattern in Selenium Python - Build an Automation Script

Choose your learning style10 modes available
Login functionality test using Page Factory pattern
Preconditions (3)
Step 1: Open the browser and navigate to 'https://example.com/login'
Step 2: Locate the username input field and enter 'testuser'
Step 3: Locate the password input field and enter 'Test@1234'
Step 4: Locate and click the login button
Step 5: Wait for the dashboard page to load
Step 6: Verify that the URL is 'https://example.com/dashboard'
Step 7: Verify that a welcome message with text 'Welcome, testuser!' is displayed
✅ Expected Result: User is successfully logged in and redirected to the dashboard page with a welcome message displayed
Automation Requirements - Selenium with Python
Assertions Needed:
Verify current URL is 'https://example.com/dashboard'
Verify welcome message text is 'Welcome, testuser!'
Best Practices:
Use Page Factory pattern with @find_element decorators
Use explicit waits to wait for elements or page load
Separate page object class from test class
Use meaningful locator strategies (By.ID, By.NAME, By.CSS_SELECTOR)
Avoid hardcoded sleeps
Automated Solution
Selenium Python
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
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.page_factory import PageFactory
import unittest

class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)
        self.username = (By.ID, 'username')
        self.password = (By.ID, 'password')
        self.login_button = (By.ID, 'loginBtn')

    def enter_username(self, username):
        self.wait.until(EC.visibility_of_element_located(self.username)).send_keys(username)

    def enter_password(self, password):
        self.wait.until(EC.visibility_of_element_located(self.password)).send_keys(password)

    def click_login(self):
        self.wait.until(EC.element_to_be_clickable(self.login_button)).click()

class DashboardPage:
    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)
        self.welcome_message = (By.ID, 'welcomeMsg')

    def get_welcome_text(self):
        element = self.wait.until(EC.visibility_of_element_located(self.welcome_message))
        return element.text

class TestLogin(unittest.TestCase):
    def setUp(self):
        options = Options()
        options.add_argument('--headless')
        self.driver = webdriver.Chrome(options=options)
        self.driver.get('https://example.com/login')

    def test_login_success(self):
        login_page = LoginPage(self.driver)
        login_page.enter_username('testuser')
        login_page.enter_password('Test@1234')
        login_page.click_login()

        # Verify URL
        WebDriverWait(self.driver, 10).until(EC.url_to_be('https://example.com/dashboard'))
        self.assertEqual(self.driver.current_url, 'https://example.com/dashboard')

        dashboard_page = DashboardPage(self.driver)
        welcome_text = dashboard_page.get_welcome_text()
        self.assertEqual(welcome_text, 'Welcome, testuser!')

    def tearDown(self):
        self.driver.quit()

if __name__ == '__main__':
    unittest.main()

The code uses Selenium WebDriver with Python's unittest framework.

We define two page classes: LoginPage and DashboardPage. Each class holds locators and methods to interact with page elements.

In LoginPage, methods enter username, password, and click login button using explicit waits to ensure elements are ready.

In DashboardPage, we wait for the welcome message to appear and get its text.

The test class TestLogin opens the browser in headless mode, navigates to login page, performs login steps, then verifies the URL and welcome message text.

Explicit waits avoid timing issues. Locators use IDs for reliability. The Page Factory pattern is followed by separating page logic from test logic, making code clean and maintainable.

Common Mistakes - 4 Pitfalls
Using time.sleep() instead of explicit waits
Locating elements inside test methods instead of page classes
Using brittle locators like absolute XPaths
Not quitting the browser after tests
Bonus Challenge

Now add data-driven testing with 3 different username and password combinations to verify login success or failure.

Show Hint

Practice

(1/5)
1. What is the main purpose of using the Page Factory pattern in Selenium with Python?
easy
A. To generate test reports automatically
B. To execute tests faster by parallel processing
C. To group web elements in a class for easier access and maintenance
D. To handle browser pop-ups and alerts

Solution

  1. Step 1: Understand the role of Page Factory

    Page Factory helps organize web elements by grouping them in a class, making tests easier to read and maintain.
  2. Step 2: Compare with other options

    Options B, C, and D describe different Selenium features unrelated to Page Factory's main purpose.
  3. Final Answer:

    To group web elements in a class for easier access and maintenance -> Option C
  4. Quick Check:

    Page Factory = Group elements for easy access [OK]
Hint: Page Factory groups elements in classes for neat tests [OK]
Common Mistakes:
  • Confusing Page Factory with test execution speed
  • Thinking it generates reports
  • Assuming it handles browser alerts
2. Which of the following is the correct way to declare a web element using Page Factory in Selenium Python?
easy
A. element = driver.find_element(By.ID, 'username')
B. username = (By.ID, 'username')
C. username = self.driver.find_element_by_id('username')
D. username = self.driver.find_element(By.ID, 'username')

Solution

  1. Step 1: Identify Page Factory syntax in Python

    Page Factory uses class attributes with locator tuples like (By.ID, 'username') to declare elements before initializing them.
  2. Step 2: Check each option

    username = (By.ID, 'username') shows the correct locator tuple usage, which is standard in Page Factory.
  3. Final Answer:

    username = (By.ID, 'username') -> Option B
  4. Quick Check:

    Page Factory uses locator tuples (By.xx, 'value') [OK]
Hint: Declare Page Factory elements as (By.xx, 'value') tuples [OK]
Common Mistakes:
  • Using direct driver.find_element calls instead of Page Factory declarations
  • Missing the locator tuple syntax
  • Assigning elements directly without initialization
3. Given the following code snippet using Page Factory in Selenium Python, what will be the output of print(page.login_button.is_displayed()) if the button is visible on the page?
from selenium.webdriver.common.by import By
from selenium.webdriver.support.page_factory import PageFactory

class LoginPage:
    def __init__(self, driver):
        self.driver = driver
        PageFactory.init_elements(driver, self)

    login_button = (By.ID, 'loginBtn')

page = LoginPage(driver)
print(page.login_button.is_displayed())
medium
A. True
B. False
C. AttributeError
D. None

Solution

  1. Step 1: Understand Page Factory element initialization

    PageFactory.init_elements initializes elements so login_button refers to the actual web element.
  2. Step 2: Check the method call

    If the button is visible, is_displayed() returns True, so printing it outputs True.
  3. Final Answer:

    True -> Option A
  4. Quick Check:

    Visible element's is_displayed() = True [OK]
Hint: is_displayed() returns True if element is visible [OK]
Common Mistakes:
  • Expecting None because locator needs initialization
  • Confusing AttributeError due to wrong initialization
  • Assuming is_displayed() returns string
4. Identify the error in the following Page Factory code snippet and choose the correct fix:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.page_factory import PageFactory

class HomePage:
    def __init__(self, driver):
        self.driver = driver
        PageFactory.init_elements(self, self.driver)

    submit_button = (By.XPATH, "//button[@id='submit']")

page = HomePage(driver)
page.submit_button.click()
medium
A. Initialize elements with PageFactory.init_elements(driver, self)
B. Replace @FindBy with @find_by (lowercase)
C. Import FindBy from correct module and use it as decorator
D. Import and use find_element instead of PageFactory

Solution

  1. Step 1: Check PageFactory.init_elements arguments

    The code uses PageFactory.init_elements(self, self.driver) but arguments must be driver first, then self.
  2. Step 2: Confirm correct usage

    Using PageFactory.init_elements(driver, self) fixes the error and allows proper element initialization.
  3. Final Answer:

    Initialize elements with PageFactory.init_elements(driver, self) -> Option A
  4. Quick Check:

    init_elements(driver, self) order [OK]
Hint: PageFactory.init_elements(driver, self) - driver first [OK]
Common Mistakes:
  • Wrong argument order for PageFactory.init_elements
  • Using wrong decorator name case
  • Incorrect PageFactory.init_elements parameters
5. You want to create a Page Factory class for a login page with username, password fields, and a login button. Which approach correctly applies the Page Factory pattern to initialize and use these elements in Selenium Python?
hard
A. Write all element locators inside test functions without any class or decorator
B. Use driver.find_element calls inside each test method without class grouping
C. Create global variables for elements outside any class and access them directly
D. Declare elements with @FindBy decorators, initialize with PageFactory.init_elements, then use element methods

Solution

  1. Step 1: Understand Page Factory best practice

    Page Factory groups elements in a class using locator tuples and initializes them with PageFactory.init_elements.
  2. Step 2: Compare with other options

    Options B, C, and D do not use Page Factory pattern and lead to less maintainable code.
  3. Final Answer:

    Declare elements with @FindBy decorators, initialize with PageFactory.init_elements, then use element methods -> Option D
  4. Quick Check:

    Page Factory = locators + init_elements + class grouping [OK]
Hint: Use locators and init_elements to organize page elements [OK]
Common Mistakes:
  • Skipping class and locators for elements
  • Using driver calls directly in tests
  • Not initializing elements with PageFactory
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard