Creating Page Classes

Introduction

After understanding the Page Object Model (POM), the next step is learning how to create Page Classes. A Page Class represents a single webpage in your application and contains everything related to that page, including its locators and the actions that can be performed on it.

Instead of writing Selenium code repeatedly in every test case, Page Classes organize all page-specific functionality into reusable methods. This makes test scripts cleaner, easier to understand, and much simpler to maintain.

In this tutorial, you’ll learn how to create Page Classes in Selenium with Python, along with practical examples, real-world scenarios, common mistakes, and best practices.


What are Page Classes?

A Page Class is a Python class that represents a single webpage of an application.

Each Page Class typically contains:

  • Page URL

  • Web element locators

  • Methods that perform user actions

  • Methods that return information from the page

The test case interacts with the Page Class instead of directly using Selenium commands.


Why Create Page Classes?

Creating Page Classes helps you:

  • Keep Selenium code organized.

  • Store locators in one place.

  • Reduce duplicate code.

  • Improve code readability.

  • Simplify maintenance.

  • Reuse page actions across multiple tests.

  • Support scalable automation frameworks.


Structure of a Page Class

A typical Page Class contains the following components:

Page Class
     │
     ├── URL
     ├── Locators
     ├── Constructor
     ├── Page Actions
     └── Getter Methods

Each component has a specific responsibility, making the class easy to understand and maintain.


What Does a Page Class Contain?

Most Page Classes include:

  • A URL for opening the page.

  • Locators that identify web elements.

  • Methods that perform user actions such as clicking buttons or entering text.

  • Methods that return values from the page for verification.

This keeps all page-related logic inside a single class.


Example

from selenium import webdriver
from selenium.webdriver.common.by import By


# Topic: 44. Page Object Model (POM) - Creating Page Classes
# Practice site: https://www.testmuai.com/selenium-playground/checkbox-demo
# Run: pytest -s 44_examples/test_02_creating_page_classes.py
#
# A page class usually stores locators as attributes and exposes methods named
# after user actions.


class CheckboxDemoPage:
    URL = "https://www.testmuai.com/selenium-playground/checkbox-demo"
    SINGLE_CHECKBOX = (By.ID, "isAgeSelected")

    def __init__(self, driver):
        self.driver = driver

    def open(self):
        self.driver.get(self.URL)
        return self

    def check_age_checkbox(self):
        element = self.driver.find_element(*self.SINGLE_CHECKBOX)
        if not element.is_selected():
            element.click()
        return self

    def is_age_checked(self):
        return self.driver.find_element(*self.SINGLE_CHECKBOX).is_selected()


def test_creating_page_classes():
    driver = webdriver.Chrome()

    try:
        page = CheckboxDemoPage(driver).open().check_age_checkbox()
        assert page.is_age_checked()
    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 Class

class CheckboxDemoPage:

A Page Class named CheckboxDemoPage is created.

This class represents the Checkbox Demo webpage and contains all its locators and actions.


Store the Page URL

URL = "https://www.testmuai.com/selenium-playground/checkbox-demo"

The webpage URL is stored as a class attribute.

This allows the page to be opened from a single location without hardcoding the URL in multiple test cases.


Store the Locator

SINGLE_CHECKBOX = (
    By.ID,
    "isAgeSelected"
)

The checkbox locator is stored as a class attribute.

Keeping locators inside the Page Class makes them easy to update if the application’s UI changes.


Create the Constructor

def __init__(self, driver):
    self.driver = driver

The constructor receives the WebDriver instance and stores it in the Page Class.

All page methods use this shared driver object to interact with the browser.


Open the Webpage

def open(self):
    self.driver.get(self.URL)
    return self

The open() method navigates to the webpage.

The statement:

return self

returns the current Page Class object, allowing method chaining.

For example:

page.open().check_age_checkbox()

Multiple methods can be called in a single statement.


Check the Checkbox

def check_age_checkbox(self):

This method performs the action of selecting the checkbox.

Instead of writing Selenium code in every test, the Page Class exposes a descriptive method that represents the user’s action.


Locate the Checkbox

element = self.driver.find_element(
    *self.SINGLE_CHECKBOX
)

The locator stored in SINGLE_CHECKBOX is passed to find_element() using the unpacking operator (*).

This is a common practice in Page Object Model because locators are stored as tuples.


Verify Before Clicking

if not element.is_selected():
    element.click()

Before clicking, the method checks whether the checkbox is already selected.

If it is not selected, Selenium clicks it.

This prevents unnecessary clicks and makes the method more reliable.


Return the Page Object

return self

Returning the current object allows additional Page Class methods to be chained together.

This improves readability and creates cleaner automation code.


Verify the Checkbox Status

def is_age_checked(self):

This method returns whether the checkbox is currently selected.

Instead of exposing Selenium code to the test, the Page Class provides a simple method that returns the required information.


Create the Page Object

page = CheckboxDemoPage(driver)

An object of the CheckboxDemoPage class is created.

The test now interacts with the webpage through this object rather than directly using Selenium commands.


Perform Page Actions

page = (
    CheckboxDemoPage(driver)
    .open()
    .check_age_checkbox()
)

The test opens the webpage and selects the checkbox using method chaining.

The test remains short, clean, and easy to understand.


Verify the Result

assert page.is_age_checked()

The assertion verifies that the checkbox is selected.

If the checkbox is not selected, the test fails.


Close the Browser

driver.quit()

Closes the browser and ends the WebDriver session.


Practical Example

Suppose an application has a Login Page.

A LoginPage class can contain methods such as:

  • Enter username

  • Enter password

  • Click Login

  • Read error message

Every login test simply calls these methods instead of writing Selenium code repeatedly.


Automation Testing Example

Consider an online shopping application.

Separate Page Classes can be created for:

  • Home Page

  • Login Page

  • Product Page

  • Shopping Cart

  • Checkout Page

Each class manages only its own page, making the framework modular and easy to maintain.


Real-World Example

Creating Page Classes is a standard practice in:

  • Banking applications

  • E-commerce websites

  • Healthcare systems

  • CRM applications

  • ERP software

  • Travel booking portals

  • Enterprise web applications

Professional Selenium frameworks typically create one Page Class for each webpage.


Advantages of Creating Page Classes

  • Improves code organization.

  • Centralizes locators.

  • Reduces duplicate Selenium code.

  • Encourages reusable page methods.

  • Simplifies maintenance.

  • Makes test scripts cleaner.

  • Supports scalable automation frameworks.


Common Mistakes Beginners Make

Writing Selenium Code Directly in Tests

Move page interactions into Page Classes instead of repeating Selenium commands in every test.


Storing Locators Inside Test Cases

Keep all page locators inside the corresponding Page Class.


Creating One Large Page Class

Each webpage should have its own Page Class.

Avoid combining multiple pages into one class.


Using Non-Descriptive Method Names

Method names should clearly describe the user action.

Examples include:

  • login()

  • search_product()

  • click_checkout()


Best Practices

  • Create one Page Class for each webpage.

  • Store all locators inside the Page Class.

  • Give methods meaningful names.

  • Return page objects when method chaining is useful.

  • Keep assertions inside test cases.

  • Keep Page Classes focused on page interactions only.


Conclusion

Creating Page Classes is one of the core principles of the Page Object Model. By organizing locators and page actions into dedicated classes, automation frameworks become more reusable, maintainable, and scalable. Well-designed Page Classes lead to cleaner test scripts, reduce code duplication, and make Selenium automation easier to maintain as applications evolve.


Frequently Asked Questions (FAQs)

What is a Page Class?

A Page Class is a Python class that represents a single webpage and contains its locators and page-specific methods.


Why should locators be stored inside Page Classes?

Storing locators in one place makes them easier to maintain when the application’s UI changes.


Why does the open() method return self?

Returning self enables method chaining, allowing multiple page methods to be called in a single statement.


Should assertions be written inside a Page Class?

Generally, no.

Page Classes should perform page interactions, while assertions should remain in the test cases.


Can multiple test cases reuse the same Page Class?

Yes.

One of the main advantages of Page Classes is that they can be reused across many different test cases.


Key Takeaways

  • A Page Class represents a single webpage in the application.

  • It stores the URL, locators, and page actions.

  • Tests interact with Page Classes instead of directly using Selenium commands.

  • Locators are centralized, making maintenance easier.

  • Returning self allows method chaining for cleaner and more readable code.

  • Creating Page Classes is a fundamental practice when building professional Selenium automation frameworks.