</>

Technology

Page Object Model

Difficulty

Intermediate

Interview Question

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

Answer

Hybrid Framework Architecture

Folder Structure

CODE
selenium-hybrid-framework/
├── src/
│   ├── main/java/com/automateqa/
│   │   ├── config/
│   │   │   └── ConfigReader.java       ← reads config.properties
│   │   ├── driver/
│   │   │   └── DriverManager.java      ← WebDriver init/quit
│   │   ├── pages/
│   │   │   ├── BasePage.java           ← common utilities
│   │   │   ├── LoginPage.java
│   │   │   └── DashboardPage.java
│   │   └── utils/
│   │       ├── ExcelUtil.java          ← read test data from Excel
│   │       ├── WaitUtil.java           ← explicit waits
│   │       └── ScreenshotUtil.java     ← capture screenshots
│   └── test/java/com/automateqa/
│       ├── base/
│       │   └── BaseTest.java           ← @BeforeMethod / @AfterMethod
│       ├── tests/
│       │   ├── LoginTest.java
│       │   └── CheckoutTest.java
│       └── listeners/
│           └── TestListener.java       ← TestNG listener for reports
├── src/test/resources/
│   ├── testdata/
│   │   └── LoginData.xlsx
│   ├── config/
│   │   ├── config.properties           ← browser, baseUrl, timeout
│   │   └── staging.properties
│   └── testng.xml
└── pom.xml

Layer 1 — Configuration

Java
// config/ConfigReader.java
public class ConfigReader {
    private static Properties props = new Properties();

    static {
        try {
            String env  = System.getProperty("env", "config");
            FileInputStream fis = new FileInputStream(
                "src/test/resources/config/" + env + ".properties");
            props.load(fis);
        } catch (IOException e) {
            throw new RuntimeException("config.properties not found", e);
        }
    }

    public static String get(String key) {
        return System.getProperty(key, props.getProperty(key));
    }
}
PROPERTIES
# config/config.properties
browser=chrome
baseUrl=https://staging.automateqa.online
implicitWait=10
explicitWait=15
headless=false

Layer 2 — Driver Management

Java
// driver/DriverManager.java
public class DriverManager {
    private static ThreadLocal<WebDriver> driver = new ThreadLocal<>();

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

    public static void init() {
        String browser  = ConfigReader.get("browser");
        boolean headless = Boolean.parseBoolean(ConfigReader.get("headless"));

        WebDriver d;
        switch (browser.toLowerCase()) {
            case "firefox":
                FirefoxOptions ffOpts = new FirefoxOptions();
                if (headless) ffOpts.addArguments("--headless");
                d = new FirefoxDriver(ffOpts);
                break;
            case "edge":
                d = new EdgeDriver();
                break;
            default:  // chrome
                ChromeOptions opts = new ChromeOptions();
                if (headless) opts.addArguments("--headless=new", "--no-sandbox",
                                                "--disable-dev-shm-usage");
                d = new ChromeDriver(opts);
        }
        d.manage().window().maximize();
        d.manage().timeouts().implicitlyWait(
            Duration.ofSeconds(Long.parseLong(ConfigReader.get("implicitWait"))));
        driver.set(d);
    }

    public static void quit() {
        if (driver.get() != null) {
            driver.get().quit();
            driver.remove();
        }
    }
}

Layer 3 — BaseTest

Java
// base/BaseTest.java
public class BaseTest {

    @BeforeMethod(alwaysRun = true)
    public void setUp(Method method) {
        DriverManager.init();
        DriverManager.getDriver().get(ConfigReader.get("baseUrl"));
        LogUtil.info("=== Starting: " + method.getName() + " ===");
    }

    @AfterMethod(alwaysRun = true)
    public void tearDown(ITestResult result) {
        if (result.getStatus() == ITestResult.FAILURE) {
            ScreenshotUtil.capture(result.getName());
            LogUtil.error("TEST FAILED: " + result.getName());
        }
        DriverManager.quit();
    }
}

Layer 4 — Test with Data Provider

Java
// tests/LoginTest.java
public class LoginTest extends BaseTest {

    @DataProvider(name = "loginData", parallel = false)
    public Object[][] loginData() throws Exception {
        return ExcelUtil.readData("src/test/resources/testdata/LoginData.xlsx", "Sheet1");
        // Returns: [["valid","alice@t.com","Pass@123","Dashboard"],
        //           ["invalid","wrong@t.com","bad","Invalid credentials"]]
    }

    @Test(dataProvider = "loginData", groups = {"smoke", "regression"})
    public void testLogin(String scenario, String email, String pass, String expected) {
        LogUtil.info("Running: " + scenario);
        LoginPage loginPage = new LoginPage(DriverManager.getDriver());
        loginPage.login(email, pass);

        if (scenario.equals("valid")) {
            DashboardPage dash = new DashboardPage(DriverManager.getDriver());
            Assert.assertTrue(dash.isWelcomeDisplayed(), "Dashboard not shown");
        } else {
            Assert.assertEquals(loginPage.getError(), expected);
        }
    }
}

Layer 5 — Extent Report Listener

Java
// listeners/TestListener.java
public class TestListener implements ITestListener {
    private static ExtentReports extent = ExtentManager.getInstance();
    private static ThreadLocal<ExtentTest> test = new ThreadLocal<>();

    @Override
    public void onTestStart(ITestResult result) {
        ExtentTest extentTest = extent.createTest(result.getMethod().getMethodName());
        test.set(extentTest);
    }

    @Override
    public void onTestSuccess(ITestResult result) {
        test.get().pass("Test passed");
    }

    @Override
    public void onTestFailure(ITestResult result) {
        test.get().fail(result.getThrowable());
        String screenshotPath = ScreenshotUtil.capture(result.getName());
        test.get().addScreenCaptureFromPath(screenshotPath);
    }

    @Override
    public void onFinish(ITestContext context) {
        extent.flush();
    }
}

Follow AutomateQA

Related Topics