Skip to main content

Selenium Python WebDriver Test Automation Framework - Reporting, DataDriven , Hybrid , POM Framework

 In today’s agile software development world, test automation has become a vital component of delivering quality software at speed. One of the most popular tools for web application testing is Selenium WebDriver. Combined with Python, Selenium offers a powerful and flexible test automation solution. In this blog post, we will walk through the creation of a robust, scalable, and maintainable Selenium Python WebDriver Test Automation Framework, using the best practices like the Page Object Model (POM), Data-Driven Testing, Hybrid Framework Design, and HTML Reporting.


🧰 Why Selenium with Python?

Before diving into the framework, let’s quickly touch on why Selenium with Python is a solid choice:

  • Simplicity & Readability: Python syntax is clean and readable, reducing the learning curve.

  • Vast Ecosystem: Python’s libraries (like unittest, pytest, openpyxl, pandas, HTMLTestRunner) make the automation process smoother.

  • Strong Community Support: Python and Selenium both have vast communities and documentation.

  • Cross-Browser Support: Selenium supports Chrome, Firefox, Edge, Safari, and more.


🏗️ Framework Design Overview

We are going to build a Hybrid Framework that combines multiple test automation approaches:

  • Modular – Reusable modules for common functionality.

  • Data-Driven – External data source integration (Excel or CSV).

  • Page Object Model (POM) – Decouples test logic from UI structure.

  • HTML Reporting – Generates user-friendly test execution reports.

🧱 Framework Structure

bash
selenium_python_framework/ │ ├── tests/ # Test case scripts │ └── test_login.py │ ├── pages/ # Page Object Models │ └── login_page.py │ ├── data/ # Test data (Excel/CSV) │ └── login_data.xlsx │ ├── utils/ # Utility functions │ ├── data_reader.py │ └── custom_logger.py │ ├── reports/ # HTML Reports │ ├── drivers/ # WebDriver executables (optional) │ ├── config/ # Configuration files │ └── config.ini │ ├── main.py # Entry point to run tests ├── requirements.txt └── README.md

📄 1. Page Object Model (POM)

Page Object Model helps in maintaining a clean separation between test scripts and the underlying page structure.

Example: login_page.py

python
from selenium.webdriver.common.by import By class LoginPage: def __init__(self, driver): self.driver = driver self.username_input = (By.ID, "username") self.password_input = (By.ID, "password") self.login_button = (By.ID, "loginBtn") def enter_username(self, username): self.driver.find_element(*self.username_input).send_keys(username) def enter_password(self, password): self.driver.find_element(*self.password_input).send_keys(password) def click_login(self): self.driver.find_element(*self.login_button).click()

This class will be used in the test script to interact with the login page, reducing duplication and increasing maintainability.


📊 2. Data-Driven Testing

To test multiple scenarios efficiently, we use Excel files or CSVs for feeding test data. Let’s create a utility to read from Excel.

data_reader.py

python
import openpyxl def read_login_data(file_path): workbook = openpyxl.load_workbook(file_path) sheet = workbook.active data = [] for row in sheet.iter_rows(min_row=2, values_only=True): data.append({"username": row[0], "password": row[1], "expected": row[2]}) return data

Your Excel file login_data.xlsx might look like:

usernamepasswordexpected
user1pass1success
user2wrongfailure

🧪 3. Test Case using Unittest

test_login.py

python
import unittest from selenium import webdriver from pages.login_page import LoginPage from utils.data_reader import read_login_data import time class TestLogin(unittest.TestCase): @classmethod def setUpClass(cls): cls.driver = webdriver.Chrome() cls.driver.get("https://example.com/login") cls.driver.maximize_window() def test_login_scenarios(self): test_data = read_login_data("data/login_data.xlsx") for data in test_data: with self.subTest(data=data): page = LoginPage(self.driver) page.enter_username(data["username"]) page.enter_password(data["password"]) page.click_login() time.sleep(2) # Replace with better waits # Dummy check if data["expected"] == "success": self.assertIn("Dashboard", self.driver.title) else: self.assertIn("Login", self.driver.title) @classmethod def tearDownClass(cls): cls.driver.quit() if __name__ == "__main__": unittest.main()

📋 4. HTML Reporting

For generating HTML reports, we can use HtmlTestRunner.

Installation:

bash
pip install html-testRunner

Modify test_login.py

python
import HtmlTestRunner # Add this under unittest.main() if __name__ == "__main__": unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner( output='reports', report_name="LoginTestReport", combine_reports=True ))

This will generate a detailed report under the reports/ directory.


⚙️ 5. Configuration Management

config/config.ini

ini
[DEFAULT] base_url = https://example.com/login browser = chrome

config_reader.py

python
import configparser def get_config(section, key): config = configparser.ConfigParser() config.read('config/config.ini') return config[section][key]

Use it in your test:

python
from utils.config_reader import get_config url = get_config("DEFAULT", "base_url")

🔀 6. Hybrid Framework Integration

Now that we have:

  • Modularized pages using POM

  • Data-driven tests via Excel

  • HTML reports

  • Config file management

We’ve effectively built a hybrid framework, blending the best features from different test automation strategies.


🔒 7. Logging and Debugging

Use Python’s built-in logging for better traceability.

custom_logger.py

python
import logging def get_logger(): logger = logging.getLogger("automation_logger") logger.setLevel(logging.DEBUG) fh = logging.FileHandler("reports/test_log.log") formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) logger.addHandler(fh) return logger

Use in your test:

python
from utils.custom_logger import get_logger logger = get_logger() logger.info("Starting login test")

🧪 8. Running Tests

Using CLI

bash
python tests/test_login.py

Using main.py to run all tests

python
import unittest import HtmlTestRunner if __name__ == "__main__": loader = unittest.TestLoader() suite = loader.discover('tests') runner = HtmlTestRunner.HTMLTestRunner( output='reports', report_name="FullTestSuite", combine_reports=True ) runner.run(suite)

Run:

bash
python main.py

📦 9. Requirements.txt

Create a requirements.txt:

css
selenium openpyxl html-testRunner

Install all:

bash
pip install -r requirements.txt

🛠️ 10. Maintenance and Scalability Tips

  • Keep test data separate from test logic.

  • Use meaningful test case names and subtests.

  • Clean up driver instances properly to avoid memory leaks.

  • Use WebDriverWait instead of time.sleep() for better reliability.

  • Group related page actions in the same POM class.


📌 Conclusion

We’ve built a full-featured Selenium WebDriver Test Automation Framework using Python that includes:

  • POM Architecture for clean structure

  • Data-Driven Testing using Excel

  • HTML Reporting with HtmlTestRunner

  • Logging for traceability

  • Hybrid Design Pattern for flexibility and power

This type of framework is not just suitable for small projects, but also scalable for enterprise-level testing with minor upgrades like integrating with Jenkins, CI/CD tools, Docker, and cloud grids (like Selenium Grid or BrowserStack).

With this foundation, you can confidently expand your test automation coverage while keeping the codebase clean and maintainable.

Comments