Wednesday, December 10, 2025

thumbnail

Building a Modular Selenium Framework in Java

 Building a Modular Selenium Framework in Java

A modular Selenium framework makes automated testing scalable, maintainable, and reusable. Instead of writing tests in a messy, repetitive way, a modular framework organizes code into logical modules.

This guide explains:

Key design principles

Must-have components

Recommended folder structure

Using Page Object Model (POM)

Adding utilities & reusable modules

Test execution setup (TestNG/JUnit)

Sample code snippets

Best practices

1. Principles of a Modular Selenium Framework

A good Selenium framework MUST follow these concepts:

✔️ DRY (Don’t Repeat Yourself)

Avoid duplicated test code.

✔️ Separation of Concerns

Keep test logic, locators, utilities, and configurations separate.

✔️ Reusable Components

Actions, drivers, waits, logging, assertions.

✔️ Maintainability

Updating a locator should NOT require changing every test.

✔️ Extensibility

Easy to add new modules and test scenarios.

๐Ÿ—‚️ 2. Recommended Folder Structure

A clean, modular structure (Maven project):

src

├── main

├── java

├── base

└── BaseTest.java

├── pages

└── LoginPage.java

├── utils

├── DriverFactory.java

├── ConfigReader.java

└── WaitUtils.java

└── enums

└── resources

└── config.properties

└── test

├── java

└── tests

└── LoginTest.java

└── resources

⚙️ 3. Core Components of the Framework

Your modular framework should include:

1️⃣ Driver Management

Selenium WebDriver initialization

Browser selection

Thread-safe driver for parallel execution

2️⃣ Page Object Model (POM)

Each page = a dedicated class

Encapsulates:

Locators

Page actions

Validations

3️⃣ Utilities

Reusable helper methods:

Waits

Logging

Screenshots

Excel/JSON readers

4️⃣ Configuration Management

Store reusable settings in:

config.properties

Example:

baseURL=https://example.com

browser=chrome

timeout=10

5️⃣ Test Runner

Using TestNG or JUnit for:

Test execution

Groups

Assertions

Reporting

๐ŸŒ 4. Driver Factory Example (Singleton + ThreadLocal)

public class DriverFactory {

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

public static WebDriver getDriver() {

return driver.get();

}

public static void initDriver(String browser) {

if (browser.equalsIgnoreCase("chrome")) {

driver.set(new ChromeDriver());

}

driver.get().manage().window().maximize();

}

public static void quitDriver() {

driver.get().quit();

driver.remove();

}

}

This enables parallel test execution safely.

๐Ÿ“„ 5. Base Test Class

public class BaseTest {

@BeforeMethod

@Parameters("browser")

public void setUp(String browser) {

DriverFactory.initDriver(browser);

DriverFactory.getDriver().get(ConfigReader.getProperty("baseURL"));

}

@AfterMethod

public void tearDown() {

DriverFactory.quitDriver();

}

}

All test classes extend BaseTest.

๐Ÿงฑ 6. Page Object Model (POM)

Example: LoginPage.java

public class LoginPage {

private WebDriver driver;

@FindBy(id="username")

private WebElement username;

@FindBy(id="password")

private WebElement password;

@FindBy(id="loginBtn")

private WebElement loginBtn;

public LoginPage(WebDriver driver) {

this.driver = driver;

PageFactory.initElements(driver, this);

}

public void enterUsername(String user) {

username.sendKeys(user);

}

public void enterPassword(String pass) {

password.sendKeys(pass);

}

public void clickLogin() {

loginBtn.click();

}

}

๐Ÿงช 7. Test Class Example

public class LoginTest extends BaseTest {

@Test

public void validLoginTest() {

LoginPage loginPage = new LoginPage(DriverFactory.getDriver());

loginPage.enterUsername("admin");

loginPage.enterPassword("12345");

loginPage.clickLogin();

Assert.assertTrue(DriverFactory.getDriver().getTitle().contains("Dashboard"));

}

}

This test is clean because all logic lives in page classes and utilities.

๐Ÿงฐ 8. Utilities (Example)

WaitUtils.java

public class WaitUtils {

public static WebElement waitForElement(WebDriver driver, By locator, int timeout) {

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeout));

return wait.until(ExpectedConditions.visibilityOfElementLocated(locator));

}

}

ConfigReader.java

public class ConfigReader {

private static Properties properties = new Properties();

static {

try (InputStream input = new FileInputStream("config.properties")) {

properties.load(input);

} catch (Exception e) {

e.printStackTrace();

}

}

public static String getProperty(String key) {

return properties.getProperty(key);

}

}

๐Ÿ“Š 9. Reporting Tools

Integrate:

ExtentReports

Allure Reports

TestNG HTML reports

These give insights into passed/failed tests, screenshots, logs, and timing.

๐Ÿงฑ 10. Best Practices for a Modular Selenium Framework

✔️ Use Page Object Model (POM)

Keep locators and methods grouped logically.

✔️ Use Page Factory or By locators consistently

Avoid mixing patterns.

✔️ Parameterize Test Data

Use JSON, CSV, Excel, or external data providers.

✔️ Keep test classes extremely small

Logic belongs in pages & utilities, not in the test itself.

✔️ Enable parallel execution

Use ThreadLocal WebDriver.

✔️ Use Maven or Gradle for dependency management

✔️ Maintain a clear naming convention

๐ŸŽ‰ Conclusion

A modular Selenium framework in Java makes test automation:

Clean

Organized

Scalable

Maintainable

Reusable

By using POM, utilities, driver factories, and structured tests, your framework becomes robust enough for real-world enterprise test automation.

Learn Selenium with JAVA Training in Hyderabad

Read More

๐Ÿงฑ Framework Building & Design

Using Config Files for Environment Management

Reading Environment Variables in Selenium Tests

Using HashMap and ArrayList to Store Test Data

Visit Our Quality Thought Institute in Hyderabad

Get Directions

Subscribe by Email

Follow Updates Articles from This Blog via Email

No Comments

About

Search This Blog

Powered by Blogger.

Blog Archive