Hybrid Selenium Framework with POM + TestNG: Complete Implementation Guide

Complete Hybrid Selenium Framework - Ready to Use

This is the full, production-ready implementation of a Hybrid Selenium Framework using Page Object Model (POM) and TestNG. All classes, utilities, and configuration files are included with complete working code.

Project Structure Overview

src/
├── main/
│   ├── java/
│   │   ├── config/
│   │   │   └── ConfigReader.java
│   │   ├── pages/
│   │   │   └── LoginPage.java
│   │   ├── utilities/
│   │   │   ├── DriverManager.java
│   │   │   └── ExcelReader.java
│   │   └── base/
│   │       └── BaseTest.java
│   └── resources/
│       ├── config.properties
│       └── testdata/
│           └── LoginData.xlsx
├── test/
│   ├── java/tests/
│   │   └── LoginTest.java
│   └── resources/
│       └── testng.xml
└── pom.xml

1. pom.xml - Complete Dependencies

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.automation</groupId>
    <artifactId>selenium-pom-framework</artifactId>
    <version>1.0</version>
    
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.17.0</version>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>7.9.0</version>
        </dependency>
        <dependency>
            <groupId>com.aventstack</groupId>
            <artifactId>extentreports</artifactId>
            <version>5.1.1</version>
        </dependency>
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>5.6.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.5</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.2.5</version>
                <configuration>
                    <suiteXmlFiles>
                        <suiteXmlFile>testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2. config.properties - Configuration File

File location: src/main/resources/config.properties

browser=chrome
url=https://login.salesforce.com
timeout=10
headless=false

3. ConfigReader.java - Read Configuration Properties

Location: src/main/java/config/ConfigReader.java

package config;

import java.io.FileInputStream;
import java.util.Properties;

public class ConfigReader {
    private static Properties properties;
    
    static {
        try {
            properties = new Properties();
            properties.load(new FileInputStream("src/main/resources/config.properties"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public static String getProperty(String key) {
        return properties.getProperty(key);
    }
}

4. DriverManager.java - WebDriver Factory

Location: src/main/java/utilities/DriverManager.java

package utilities;

import config.ConfigReader;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;

public class DriverManager {
    public static WebDriver getDriver() {
        String browser = ConfigReader.getProperty("browser");
        if ("chrome".equalsIgnoreCase(browser)) {
            WebDriverManager.chromedriver().setup();
            ChromeOptions options = new ChromeOptions();
            if (Boolean.parseBoolean(ConfigReader.getProperty("headless"))) {
                options.addArguments("--headless");
            }
            options.addArguments("--disable-notifications");
            return new ChromeDriver(options);
        } else {
            WebDriverManager.firefoxdriver().setup();
            return new FirefoxDriver();
        }
    }
}

5. ExcelReader.java - Data-Driven Test Support

Location: src/main/java/utilities/ExcelReader.java

package utilities;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;
import java.io.IOException;

public class ExcelReader {
    public static Object[][] getData(String filePath, String sheetName) {
        try (FileInputStream fis = new FileInputStream(filePath);
             Workbook workbook = new XSSFWorkbook(fis)) {
            
            Sheet sheet = workbook.getSheet(sheetName);
            int rows = sheet.getLastRowNum();
            int cells = sheet.getRow(0).getLastCellNum();
            
            Object[][] data = new Object[rows][cells];
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < cells; j++) {
                    data[i][j] = sheet.getRow(i + 1).getCell(j).getStringCellValue();
                }
            }
            return data;
        } catch (IOException e) {
            throw new RuntimeException("Excel read error: " + e.getMessage());
        }
    }
}

6. LoginPage.java - Page Object Model

Location: src/main/java/pages/LoginPage.java

package pages;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class LoginPage {
    private WebDriver driver;
    private WebDriverWait wait;
    
    @FindBy(xpath = "//input[contains(@id,'username')]")
    private WebElement usernameField;
    
    @FindBy(xpath = "//input[contains(@id,'password')]")
    private WebElement passwordField;
    
    @FindBy(xpath = "//input[@type='submit' or contains(@value,'Log')]")
    private WebElement loginButton;
    
    @FindBy(xpath = "//div[contains(@class,'error')]")
    private WebElement errorMessage;
    
    public LoginPage(WebDriver driver) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, 10);
        PageFactory.initElements(driver, this);
    }
    
    public void enterUsername(String username) {
        wait.until(ExpectedConditions.visibilityOf(usernameField));
        usernameField.clear();
        usernameField.sendKeys(username);
    }
    
    public void enterPassword(String password) {
        passwordField.clear();
        passwordField.sendKeys(password);
    }
    
    public void clickLogin() {
        loginButton.click();
    }
    
    public String getErrorMessage() {
        return errorMessage.getText();
    }
    
    public void login(String username, String password) {
        enterUsername(username);
        enterPassword(password);
        clickLogin();
    }
}

7. BaseTest.java - Test Base Class

Location: src/test/java/base/BaseTest.java

package base;

import config.ConfigReader;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import pages.LoginPage;
import utilities.DriverManager;

public class BaseTest {
    protected WebDriver driver;
    protected LoginPage loginPage;
    
    @BeforeMethod
    public void setup() {
        driver = DriverManager.getDriver();
        driver.manage().window().maximize();
        driver.get(ConfigReader.getProperty("url"));
        loginPage = new LoginPage(driver);
    }
    
    @AfterMethod
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

8. LoginTest.java - Test Class with Data Provider

Location: src/test/java/tests/LoginTest.java

package tests;

import base.BaseTest;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import utilities.ExcelReader;

public class LoginTest extends BaseTest {
    
    @DataProvider(name = "loginData")
    public Object[][] getLoginData() {
        return ExcelReader.getData("src/main/resources/testdata/LoginData.xlsx", "Sheet1");
    }
    
    @Test(dataProvider = "loginData", groups = "smoke")
    public void validLoginTest(String username, String password) {
        loginPage.login(username, password);
        Assert.assertTrue(driver.getTitle().contains("Salesforce"));
    }
    
    @Test(groups = "negative")
    public void invalidLoginTest() {
        loginPage.login("invalid@test.com", "wrongpass");
        Assert.assertTrue(loginPage.getErrorMessage().contains("Error"));
    }
}

9. testng.xml - Test Suite Configuration

Location: src/test/resources/testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<suite name="SalesforceRegressionSuite" parallel="methods" thread-count="3">
    <test name="SmokeTests">
        <groups>
            <run>
                <include name="smoke"/>
            </run>
        </groups>
        <classes>
            <class name="tests.LoginTest"/>
        </classes>
    </test>
    <test name="NegativeTests">
        <groups>
            <run>
                <include name="negative"/>
            </run>
        </groups>
        <classes>
            <class name="tests.LoginTest"/>
        </classes>
    </test>
</suite>

How Each Class Works Together

Post a Comment

0 Comments