Advanced Chapter 15 · 14 min read

Base Test Class & Framework Design

Build a production-ready test framework with base classes, driver factory, configuration management, and utility helpers.

Production-Ready Test Framework

A well-designed framework is the difference between tests that scale and tests that break. Build a solid foundation with a base test class, driver factory, centralized config, and reusable utilities.

DriverFactory.java
package com.selenium.course.base;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.edge.EdgeDriver;
import java.time.Duration;

public class DriverFactory {

    private static ThreadLocal<WebDriver> driver = new ThreadLocal<>();

    public static WebDriver getDriver() {
        return driver.get();
    }

    public static void initDriver(String browser, boolean headless) {
        WebDriver webDriver;

        switch (browser.toLowerCase()) {
            case "firefox":
                FirefoxOptions ffOptions = new FirefoxOptions();
                if (headless) ffOptions.addArguments("--headless");
                webDriver = new FirefoxDriver(ffOptions);
                break;
            case "edge":
                webDriver = new EdgeDriver();
                break;
            default:
                ChromeOptions chromeOptions = new ChromeOptions();
                if (headless) chromeOptions.addArguments("--headless=new");
                chromeOptions.addArguments("--no-sandbox");
                chromeOptions.addArguments("--window-size=1920,1080");
                webDriver = new ChromeDriver(chromeOptions);
        }

        webDriver.manage().timeouts()
            .implicitlyWait(Duration.ofSeconds(10));
        webDriver.manage().timeouts()
            .pageLoadTimeout(Duration.ofSeconds(30));
        webDriver.manage().window().maximize();

        driver.set(webDriver);
    }

    public static void quitDriver() {
        if (driver.get() != null) {
            driver.get().quit();
            driver.remove();
        }
    }
}
BaseTest.java
package com.selenium.course.base;

import org.openqa.selenium.WebDriver;
import org.testng.annotations.*;
import java.io.FileInputStream;
import java.util.Properties;

public class BaseTest {

    protected WebDriver driver;
    protected static Properties config;

    @BeforeSuite
    public void loadConfig() throws Exception {
        config = new Properties();
        String env = System.getProperty("env", "test");
        config.load(new FileInputStream(
            "src/test/resources/config-" + env + ".properties"));
    }

    @BeforeMethod
    @Parameters({"browser"})
    public void setup(@Optional("chrome") String browser) {
        boolean headless = Boolean.parseBoolean(
            System.getProperty("headless", "false"));

        DriverFactory.initDriver(browser, headless);
        driver = DriverFactory.getDriver();

        String baseUrl = config.getProperty("base.url");
        if (baseUrl != null) {
            driver.get(baseUrl);
        }
    }

    @AfterMethod
    public void teardown() {
        DriverFactory.quitDriver();
    }
}

// Run: mvn test -Dbrowser=chrome -Dheadless=true -Denv=staging
base/driver_factory.py
"""Driver factory with browser selection and options"""
from selenium import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions

def create_driver(browser='chrome', headless=False):
    if browser == 'firefox':
        options = FirefoxOptions()
        if headless:
            options.add_argument('--headless')
        return webdriver.Firefox(options=options)

    elif browser == 'edge':
        return webdriver.Edge()

    else:  # Chrome (default)
        options = ChromeOptions()
        if headless:
            options.add_argument('--headless=new')
        options.add_argument('--no-sandbox')
        options.add_argument('--window-size=1920,1080')
        return webdriver.Chrome(options=options)
conftest.py
"""Centralized fixtures for entire framework"""
import pytest, os
from base.driver_factory import create_driver

def pytest_addoption(parser):
    parser.addoption('--browser', default='chrome',
                     help='Browser: chrome, firefox, edge')
    parser.addoption('--headless', action='store_true',
                     help='Run in headless mode')
    parser.addoption('--env', default='test',
                     help='Environment: test, staging, prod')

@pytest.fixture(scope='function')
def driver(request):
    browser = request.config.getoption('--browser')
    headless = request.config.getoption('--headless')

    d = create_driver(browser, headless)
    d.implicitly_wait(10)
    d.set_page_load_timeout(30)
    d.maximize_window()

    yield d
    d.quit()

@pytest.fixture(scope='session')
def config(request):
    env = request.config.getoption('--env')
    configs = {
        'test': {'base_url': 'https://www.selenium.dev/'},
        'staging': {'base_url': 'https://staging.example.com/'},
    }
    return configs.get(env, configs['test'])

# Run: pytest --browser=chrome --headless --env=staging

Selenium Advanced Base Test Class & Framework Design

Written by PV

© 2026 All Rights Reserved