🔹 What is POM?
● Design pattern used in test automation frameworks.
● Helps create an object repository for web elements.
● Each web page = one class file in your code.
● Separates test logic from UI locators, making code reusable & maintainable.
● If a locator changes → only update in page class, not in all test scripts.
🔹 Key Advantages
● Reusability: Same page methods used in multiple tests.
● Maintainability: Update locators in one place only.
● Readability: Test scripts look cleaner & business-focused.
● Reduces code duplication.
🔹 Structure
1. Page Class (represents a page)
○ Contains web elements (locators).
○ Contains methods (actions on elements).
2. Test Class (represents test cases)
○ Calls page methods to perform actions.
🔹 Example
Suppose you want to automate Login Page.
✅ Page Class → [Link]
package pages;
import [Link];
import [Link];
import [Link];
import [Link];
public class LoginPage {
WebDriver driver;
// Constructor
public LoginPage(WebDriver driver) {
[Link] = driver;
[Link](driver, this); // Initializes
@FindBy
}
// Locators
@FindBy(id="username")
WebElement username;
@FindBy(id="password")
WebElement password;
@FindBy(id="loginBtn")
WebElement loginButton;
// Actions
public void setUsername(String user) {
[Link](user);
}
public void setPassword(String pass) {
[Link](pass);
}
public void clickLogin() {
[Link]();
}
// High-level method
public void login(String user, String pass) {
setUsername(user);
setPassword(pass);
clickLogin();
}
}
✅ Test Class → [Link]
package tests;
import [Link];
import [Link];
import [Link];
import [Link];
public class LoginTest {
@Test
public void verifyLogin() {
WebDriver driver = new ChromeDriver();
[Link]("[Link]
// Create Page Object
LoginPage loginPage = new LoginPage(driver);
// Perform login using POM methods
[Link]("testUser", "testPass");
// Assertions can go here
// Example: Assert page title or welcome message
[Link]();
}
}
🔹 Flow
1. Test class opens browser → navigates to URL.
2. It creates object of LoginPage.
3. Calls [Link]("user", "pass").
4. Page class handles locators & actions internally.
👉 Without POM → you would write locators & actions in every test.
👉 With POM → you centralize them in one class = clean, reusable, scalable code
🔹 Page Factory in Selenium
● Page Factory is a class in Selenium that helps implement Page Object Model (POM)
easily.
● It provides @FindBy annotations to locate elements.
● Removes boilerplate code like [Link](...).
● Elements are initialized using [Link](driver, this).
● Supports lazy initialization (elements are created only when used).
🔹 POM vs POM with Page Factory
● POM without Page Factory → You declare WebElement normally and use
[Link]() in methods.
● POM with Page Factory → You declare WebElement with @FindBy, and Selenium
initializes them automatically
🔹 Example: Login Page with Page
Factory
✅ Page Class → [Link]
package pages;
import [Link];
import [Link];
import [Link];
import [Link];
public class LoginPage {
WebDriver driver;
// Constructor
public LoginPage(WebDriver driver) {
[Link] = driver;
[Link](driver, this); // Initializes
@FindBy annotated elements
// Locators using PageFactory
@FindBy(id="username")
private WebElement username;
@FindBy(id="password")
private WebElement password;
@FindBy(id="loginBtn")
private WebElement loginButton;
// Actions
public void setUsername(String user) {
[Link](user);
public void setPassword(String pass) {
[Link](pass);
public void clickLogin() {
[Link]();
}
// High-level action (combined steps)
public void login(String user, String pass) {
setUsername(user);
setPassword(pass);
clickLogin();
✅ Test Class → [Link]
package tests;
import [Link];
import [Link];
import [Link];
import [Link];
public class LoginTest {
@Test
public void verifyLogin() {
WebDriver driver = new ChromeDriver();
[Link]("[Link]
// Create Page Object (PageFactory initializes elements
automatically)
LoginPage loginPage = new LoginPage(driver);
// Perform login using PageFactory methods
[Link]("testUser", "testPass");
// Assertions here
// Example: [Link]([Link](),
"Dashboard");
[Link]();
🔹 Benefits of Page Factory
● No need for [Link]().
● Makes code shorter & more readable.
● Elements are initialized automatically.
● Supports @FindBys (AND conditions) & @FindAll (OR conditions)
🔹 Folder Structure Example
/project-root
├── src/test/java
│ ├── pages
│ │ └── [Link]
│ ├── tests
│ │ └── [Link]
│ ├── utils
│ │ └── [Link]
│ └── [Link]
└── [Link] (if using Maven)
👉 Summary:
● POM = design pattern to organize tests.
● Page Factory = Selenium’s helper to make POM easier & cleaner.
🔹 1. What is a Hybrid Framework in Test
Automation?
● A Hybrid Framework is a combination of multiple automation frameworks.
● It takes the best parts of:
○ Data Driven Framework → test data from external files (Excel, CSV, DB, JSON,
etc.).
○ Keyword Driven Framework → actions (click, type, select) defined as keywords
in external files.
○ Page Object Model (POM) → separates locators & actions in page classes.
● It is called hybrid because it blends these approaches.
✅ Example:
● Test logic → in TestNG/JUnit classes.
● UI interaction → in POM classes.
● Test data → Excel/CSV (read using Apache POI).
● Keywords (optional) → like LOGIN, LOGOUT, SEARCH.
🔹 2. Data Driven Framework
(Excel-based)
● Data Driven Framework means test input/output values are read from external
sources.
● Excel is most common → allows testers to run the same test with multiple datasets.
● Example use: Testing login with multiple username/password combinations.
🔹 3. How to Read Data from Excel in
Selenium (Apache POI)
✅ Step 1: Add Dependency (Maven)
<dependency>
<groupId>[Link]</groupId>
<artifactId>poi</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
✅ Step 2: Create Excel File (e.g., [Link])
Usernam Passwor
e d
testUser1 pass123
testUser2 pass456
✅ Step 3: Utility to Read Excel → [Link]
package utils;
import [Link].*;
import [Link];
import [Link];
import [Link];
public class ExcelUtils {
public static Object[][] getData(String filePath, String
sheetName) throws IOException {
FileInputStream fis = new FileInputStream(filePath);
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = [Link](sheetName);
int rows = [Link]();
int cols = [Link](0).getPhysicalNumberOfCells();
Object[][] data = new Object[rows - 1][cols]; // Skip header
row
for (int i = 1; i < rows; i++) {
Row row = [Link](i);
for (int j = 0; j < cols; j++) {
Cell cell = [Link](j);
data[i - 1][j] = [Link](); // Store as String
[Link]();
[Link]();
return data;
}
✅ Step 4: Test Class with DataProvider → [Link]
package tests;
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
public class LoginTest {
@DataProvider(name = "loginData")
public Object[][] getLoginData() throws Exception {
return [Link]("src/test/resources/[Link]",
"Sheet1");
@Test(dataProvider = "loginData")
public void verifyLogin(String username, String password) {
WebDriver driver = new ChromeDriver();
[Link]("[Link]
LoginPage loginPage = new LoginPage(driver);
[Link](username, password);
// Assertions here
[Link]();
🔹 4. Flow of Hybrid Framework (Excel +
POM + TestNG)
1. Test Data → Excel ([Link]).
2. ExcelUtils → Reads data via Apache POI.
3. DataProvider → Supplies data to TestNG tests.
4. Test Class → Iterates over test data, executes login multiple times.
5. POM (PageFactory) → Handles UI locators/actions.
🔹 5. Benefits
● Hybrid Framework:
○ Reusable test data (Excel).
○ Clean code (POM).
○ Flexibility (combine with keywords).
○ Easy maintenance.
👉 In short:
● Data Driven Framework → only test data separation.
● Hybrid Framework → mix of POM + Data Driven + sometimes Keyword Driven →
scalable + maintainable.
❓ Where do you use OOPs in your framework?
As an SDET, I use OOPs concepts (Encapsulation, Inheritance, Polymorphism, Abstraction)
extensively in my Selenium framework.
1. Encapsulation (Data hiding + Getters/Setters)
👉 Used in Page Object Model (POM) where we keep locators private and expose actions via
public methods.
public class LoginPage {
// Encapsulation: Locators hidden as private
private WebDriver driver;
private By username = [Link]("username");
private By password = [Link]("password");
private By loginBtn = [Link]("login");
public LoginPage(WebDriver driver) {
[Link] = driver;
// Public methods to access private locators
public void enterUsername(String user) {
[Link](username).sendKeys(user);
public void enterPassword(String pass) {
[Link](password).sendKeys(pass);
public void clickLogin() {
[Link](loginBtn).click();
✅ Answer: I use encapsulation in my POM design by keeping locators private and exposing
reusable methods for page interactions.
2. Inheritance (Reusability)
👉 Used in Base Class where common functionality (launch browser, quit browser, waits,
screenshots) is defined, and other classes extend it.
public class BaseTest {
protected WebDriver driver;
public void setUp() {
driver = new ChromeDriver();
[Link]().window().maximize();
public void tearDown() {
[Link]();
}
// Test class inherits BaseTest
public class LoginTest extends BaseTest {
@Test
public void testLogin() {
setUp();
[Link]("[Link]
// test steps
tearDown();
✅ Answer: I use inheritance to avoid code duplication – test classes extend a BaseTest that
contains setup, teardown, and utility functions.
3. Polymorphism (Method Overloading & Overriding)
👉 Used in utility methods for flexibility.
Overloading (compile-time polymorphism):
public class WaitHelper {
WebDriver driver;
public WaitHelper(WebDriver driver) {
[Link] = driver;
// Overloaded methods
public void waitForElement(By locator, int time) {
new WebDriverWait(driver, [Link](time))
.until([Link](locator));
public void waitForElement(WebElement element, int time) {
new WebDriverWait(driver, [Link](time))
.until([Link](element));
Overriding (runtime polymorphism):
class DriverManager {
public WebDriver getDriver() {
return new ChromeDriver();
}
class FirefoxDriverManager extends DriverManager {
@Override
public WebDriver getDriver() {
return new FirefoxDriver();
✅ Answer: I use polymorphism to overload methods (same method name, different
parameters) and also to override driver managers for different browsers.
4. Abstraction (Hiding implementation details)
👉 Achieved using interfaces/abstract classes to define contracts.
// Abstraction: Only define what to do, not how
public interface ITestLogger {
void logInfo(String message);
void logError(String message);
// Implementation 1
public class ConsoleLogger implements ITestLogger {
public void logInfo(String message) {
[Link]("INFO: " + message);
}
public void logError(String message) {
[Link]("ERROR: " + message);
// Implementation 2
public class FileLogger implements ITestLogger {
public void logInfo(String message) {
// write log to file
public void logError(String message) {
// write error to file
✅ Answer: I use abstraction via interfaces for things like logging and reporting – where I define
a contract and multiple implementations can exist (console, file, or reporting tools).
🎯 Final Interview-Ready Answer (Short)
*"In my Selenium framework, I use all OOPs concepts:
● Encapsulation in POM (locators private, actions public).
● Inheritance in BaseTest for setup/teardown shared across tests.
● Polymorphism in utility methods (overloading waits, overriding browser drivers).
● Abstraction via interfaces for logging, reporting, and driver management.
This ensures reusability, scalability, and maintainability of the framework."*