Hybrid Framework Design
A Hybrid Framework combines the best elements of multiple framework types — POM for maintainability, Data-Driven for test coverage, Keyword-Driven for readability, and BDD for business alignment. The professional SDET's most important skill is knowing HOW to combine these patterns into a cohesive, scalable architecture that serves both technical and non-technical stakeholders.
Hybrid Framework Architecture
# ══════════════════════════════════════════════════════════════
# PROFESSIONAL HYBRID FRAMEWORK STRUCTURE
# ══════════════════════════════════════════════════════════════
# framework/
# ├── config/
# │ ├── config.py ← Environment configs (base URLs, timeouts)
# │ └── test_config.json ← Test-level settings
# │
# ├── pages/ ← PAGE OBJECT MODEL layer
# │ ├── base_page.py ← Shared WebDriver utilities
# │ ├── login_page.py
# │ ├── dashboard_page.py
# │ └── checkout_page.py
# │
# ├── test_data/ ← DATA-DRIVEN layer
# │ ├── login_data.csv
# │ ├── products.json
# │ └── checkout_scenarios.xlsx
# │
# ├── features/ ← BDD layer (Gherkin)
# │ ├── login.feature
# │ └── checkout.feature
# │
# ├── step_definitions/ ← BDD step implementations
# │ ├── auth_steps.py
# │ └── common_steps.py
# │
# ├── tests/ ← Direct pytest tests (non-BDD)
# │ ├── test_api.py ← API tests
# │ └── test_regression.py ← Full regression suite
# │
# ├── utilities/
# │ ├── api_client.py ← HTTP request helper
# │ ├── db_helper.py ← Database setup/teardown
# │ └── excel_reader.py ← Excel test data reader
# │
# ├── reports/ ← Generated test reports
# ├── screenshots/ ← Failure screenshots
# ├── conftest.py ← pytest fixtures (driver, base_url)
# └── pytest.ini ← Run configuration
# ── config/config.py ─────────────────────────────────────────
import os
class Config:
BASE_URL = os.getenv("BASE_URL", "https://staging.myapp.com")
TIMEOUT = int(os.getenv("TIMEOUT", "15"))
HEADLESS = os.getenv("HEADLESS", "true").lower() == "true"
BROWSER = os.getenv("BROWSER", "chrome")
class TestData:
VALID_USER = {"email": "alice@test.com", "password": "Test@1234"}
ADMIN_USER = {"email": "admin@test.com", "password": "Admin@1234"}
LOCKED_USER = {"email": "locked@test.com", "password": "Test@1234"}
# ── utilities/api_client.py ───────────────────────────────────
import requests
class ApiClient:
def __init__(self, base_url):
self.base_url = base_url
self.session = requests.Session()
def login(self, email, password):
"""API login — sets session cookie, no UI needed"""
response = self.session.post(
f"{self.base_url}/api/auth/login",
json={"email": email, "password": password}
)
response.raise_for_status()
return response.json()["token"]
def create_test_user(self, user_data):
"""Create test data via API before UI tests"""
return self.session.post(f"{self.base_url}/api/test/users", json=user_data)
# ── conftest.py (hybrid approach) ────────────────────────────
import pytest
from selenium import webdriver
from config.config import Config
from utilities.api_client import ApiClient
@pytest.fixture(scope="session")
def api_client():
"""Session-scoped API client for test data setup"""
return ApiClient(Config.BASE_URL)
@pytest.fixture(scope="function")
def authenticated_driver(api_client):
"""Driver with pre-authenticated session (skip UI login)"""
options = webdriver.ChromeOptions()
if Config.HEADLESS:
options.add_argument("--headless")
driver = webdriver.Chrome(options=options)
# Login via API and set cookie in browser
token = api_client.login("alice@test.com", "Test@1234")
driver.get(Config.BASE_URL)
driver.add_cookie({"name": "auth_token", "value": token})
yield driver
driver.quit()Common Mistakes
- Over-engineering from day 1 — start with POM + pytest; add BDD when business users need to read specs; add data-driven when test counts grow
- Framework becomes a product in itself — framework must serve the tests, not the other way around; don't spend more time on framework than on tests
- Not using API for test setup — UI-based test data setup (navigating forms to create preconditions) is 10x slower than API calls; use the API
- Missing environment configuration — base URLs, credentials, and timeouts hardcoded in code prevent running on staging vs production without code changes
Tip
Tip
Practice Hybrid Framework Design in small, isolated examples before integrating into larger projects. Breaking concepts into small experiments builds genuine understanding faster than reading alone.
Testing pyramid: many unit tests, fewer integration, fewest E2E
Practice Task
Note
Practice Task — (1) Write a working example of Hybrid Framework Design from scratch without looking at notes. (2) Modify it to handle an edge case (empty input, null value, or error state). (3) Share your solution in the Priygop community for feedback.
Quick Quiz
Common Mistake
Warning
A common mistake with Hybrid Framework Design is skipping edge case testing — empty inputs, null values, and unexpected data types. Always validate boundary conditions to write robust, production-ready software testing code.
Key Takeaways
- A Hybrid Framework combines the best elements of multiple framework types — POM for maintainability, Data-Driven for test coverage, Keyword-Driven for readability, and BDD for business alignment.
- Over-engineering from day 1 — start with POM + pytest; add BDD when business users need to read specs; add data-driven when test counts grow
- Framework becomes a product in itself — framework must serve the tests, not the other way around; don't spend more time on framework than on tests
- Not using API for test setup — UI-based test data setup (navigating forms to create preconditions) is 10x slower than API calls; use the API