Answer
Hybrid Framework Architecture in Selenium
A Hybrid Framework combines the best of Data-Driven + Keyword-Driven + Page Object Model approaches. It is the most commonly used framework in real enterprise QA teams.
Directory Structure
CODE
SeleniumHybridFramework/
├── src/
│ ├── main/java/
│ │ ├── base/ BaseTest.java
│ │ ├── pages/ LoginPage.java, DashboardPage.java
│ │ ├── utils/ ExcelUtils.java, DriverManager.java
│ │ └── keywords/ KeywordExecutor.java
│ └── test/
│ ├── java/tests/ LoginTest.java
│ └── resources/
│ ├── config.properties
│ └── testdata/ TestData.xlsx
├── testng.xml
└── pom.xml
Layer 1 — Page Object Layer
Java
public class LoginPage {
@FindBy(id = "username") private WebElement usernameField;
@FindBy(id = "password") private WebElement passwordField;
@FindBy(id = "loginBtn") private WebElement loginBtn;
public LoginPage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
public void login(String user, String pass) {
usernameField.sendKeys(user);
passwordField.sendKeys(pass);
loginBtn.click();
}
}
Layer 2 — Data-Driven (Excel)
Java
public class ExcelUtils {
private XSSFWorkbook workbook;
public ExcelUtils(String filePath) throws Exception {
workbook = new XSSFWorkbook(new FileInputStream(filePath));
}
public String getCellData(String sheetName, int row, int col) {
return workbook.getSheet(sheetName).getRow(row).getCell(col).getStringCellValue();
}
public int getRowCount(String sheetName) {
return workbook.getSheet(sheetName).getLastRowNum();
}
}
Layer 3 — Keyword Engine
Java
public class KeywordExecutor {
private WebDriver driver;
public KeywordExecutor(WebDriver driver) { this.driver = driver; }
public void execute(String keyword, String locator, String value) {
WebElement el;
switch (keyword.toUpperCase()) {
case "CLICK" -> driver.findElement(By.xpath(locator)).click();
case "TYPE" -> { el = driver.findElement(By.xpath(locator));
el.clear(); el.sendKeys(value); }
case "VERIFY" -> Assert.assertEquals(
driver.findElement(By.xpath(locator)).getText(), value);
case "NAVIGATE" -> driver.get(value);
case "WAIT" -> new WebDriverWait(driver, Duration.ofSeconds(Integer.parseInt(value)))
.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(locator)));
}
}
}
Layer 4 — TestNG Test + DataProvider
Java
public class LoginTest extends BaseTest {
@Test(dataProvider = "loginData")
public void loginTest(String username, String password, String expected) {
LoginPage loginPage = new LoginPage(DriverManager.getDriver());
loginPage.login(username, password);
Assert.assertTrue(DriverManager.getDriver().getTitle().contains(expected));
}
@DataProvider(name = "loginData")
public Object[][] loginData() throws Exception {
ExcelUtils excel = new ExcelUtils("src/test/resources/testdata/TestData.xlsx");
int rows = excel.getRowCount("Login");
Object[][] data = new Object[rows][3];
for (int i = 0; i < rows; i++) {
data[i][0] = excel.getCellData("Login", i + 1, 0); // username
data[i][1] = excel.getCellData("Login", i + 1, 1); // password
data[i][2] = excel.getCellData("Login", i + 1, 2); // expected
}
return data;
}
}
Framework Benefits
| Benefit | How Achieved |
|---|---|
| Easy maintenance | POM — one place to update locators |
| Business-readable | Keyword-driven test sheets |
| Multiple data sets | Excel DataProvider |
| Parallel execution | ThreadLocal driver + TestNG |
| Reports | ExtentReports listener |
| CI/CD ready | Maven + Jenkins |
