Our Latest Articles

Selenium Page Object Model Framework Using Python

Selenium Page Object Model Framework Using Python | Real-World Automation Simulation #002

August 27, 202613 min read

Real-World Software Automation Simulation #002

Don’t Just Learn Automation. Simulate the Job.

Introduction

In Day 1 of the FutureTech Real-World Software Automation Simulation Series, we automated a Login page using Selenium WebDriver, Python, and pytest.

We created automated tests for:

Valid Login

Invalid Username

Invalid Password

Empty Username

Empty Password

Both Fields Empty

Password Masking

Forgot Password

The Day 1 project introduced the basic Selenium automation workflow.

However, as an automation project grows, simply writing Selenium commands inside every test case becomes difficult to maintain.

Imagine a project with 100 automated test cases.

If every test contains its own locators, browser actions, element interactions, waits, and page-specific logic, even a small UI change can require modifications across multiple test files.

This is where the Page Object Model becomes useful.

What Is Page Object Model?

Page Object Model, commonly called POM, is a design pattern used in test automation to separate test logic from page interaction logic.

The basic idea is:

Test Case

Page Object

Selenium WebDriver

Web Application

The test describes what needs to be tested.

The Page Object describes how to interact with the page.

For example, instead of writing Selenium commands directly inside a test, we can create reusable methods such as:

enter_username()

enter_password()

click_login()

login()

The test then becomes easier to understand and maintain.

Why Do We Need Page Object Model?

Consider a Login page.

Suppose we have 20 tests that need to interact with the Login button.

Without POM, the Login button locator could be repeated across many tests.

Now suppose the development team changes the Login button locator.

You may have to update multiple test files.

With Page Object Model, the locator is centralized inside the LoginPage class.

The tests simply call:

click_login()

This reduces duplication and makes maintenance easier.

Real-World QA Scenario

Imagine you are working as a QA Automation Engineer for an e-commerce application.

The application contains:

Login

Registration

Home

Product Search

Product Details

Shopping Cart

Checkout

Orders

Profile

Each page can have its own Page Object.

For example:

LoginPage

HomePage

ProductPage

CartPage

CheckoutPage

OrderPage

ProfilePage

This allows the automation framework to represent the application's user interface in a structured way.

Day 1 vs Day 2

In Day 1, we focused on creating basic Selenium automation.

The basic flow was:

Open Browser

Open Login Page

Locate Element

Enter Data

Click Button

Verify Result

In Day 2, we improve the architecture.

The new flow becomes:

Test Case

LoginPage

Reusable Page Method

Locator

Selenium WebDriver

Browser

This separation is the foundation of a maintainable automation framework.

Project Objective

In this simulation, we will create a Selenium Page Object Model framework using:

Python

Selenium WebDriver

pytest

WebDriverWait

Page Objects

Test Data

pytest Fixtures

Assertions

Failure Screenshots

By the end of the project, you will understand how to convert a basic Selenium test into a structured automation framework.

Technology Stack

Python

Python is used as the programming language for the automation framework.

Selenium WebDriver

Selenium is used to control the browser and interact with web elements.

pytest

pytest is used as the test framework for organizing and executing automated tests.

HTML, CSS and JavaScript

A local demo Login application is included in the project.

GitHub

GitHub is used to store and share the complete automation project.

Project Structure

The Day 2 project can be organized as:

futuretech-selenium-login-automation-day2

pages

login_page.py

tests

test_login.py

test_data

login_data.py

utils

screenshot.py

demo_app

login.html

requirements.txt

pytest.ini

README.md

Understanding Each Folder

pages

The pages folder contains Page Object classes.

For example:

login_page.py

This file represents the Login page.

tests

The tests folder contains the actual test scenarios.

For example:

test_login.py

test_data

This folder contains reusable test data such as:

Valid username

Valid password

Invalid username

Invalid password

utils

The utils folder contains reusable helper functions such as screenshot capture.

demo_app

The demo application is included so students can run the automation locally.

Step 1 — Create the Login Page Object

Create:

pages/login_page.py

Inside this file, create:

LoginPage

The LoginPage class represents the Login screen of the application.

Step 2 — Define Page Locators

The Login page contains:

Username

Password

Login button

Error message

Success message

Forgot Password

Instead of defining these locators inside every test, we store them in the Page Object.

For example:

USERNAME

PASSWORD

LOGIN_BUTTON

ERROR_MESSAGE

LOGIN_MESSAGE

FORGOT_PASSWORD

This creates a central location for Login page elements.

Step 3 — Create the Constructor

The LoginPage class receives the Selenium WebDriver instance.

The driver allows the Page Object to communicate with the browser.

The concept is:

LoginPage(driver)

The Page Object can now use the driver to:

Find elements

Click elements

Enter data

Read text

Wait for elements

Step 4 — Create enter_username()

Create a reusable method:

enter_username()

Its responsibility is:

Locate the Username field

Clear existing value

Enter the supplied username

The test does not need to know how the Username field is located.

Step 5 — Create enter_password()

Create:

enter_password()

This method:

Locates the Password field

Clears the existing value

Enters the password

The technical implementation remains inside LoginPage.

Step 6 — Create click_login()

Create:

click_login()

This method locates the Login button and clicks it.

Step 7 — Create login()

Now we can combine the common Login actions.

The method performs:

Enter username

Enter password

Click Login

The test can now simply use:

login_page.login(username, password)

This is a major advantage of Page Object Model.

Step 8 — Create Result Methods

The Login page needs to provide information that the tests can verify.

Create methods such as:

get_error_message()

get_login_message()

The test can then perform the assertion.

For example:

Expected result:

Login successful.

The test verifies that the actual message matches the expected message.

Step 9 — Use Explicit Waits

Web applications may not always respond instantly.

Instead of relying on fixed delays, use explicit waits.

For example:

Wait until the Username field is visible.

Wait until the Login button is clickable.

Wait until the result message becomes visible.

The project uses:

WebDriverWait

and:

Expected Conditions

This makes synchronization more reliable than using arbitrary fixed delays.

Why Avoid time.sleep()?

A beginner may write:

time.sleep(5)

This forces the test to wait five seconds even if the element becomes ready after one second.

It also does not guarantee that an element will be ready after five seconds if the application is slower.

Explicit waits are condition-based.

For example:

Wait until element is visible.

Wait until element is clickable.

This makes the automation more purposeful and maintainable.

Step 10 — Create Test Data

Create:

test_data/login_data.py

Store reusable values such as:

VALID_USERNAME

VALID_PASSWORD

INVALID_USERNAME

INVALID_PASSWORD

EMPTY_USERNAME

EMPTY_PASSWORD

This keeps test data separate from test logic.

Why Separate Test Data?

If credentials are hard-coded into dozens of test files, changing the credentials becomes difficult.

Centralizing test data makes maintenance easier.

Later, this approach can be extended to:

CSV

Excel

JSON

Database

Environment Variables

Configuration Files

Step 11 — Create pytest Fixture

Browser setup should not be repeated in every test.

Create a pytest fixture responsible for:

Starting Chrome

Maximizing the browser

Providing the driver

Closing the browser

This allows multiple tests to reuse the browser setup logic.

Step 12 — Create the Test File

Create:

tests/test_login.py

The test file should focus on scenarios.

For example:

test_valid_login

test_invalid_username

test_invalid_password

test_empty_username

test_empty_password

The test should describe the behavior being validated.

Test Example — Valid Login

Scenario:

Verify that a valid user can log in.

Test Data:

Username:

testuser

Password:

Password@123

Expected Result:

Login successful.

Test Flow:

Open Login page

Enter username

Enter password

Click Login

Verify success message

The Page Object handles the browser interaction.

The test handles the expected result.

Test Example — Invalid Password

Scenario:

Verify that Login fails when an incorrect password is entered.

Test Data:

Username:

testuser

Password:

WrongPassword

Expected Result:

Invalid username or password.

The test calls the Page Object methods and verifies the expected result.

Test Example — Empty Username

Scenario:

Verify validation when Username is empty.

Test Data:

Username:

Empty

Password:

Password@123

Expected Result:

Username is required.

Test Example — Empty Password

Scenario:

Verify validation when Password is empty.

Expected Result:

Password is required.

Test Example — Both Fields Empty

Scenario:

Verify validation when both fields are empty.

Expected Result:

Username and password are required.

Test Example — Password Masking

Scenario:

Verify that the password input is configured as a password field.

Expected Result:

Password characters should be masked.

Test Example — Forgot Password

Scenario:

Verify that the Forgot Password interaction works.

Expected Result:

Password recovery message should be displayed.

Page Object Model Architecture

The framework can now be visualized as:

test_login.py

LoginPage

Selenium WebDriver

Chrome Browser

Login Application

This provides separation between the test layer and page interaction layer.

What Belongs in a Page Object?

A Page Object should generally contain:

Page locators

Page-specific actions

Element interaction methods

Page information retrieval

Synchronization related to page interactions

Examples:

enter_username()

enter_password()

click_login()

get_error_message()

get_login_message()

What Belongs in the Test?

The test should contain:

Test scenario

Test data

Expected result

Assertions

For example:

Valid Login

Invalid Login

Required field validation

Password masking

This separation keeps tests readable.

Why Is This Better?

Compare a test containing many technical Selenium commands with a test that simply calls:

login_page.login(username, password)

assert login_page.get_login_message() == expected_message

The second version communicates the business intent much more clearly.

Maintainability Example

Suppose the Username locator changes.

Old locator:

username

New locator:

user-name

Without POM, multiple test files may contain the old locator.

With POM, you update the locator in:

login_page.py

The tests can continue using:

enter_username()

This reduces maintenance effort.

Reusability Example

Suppose 30 tests need to perform Login.

Instead of writing the Login sequence 30 times, create:

login()

Then reuse it.

This reduces duplicated code and provides a single place for common Login behavior.

Scalability

Today the project contains one Page Object:

LoginPage

As the application grows, we can create:

LoginPage

HomePage

ProductPage

CartPage

CheckoutPage

OrderPage

This allows the automation framework to grow with the application.

E-Commerce Example

Imagine an e-commerce test:

User logs in

Searches for a product

Opens product

Adds product to cart

Opens cart

Checks out

Places order

A Page Object architecture could represent this as:

login_page.login()

home_page.search_product()

product_page.add_to_cart()

cart_page.open()

checkout_page.complete_checkout()

order_page.verify_order()

The test reads almost like the actual user journey.

Locator Strategy

A reliable automation framework depends heavily on good locators.

Common Selenium locator strategies include:

ID

Name

Class Name

CSS Selector

XPath

Link Text

Partial Link Text

Tag Name

Whenever possible, prefer stable and meaningful attributes.

For example:

ID

data-testid

Stable name attributes

Avoid unnecessarily complicated XPath expressions when a simpler stable locator exists.

Common Beginner Mistakes

Mistake 1 — Putting all Selenium code directly in test files

This creates duplicated code and makes maintenance harder.

Mistake 2 — Duplicating locators

The same locator should not be unnecessarily repeated across multiple tests.

Mistake 3 — Using time.sleep() everywhere

Use condition-based explicit waits where appropriate.

Mistake 4 — Hard-coding test data everywhere

Keep reusable data in a dedicated location.

Mistake 5 — Putting business assertions inside Page Objects

Assertions should generally remain in the test layer.

Mistake 6 — Creating unnecessary abstractions

Do not create a complicated framework simply for the sake of having more files.

Mistake 7 — Using unstable locators

Prefer reliable locators that are less likely to change.

Mistake 8 — Building the framework before understanding the application

Understand the application and test requirements first.

Important Principle

The goal of a framework is not to create more files.

The goal is to make automation:

Readable

Reusable

Maintainable

Scalable

Reliable

Page Object Model Is a Design Pattern

POM should not be treated simply as:

Create a pages folder.

Create a Python file.

Move locators.

Done.

The real objective is separation of responsibility.

Test layer:

What should be tested?

Page layer:

How do we interact with the page?

Test data layer:

What data should be used?

Utility layer:

What reusable support functions are needed?

This separation creates a cleaner architecture.

Practical Assignment

Take the Day 1 Selenium Login project.

Refactor it using Page Object Model.

Create:

LoginPage

Reusable Login methods

Separated test data

pytest fixture

Explicit waits

Assertions

Automate at least:

  1. Valid Login

  2. Invalid Username

  3. Invalid Password

  4. Both Credentials Invalid

  5. Empty Username

  6. Empty Password

  7. Both Fields Empty

  8. Password Masking

  9. Forgot Password

Advanced Assignment

After completing the basic framework, add:

BasePage

Reusable click method

Reusable input method

Reusable explicit wait methods

Logging

HTML reports

Environment configuration

Browser selection

Screenshot capture

Test execution options

This will prepare you for building a larger automation framework.

Project Execution

Install the dependencies:

pip install -r requirements.txt

Run the complete test suite:

pytest -v

Run only Login tests:

pytest tests/test_login.py -v

The project uses Chrome WebDriver.

Current Selenium versions can use Selenium Manager to automatically manage the appropriate browser driver in many standard local configurations.

Expected Result

The test execution should show the Login test cases being executed.

A successful run should show passing tests.

If a test fails, investigate:

Locator

Application state

Test data

Timing

Assertion

Browser environment

A failed automated test should be investigated rather than immediately assuming that it represents a product defect.

Automation Framework Evolution

The FutureTech Simulation Series follows this progression:

Day 1

Basic Selenium Login Automation

Day 2

Page Object Model

Day 3

Data-Driven Testing

Day 4

Dynamic Elements and Explicit Waits

Day 5

BDD Automation

Day 6

Playwright Automation

Day 7

API Automation

Future

CI/CD Automation

What You Should Understand After Day 2

You should now understand:

What Page Object Model is

Why POM is used

How to create a Page Object

How to store locators

How to create page methods

How to separate test data

How to use pytest fixtures

How to use explicit waits

How to create readable tests

How to reduce duplicated automation code

How to make a framework easier to maintain

Career Connection

There is a significant difference between saying:

“I learned Selenium.”

And saying:

“I built a Selenium automation framework using Python and pytest with Page Object Model, reusable page actions, explicit waits, test data separation, assertions, and failure handling.”

The second statement demonstrates practical automation experience.

Portfolio Project Description

Developed a maintainable Selenium WebDriver automation framework using Python and pytest based on the Page Object Model design pattern. Implemented reusable page methods, centralized locators, test-data separation, explicit waits, pytest fixtures, assertions, and failure screenshot handling for Login functionality.

Interview Questions

  1. What is Page Object Model?

  2. Why is POM used in Selenium automation?

  3. What are the advantages of POM?

  4. Where should page locators be stored?

  5. Should assertions be placed inside Page Objects?

  6. What is the responsibility of a Page Object?

  7. How does POM reduce code duplication?

  8. What happens when a page locator changes?

  9. Why should test data be separated?

  10. What is a pytest fixture?

  11. Why are explicit waits important?

  12. What is the difference between implicit and explicit waits?

  13. What is the difference between a test class and a Page Object class?

  14. Can Page Object Model be used for large applications?

  15. What locator strategies can Selenium use?

  16. Why should unstable locators be avoided?

Final Takeaway

Page Object Model is more than an automation folder structure.

It is a way to separate:

WHAT we test

from:

HOW we interact with the application.

A maintainable automation framework should allow testers to change page implementation without rewriting every test.

The journey is:

Manual Test Case

Selenium Automation

pytest

Page Object Model

Reusable Framework

Data-Driven Testing

Reporting

CI/CD

Don't just learn Selenium commands.

Learn how to build maintainable automation.

Learn → Simulate → Automate → Test → Improve → Share

FutureTech Simulation Academy

Don't Just Learn Technology. Simulate the Job.

selenium page object modelselenium POMselenium POM frameworkselenium page object model pythonselenium python frameworkselenium automation frameworkSelenium WebDriver Pythonselenium pytest frameworkpage object model tutorialpage object model python tutorialPOM framework seleniumSelenium automation testingSelenium testing projectSelenium login automationPython test automationpytest SeleniumQA automation frameworksoftware testing automationautomation testing projectSelenium framework for beginnersSelenium portfolio projectreal world Selenium projectQA automation projecttest automation frameworkFutureTech Simulation
Back to Blog

Empowering learners worldwide to master AI through accessible, high-quality learning.

Newsletter

Get AI career insights, learning resources, project updates, certifications, and future-ready tech guidance directly in your inbox.