How to Build a Modular Selenium + Cucumber Framework in Java

Modern QA demands more than just writing test cases — it requires building scalable, maintainable, and modular automation frameworks. If you’re using Selenium with Java, integrating it with Cucumber brings structure and clarity to your test design. But how do you build a modular framework that can scale across projects and teams?
This guide walks through how to design a robust Selenium + Cucumber automation framework using Java, following best practices in architecture, reusability, and CI/CD integration.
Why Modular Design?
A modular automation framework:
- Promotes code reuse and separation of concerns
- Makes test maintenance easier when UI changes occur
- Allows for parallel and CI-driven test execution
- Encourages cleaner collaboration among QA, dev, and business teams
Recommended Folder Structure
Here’s a logical structure to keep the codebase clean and scalable:
lua
CopyEdit
src/test/java
├── base --> Base classes (WebDriver setup, Hooks)
├── pages --> Page Object classes
├── stepdefinitions--> Step definitions for Gherkin steps
├── runners --> Test runners (Cucumber options)
├── utils --> Utilities like config reader, wait, logs
├── features --> Gherkin (.feature) files
Tech Stack
ComponentToolUI AutomationSelenium WebDriverBDDCucumber + GherkinLanguageJavaBuild ToolMaven
GradleTest ReportingAllure
ExtentReportsCI/CDJenkins
GitHub Actions
Setting Up WebDriver & Hooks
Base Class: Centralized WebDriver setup
java
CopyEdit
public class BaseTest {
public static WebDriver driver;
public void initializeDriver() {
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
public void tearDown() {
driver.quit();
}
}
Hooks Class: To run before and after each scenario
java
CopyEdit
public class Hooks {
BaseTest base = new BaseTest();
@Before
public void setup() {
base.initializeDriver();
}
@After
public void cleanUp() {
base.tearDown();
}
}
Page Object Model (POM)
Helps encapsulate element locators and actions:
java
CopyEdit
public class LoginPage {
WebDriver driver;
@FindBy(id = "username") WebElement username;
@FindBy(id = "password") WebElement password;
@FindBy(id = "login") WebElement loginBtn;
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void login(String user, String pass) {
username.sendKeys(user);
password.sendKeys(pass);
loginBtn.click();
}
}
Feature File (BDD Scenario)
gherkin
CopyEdit
Feature: Login functionality
Scenario: Successful login with valid credentials
Given User is on login page
When User enters valid credentials
Then User is navigated to the homepage
Step Definitions
java
CopyEdit
public class LoginSteps {
WebDriver driver = BaseTest.driver;
LoginPage login = new LoginPage(driver);
@Given("User is on login page")
public void userIsOnLoginPage() {
driver.get("https://example.com/login");
}
@When("User enters valid credentials")
public void userEntersValidCredentials() {
login.login("testuser", "testpass");
}
@Then("User is navigated to the homepage")
public void userIsOnHomePage() {
Assert.assertTrue(driver.getTitle().contains("Dashboard"));
}
}
Reporting Integration
Add Allure Maven dependencies:
xml
CopyEdit
io.qameta.allure
allure-cucumber6-jvm
2.13.0
Use annotations like @Step
, @Attachment
to enhance test traceability in reports.
CI/CD with Jenkins
Create a Jenkins job linked to your Git repository.
Add Maven build step: clean test
Post-build step: Publish Allure results
Configure triggers for nightly or pull request builds.
Best Practices
Use @BeforeStep
and @AfterStep
for fine-grained logs or screenshots.
Avoid hardcoded test data; externalize into .properties
or Excel files.
Implement RetryAnalyzer
to auto-retry flaky tests.
Run tests in parallel using TestNG
or Cucumber plugin for threads.
Final Thoughts
A modular Selenium + Cucumber framework is not just about cleaner code — it’s about test resilience, scalability, and team collaboration. With the right structure and CI integrations, it can become a powerful asset for any automation team.
If you’re starting out, begin small and scale your framework piece by piece. Over time, this structured approach will save you hundreds of hours in test maintenance and onboarding.