Using Page Objects with Python and Selenium: A Practical Guide to Automated Testing

Among various testing strategies, the Page Object Model (POM) stands out for its effectiveness in creating maintainable and reusable code for web application testing. This post dives into the practical application of POM using Python and Selenium, focusing on a shopping scenario on the website practiceautomatedtesting.com.

What is the Page Object Model?

The Page Object Model is a design pattern that encourages abstraction of web page details from the actual tests. Instead of scattering locators (ways to find elements on a page) and page-specific methods throughout test scripts, POM suggests encapsulating them within class objects representing the pages.

Why Use POM?

  • Maintainability: Changes in page structure only require updates in one place.
  • Readability: Tests read more like high-level descriptions than low-level operations.
  • Reusability: Common page elements can be reused across multiple test cases.

Implementing POM for a Shopping Page

Consider a scenario where we automate testing for a shopping page on practiceautomatedtesting.com. We’ll create page objects and then utilize them in test cases.

The ShoppingPage Object

The ShoppingPage class abstracts interactions with the shopping page. It includes methods for navigating to the page, searching for products, sorting, and adding items to the cart.

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.common.action_chains import ActionChains

class ShoppingPage:
    URL = "https://practiceautomatedtesting.com/webelements"
    
    ELEMENTS_MENU = (By.XPATH, "//summary[contains(., 'Elements')]")
    SHOPPING_LINK = (By.XPATH, "//a[contains(., 'Shopping')]")
    # More locators for page elements follow...

    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)
        self.actions = ActionChains(driver)

    def navigate(self):
        """Navigate to the shopping page"""
        self.driver.get(self.URL)
        elements_menu = self.wait.until(EC.element_to_be_clickable(self.ELEMENTS_MENU))
        elements_menu.click()
        shopping_link = self.wait.until(EC.element_to_be_clickable(self.SHOPPING_LINK))
        shopping_link.click()
        self.wait.until(EC.presence_of_element_located(self.PRODUCT_CARDS))

    # Additional methods for interacting with the page follow...

ShoppingPage Methods

  • navigate(): Opens the shopping page and waits for product cards to be visible.
  • search_product(search_term): Enters a search term in the search input.
  • sort_by_name() and sort_by_price(): Sort products accordingly.
  • add_product_to_cart(product_name): Adds a specified product to the cart.

The CheckoutPage Object

Similar to ShoppingPage, the CheckoutPage class encapsulates interactions with the checkout page, including filling payment information and placing orders.

class CheckoutPage:
    URL = "https://practiceautomatedtesting.com/checkout"
    # Locators and methods for interacting with the checkout page follow...

    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 5)

    # Methods for interacting with the checkout page follow...

Using Page Objects in Tests

With our page objects set up, we can now write clear and concise tests. Here’s an example test case that adds a product to the cart and verifies the addition:

import pytest

class TestCheckout:
    @pytest.fixture(autouse=True)
    def setup(self, driver):
        self.shopping_page = ShoppingPage(driver)
        self.checkout_page = CheckoutPage(driver)
        self.shopping_page.navigate()

    def test_add_items_and_checkout(self, driver):
        self.shopping_page.add_product_to_cart_by_aria("Bluetooth Headphones")
        self.shopping_page.go_to_cart()
        # Assertions and further actions to complete and verify checkout follow...

This test demonstrates the clarity and maintainability POM brings to automated testing. By hiding the complexity of UI interactions within the page objects, tests become more about what should happen rather than how.

Conclusion

The Page Object Model is a powerful pattern for web UI test automation, making tests more maintainable, readable, and reusable. By leveraging POM with Python and Selenium, as shown with our shopping page example, teams can efficiently create robust automated test suites for their web applications.