Base Page

Introduction

As an automation framework grows, many web pages require the same Selenium operations such as opening a URL, clicking elements, entering text, waiting for elements to appear, and retrieving text. Writing these operations repeatedly in every page class leads to duplicate code and makes the framework difficult to maintain.

To solve this problem, Selenium frameworks use a Base Page. A Base Page is a parent class that contains common methods shared by all page classes. Instead of rewriting these methods multiple times, every page object inherits them from the Base Page.

Using a Base Page makes the framework cleaner, reduces code duplication, improves maintainability, and allows changes to be made in a single place whenever common functionality needs to be updated.

In this tutorial, you’ll learn what a Base Page is, why it is important in the Page Object Model (POM), how it works, and how to create one using Selenium with Python.


What is a Base Page?

A Base Page is a reusable parent class that stores the common Selenium actions required by multiple page classes.

Instead of writing browser interaction code in every page object, shared operations are placed inside the Base Page so they can be reused throughout the framework.

Typically, a Base Page contains methods for:

  • Opening webpages

  • Clicking web elements

  • Entering text into input fields

  • Reading text from elements

  • Waiting for elements to become visible or clickable

Every page class in the framework can inherit these methods, making the code more organized and easier to maintain.


Why Use a Base Page?

A Base Page provides several benefits:

  • Eliminates duplicate Selenium code.

  • Keeps page classes short and easy to understand.

  • Centralizes common browser actions.

  • Simplifies framework maintenance.

  • Encourages code reusability.

  • Makes automation scripts cleaner and more consistent.


Example

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC


# Topic: 45. Framework Components - Base Page
# Practice site: https://www.testmuai.com/selenium-playground/
# Run: pytest -s 45_examples/test_01_base_page.py
#
# BasePage holds shared actions like click, type, and wait used by all pages.


class BasePage:
    def __init__(self, driver, timeout=10):
        self.driver = driver
        self.wait = WebDriverWait(driver, timeout)

    def open_url(self, url):
        self.driver.get(url)

    def click(self, locator):
        self.wait.until(EC.element_to_be_clickable(locator)).click()

    def type(self, locator, text):
        element = self.wait.until(EC.visibility_of_element_located(locator))
        element.clear()
        element.send_keys(text)

    def get_text(self, locator):
        return self.wait.until(EC.visibility_of_element_located(locator)).text


def test_base_page():
    from selenium import webdriver
    from selenium.webdriver.common.by import By

    driver = webdriver.Chrome()

    try:
        page = BasePage(driver)
        page.open_url("https://www.testmuai.com/selenium-playground/simple-form-demo")
        page.type((By.ID, "user-message"), "Base Page")
        page.click((By.ID, "showInput"))

        assert page.get_text((By.ID, "message")) == "Base Page"
    finally:
        driver.quit()

Understanding the Code

Import Required Libraries

WebDriverWait is imported to perform explicit waits, while expected_conditions (EC) provides predefined conditions such as waiting for an element to become visible or clickable.

These libraries help synchronize Selenium with dynamic web pages.


Create the Base Page Class

class BasePage:

This creates the BasePage class.

It acts as the parent class for all page objects and stores reusable Selenium methods that every page can inherit.


Initialize the Driver and Wait

def __init__(self, driver, timeout=10):

The constructor receives the WebDriver instance and creates a WebDriverWait object.

self.driver = driver
self.wait = WebDriverWait(driver, timeout)

This wait object is reused by all methods in the Base Page.


Open a Webpage

def open_url(self, url):

This method opens the specified webpage.

self.driver.get(url)

Instead of calling driver.get() in every test, page classes can simply use open_url().


Click an Element

def click(self, locator):

This method waits until an element becomes clickable before clicking it.

self.wait.until(
    EC.element_to_be_clickable(locator)
).click()

Using element_to_be_clickable() helps prevent failures caused by elements that are not yet ready for interaction.


Enter Text

def type(self, locator, text):

This method waits until the element becomes visible.

element = self.wait.until(
    EC.visibility_of_element_located(locator)
)

It then clears any existing text.

element.clear()

Finally, it enters the new value.

element.send_keys(text)

Using a single type() method ensures consistent text entry across the framework.


Read Text from an Element

def get_text(self, locator):

This method waits for the element to become visible and returns its displayed text.

return self.wait.until(
    EC.visibility_of_element_located(locator)
).text

This removes the need to repeatedly write find_element().text in every page class.


Create a BasePage Object

page = BasePage(driver)

An object of the BasePage class is created using the current WebDriver instance.


Open the Practice Website

page.open_url(
    "https://www.testmuai.com/selenium-playground/simple-form-demo"
)

The open_url() method opens the Selenium Playground page.


Enter a Message

page.type(
    (By.ID, "user-message"),
    "Base Page"
)

The type() method locates the input field and enters the text “Base Page”.


Click the Button

page.click(
    (By.ID, "showInput")
)

The click() method waits for the button to become clickable and clicks it.


Verify the Result

assert page.get_text(
    (By.ID, "message")
) == "Base Page"

The get_text() method retrieves the displayed message.

The assertion verifies that the correct message appears on the webpage.


Close the Browser

driver.quit()

This closes the browser and ends the WebDriver session.


Practical Example

Suppose an e-commerce application contains dozens of pages such as Login, Product, Cart, Checkout, and Profile.

Each page needs to:

  • Open URLs

  • Click buttons

  • Enter text

  • Read messages

Instead of writing these actions in every page class, they are placed inside the Base Page, allowing every page object to reuse the same methods.


Automation Testing Example

Consider a banking application with more than 200 automated test cases.

Every page performs common actions such as entering usernames, clicking buttons, waiting for elements, and reading confirmation messages.

A Base Page centralizes these common operations so that updates only need to be made once, making the framework easier to maintain.


Real-World Example

Base Pages are widely used in:

  • Enterprise Automation Frameworks

  • Banking Applications

  • Healthcare Systems

  • E-commerce Websites

  • Insurance Portals

  • CRM Applications

  • ERP Systems

  • SaaS Platforms

Almost every professional Selenium framework uses a Base Page to avoid duplicate code and improve maintainability.


Advantages of Using a Base Page

  • Eliminates duplicate Selenium code.

  • Promotes code reusability.

  • Centralizes common browser operations.

  • Simplifies framework maintenance.

  • Keeps page classes clean and readable.

  • Improves scalability for large automation projects.


Common Mistakes Beginners Make

Writing Selenium Code in Every Page

Avoid duplicating common Selenium methods in multiple page classes.

Instead, place reusable functionality inside the Base Page.


Not Using Explicit Waits

Calling click() or send_keys() directly without waiting may cause unstable tests.

Use WebDriverWait wherever appropriate.


Putting Assertions Inside the Base Page

The Base Page should only perform browser actions.

Assertions should remain inside the test classes.


Making the Base Page Too Large

Only common reusable methods should be placed in the Base Page.

Business-specific actions should remain inside individual page classes.


Best Practices

  • Store reusable Selenium actions inside the Base Page.

  • Use WebDriverWait for common interactions.

  • Keep the Base Page generic and reusable.

  • Let page classes inherit from the Base Page.

  • Keep assertions inside test classes.

  • Add only commonly used methods to the Base Page.


Conclusion

The Base Page is one of the most important building blocks of a Selenium automation framework. It centralizes common browser operations such as opening pages, clicking elements, entering text, and retrieving information. By moving reusable functionality into a single parent class, automation frameworks become cleaner, easier to maintain, and more scalable as the number of page objects and test cases grows.


Frequently Asked Questions (FAQs)

What is a Base Page?

A Base Page is a parent class that stores reusable Selenium methods shared by multiple page objects.


Why is a Base Page used?

It reduces duplicate code, improves maintainability, and promotes code reuse throughout the automation framework.


What methods are commonly placed in a Base Page?

Common methods include opening URLs, clicking elements, entering text, reading text, waiting for elements, scrolling, and handling alerts.


Does every page inherit from the Base Page?

Yes. In most Page Object Model (POM) frameworks, page classes inherit common functionality from the Base Page.


Can assertions be written inside the Base Page?

No. The Base Page should only contain reusable browser actions. Assertions should remain inside the test classes.


Key Takeaways

  • A Base Page centralizes common Selenium operations.

  • It reduces duplicate code across page classes.

  • WebDriverWait improves test stability.

  • Page objects inherit reusable methods from the Base Page.

  • Assertions should remain in test classes, not in the Base Page.

  • A well-designed Base Page makes automation frameworks easier to maintain and scale.