</>

Technology

Scenario-Based

Difficulty

Advanced

Interview Question

How do you design a Selenium test automation framework from scratch?

Answer

Designing a Selenium Framework from Scratch

As a Senior Automation Architect, this is the blueprint for an enterprise-grade framework:

Phase 1 — Technology Selection

CODE
Language:        Java (most common for Selenium)
Test Framework:  TestNG (parallel, groups, listeners)
Build Tool:      Maven (dependency management, CI integration)
Browser Driver:  WebDriverManager (auto-manages driver versions)
Reporting:       ExtentReports + Allure
Logging:         Log4j2
Data:            Apache POI (Excel) + Properties files
Version Control: Git + GitHub
CI/CD:           Jenkins / GitHub Actions

Phase 2 — Project Structure

CODE
project-root/
├── src/
│   ├── main/java/
│   │   ├── base/
│   │   │   ├── BaseTest.java        ← driver init, config load, teardown
│   │   │   └── BasePage.java        ← common wait methods, WebDriver ref
│   │   ├── pages/
│   │   │   ├── LoginPage.java       ← page objects
│   │   │   └── DashboardPage.java
│   │   ├── utils/
│   │   │   ├── DriverManager.java   ← ThreadLocal WebDriver
│   │   │   ├── ExcelUtils.java      ← test data reading
│   │   │   ├── ScreenshotUtils.java ← screenshot on failure
│   │   │   └── WaitUtils.java       ← reusable explicit waits
│   │   ├── listeners/
│   │   │   ├── ExtentReportListener.java
│   │   │   └── RetryListener.java
│   │   └── constants/
│   │       └── FrameworkConstants.java ← paths, timeouts, URLs
│   └── test/
│       ├── java/tests/
│       │   ├── LoginTest.java
│       │   └── CheckoutTest.java
│       └── resources/
│           ├── config.properties        ← env-specific settings
│           ├── log4j2.xml              ← logging config
│           └── testdata/
│               └── TestData.xlsx
├── testng.xml                           ← suite definition
├── testng-regression.xml
├── testng-smoke.xml
├── pom.xml
└── .github/workflows/ci.yml            ← GitHub Actions

Phase 3 — Core Components

FrameworkConstants.java
Java
public class FrameworkConstants {
    public static final int EXPLICIT_WAIT = 15;
    public static final int PAGE_LOAD_TIMEOUT = 30;
    public static final String SCREENSHOT_PATH = "test-output/screenshots/";
    public static final String EXTENT_REPORT_PATH = "test-output/ExtentReport.html";
    public static final String EXCEL_DATA_PATH = "src/test/resources/testdata/TestData.xlsx";
}
BasePage.java
Java
public class BasePage {
    protected WebDriver driver;
    protected WebDriverWait wait;

    public BasePage() {
        this.driver = DriverManager.getDriver();
        this.wait = new WebDriverWait(driver, Duration.ofSeconds(EXPLICIT_WAIT));
    }

    protected WebElement waitForElement(By locator) {
        return wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
    }

    protected void clickElement(By locator) {
        waitForElement(locator).click();
    }

    protected void typeText(By locator, String text) {
        WebElement el = waitForElement(locator);
        el.clear();
        el.sendKeys(text);
    }
}

Phase 4 — CI/CD Integration

GitHub Actions workflow:

YAML
name: Selenium Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with: { java-version: '17', distribution: 'temurin' }
      - name: Run Smoke Tests
        run: mvn test -Dgroups="smoke" -Dheadless=true
      - name: Upload Reports
        uses: actions/upload-artifact@v4
        with:
          name: test-reports
          path: test-output/

Phase 5 — Execution Commands

Bash
# Run smoke tests headless
mvn test -Dgroups="smoke" -Dheadless=true

# Cross-browser regression
mvn test -DsuiteXmlFile=testng-regression.xml

# Rerun failures
mvn test -DsuiteXmlFile=test-output/testng-failed.xml

Framework Design Principles (Senior Level)

  1. No hardcoded values — everything in config.properties or Constants
  2. ThreadLocal driver — mandatory for parallel execution
  3. Page Object Model — never write locators directly in test classes
  4. Single Responsibility — each class/page does one thing
  5. Explicit over implicit waits — predictable, debuggable
  6. Self-documenting tests — test method names read like user stories
  7. CI/CD first — framework must run headless in Docker from day 1

Follow AutomateQA

Related Topics