In this tutorial, will create a detailed tutorial on creating a data driven framework in Selenium using excel.
Table of Contents
- What is Data Driven Framework?
- Project Structure
- Dependency List
- Implementation Steps
- Step 1- Download and Install Java
- Step 2 – Download and setup Eclipse IDE on the system
- Step 3 – Setup Maven
- Step 4 – Create a new Maven Project
- Step 5 – Add Selenium ,TestNG and Apache POI dependencies to the project
- Step 6 – Create a Java Class for each page
- Step 7 – Create an ExcelUtils Class
- Step 8 – Create a Listener Class
- Step 9 – Create a BaseTests Class
- Step 10 – Create a Test Excel File
- Step 11 – Create the Tests in src/test/java
- Step 12 – Create testng.xml at the root of the project
- Step 13 – Run the tests through testng.xml
- Step 14 – View TestNG Reports
What is Data Driven Framework?
A Data Driven Framework is a software testing framework that separates the test script logic from the test data. The test data is stored separately in external files like csv, xlsx, or databases that allows easy maintenance of the framework. In data driven framework, the test scripts retrieves the input values and expected results from the external source and write the actual result to the same source like spreadsheets, XML files, CSV files or database.
Project Structure
Here is the final snapshot of our project.
![](https://qaautomation.expert/wp-content/uploads/2024/06/image-1.png?w=480)
Dependency List
- Selenium – 4.21.0
- TestNG – 7.10.2
- Apache POI – 5.2.5
- Commons – 2.16.1
- Maven Surefire – 3.2.5
- Maven Compiler – 3.13.0
- Java 17
- Maven – 3.9.6
Implementation Steps
Step 1- Download and Install Java
Selenium needs Java to be installed on the system to run the tests. Click here to learn How to install Java.
Step 2 – Download and setup Eclipse IDE on the system
The Eclipse IDE (integrated development environment) provides strong support for Java developers, which is needed to write Java code. Click here to learn How to install Eclipse.
Step 3 – Setup Maven
To build a test framework, we need to add a number of dependencies to the project. It is a very tedious and cumbersome process to add each dependency manually. So, to overcome this problem, we use a build management tool. Maven is a build management tool that is used to define project structure, dependencies, build, and test management. Click here to learn How to install Maven.
Step 4 – Create a new Maven Project
Click here to learn How to create a Maven project
Below is the Maven project structure. Here,
Group Id – com.example
Artifact Id – DataDrivenFramework
Version – 0.0.1-SNAPSHOT
Package – com. example. DataDrivenFramework
Step 5 – Add Selenium ,TestNG and Apache POI dependencies to the project
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>DataDrivenFramework</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>DataDrivenFramework</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<selenium.version>4.21.0</selenium.version>
<testng.version>7.10.2</testng.version>
<poi.version>5.2.5</poi.version>
<poi.ooxml.version>5.2.5</poi.ooxml.version>
<commons.version>2.16.1</commons.version>
<maven.surefire.plugin.version>3.2.5</maven.surefire.plugin.version>
<maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.ooxml.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.plugin.version}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven.surefire.plugin.version}</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
</project>
Step 6 – Create a Java Class for each page
In this example, we will access 2 web pages, “Login” and “Home” pages.
Hence, we will create 2 Java classes in Page Layer – LoginPage.java and HomePage.java and a BasePage class to initialize the driver using PageFactory.
BasePage
package com.example.pages;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.PageFactory;
public class BasePage {
public WebDriver driver;
public BasePage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver,this);
}
}
LoginPage
package com.example.pages;
import com.example.utils.ExcelUtils;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPage extends BasePage{
public LoginPage(WebDriver driver) {
super(driver);
}
@FindBy(name = "username")
public WebElement userName;
@FindBy(name = "password")
public WebElement password;
@FindBy(xpath = "//*[@class='oxd-form']/div[1]/div/span")
public WebElement missingUsernameErrorMessage;
@FindBy(xpath = "//*[@class='oxd-form']/div[2]/div/span")
public WebElement missingPasswordErrorMessage;
@FindBy(xpath = "//*[@class='oxd-form']/div[3]/button")
public WebElement login;
@FindBy(xpath = "//*[@id='app']/div[1]/div/div[1]/div/div[2]/div[2]/div/div[1]/div[1]/p")
public WebElement errorMessage;
public void login(String strUserName, String strPassword) {
userName.sendKeys(strUserName);
password.sendKeys(strPassword);
login.click();
}
public String getMissingUsernameText() {
return missingUsernameErrorMessage.getText();
}
public String getMissingPasswordText() {
return missingPasswordErrorMessage.getText();
}
public String getErrorMessage() {
return errorMessage.getText();
}
public LoginPage saveTestResults(int row, int column) {
ExcelUtils.rowNumber = row ;
ExcelUtils.columnNumber = column;
return this;
}
}
HomePage
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class HomePage extends BasePage {
public HomePage(WebDriver driver) {
super(driver);
}
@FindBy(xpath = "//*[@id='app']/div[1]/div[1]/header/div[1]/div[1]/span/h6")
public WebElement homePageUserName;
public String getHomePageText() {
return homePageUserName.getText();
}
}
Step 7 – Create an ExcelUtils Class
In order to manipulate excel files and do excel operations, we should create an excel file and called it “ExcelUtils” under utils package as shown below.
package com.example.utils;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ExcelUtils {
public static final String testDataExcelFileName = "testdata.xlsx"; //Global test data excel file
public static final String currentDir = System.getProperty("user.dir"); //Main Directory of the project
public static final String resourcePath = "\\src\\test\\resources\\"; //Main Directory of the project
public static String testDataExcelPath = null; //Location of Test data excel file
private static XSSFWorkbook excelWorkBook; //Excel WorkBook
private static XSSFSheet excelWorkSheet; //Excel Sheet
private static XSSFCell cell; //Excel cell
private static XSSFRow row; //Excel row
public static int rowNumber; //Row Number
public static int columnNumber; //Column Number
public static FileInputStream ExcelFile;
public static DataFormatter formatter;
public static FileOutputStream fileOut;
// This method has two parameters: "Test data excel file name" and "Excel sheet name"
// It creates FileInputStream and set excel file and excel sheet to excelWBook and excelWSheet variables.
public static void setExcelFileSheet(String sheetName) throws IOException {
testDataExcelPath = currentDir + resourcePath;
// Open the Excel file
ExcelFile = new FileInputStream(testDataExcelPath + testDataExcelFileName);
excelWorkBook = new XSSFWorkbook(ExcelFile);
excelWorkSheet = excelWorkBook.getSheet(sheetName);
}
//This method reads the test data from the Excel cell.
public static String getCellData(int rowNum, int colNum) {
cell = excelWorkSheet.getRow(rowNum).getCell(colNum);
formatter = new DataFormatter();
return formatter.formatCellValue(cell);
}
//This method takes row number as a parameter and returns the data of given row number.
public static XSSFRow getRowData(int rowNum) {
row = excelWorkSheet.getRow(rowNum);
return row;
}
//This method gets excel file, row and column number and set a value to the that cell.
public static void setCellData(String value, int rowNum, int colNum) throws IOException {
row = excelWorkSheet.getRow(rowNum);
cell = row.getCell(colNum);
if (cell == null) {
cell = row.createCell(colNum);
cell.setCellValue(value);
} else {
cell.setCellValue(value);
}
// Write to the workbook
fileOut = new FileOutputStream(testDataExcelPath + testDataExcelFileName);
excelWorkBook.write(fileOut);
fileOut.flush();
fileOut.close();
}
}
In this file, I wrote all excel operation methods.
setExcelFileSheet: This method has two parameters: “testdata.xlsx” and “LoginData”. It creates FileInputStream and set excel file and excel sheet to excelWorkBook and excelWorkSheet variables.
getCellData: This method reads the test data from the Excel cell. We are passing row numbers and column numbers as parameters.
getRowData: This method takes row number as a parameter and returns the data of the given row number.
setCellData: This method gets an excel file, row, and column number and sets a value to that cell.
Step 8 – Create a Listener Class
We need to create a TestNG Listener class to check the status of each of the test.
import com.example.tests.BaseTests;
import org.openqa.selenium.WebDriver;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import java.io.IOException;
public class TestListener implements ITestListener {
private static String getTestMethodName(ITestResult iTestResult) {
return iTestResult.getMethod().getConstructorOrMethod().getName();
}
@Override
public void onStart(ITestContext iTestContext) {
System.out.println("I am in onStart method :" + iTestContext.getName());
}
@Override
public void onFinish(ITestContext iTestContext) {
System.out.println("I am in onFinish method :" + iTestContext.getName());
}
@Override
public void onTestStart(ITestResult iTestResult) {
System.out.println("I am in onTestStart method :" + getTestMethodName(iTestResult) + ": start");
}
@Override
public void onTestSuccess(ITestResult iTestResult) {
System.out.println("I am in onTestSuccess method :" + getTestMethodName(iTestResult) + ": succeed");
try {
ExcelUtils.setCellData("PASSED", ExcelUtils.rowNumber, ExcelUtils.columnNumber);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void onTestFailure(ITestResult iTestResult) {
System.out.println("I am in onTestFailure method :" + getTestMethodName(iTestResult) + " failed");
try {
ExcelUtils.setCellData("FAILED", ExcelUtils.rowNumber, ExcelUtils.columnNumber);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void onTestSkipped(ITestResult iTestResult) {
System.out.println("I am in onTestSkipped method :" + getTestMethodName(iTestResult) + ": skipped");
try {
ExcelUtils.setCellData("SKIPPED", ExcelUtils.rowNumber, ExcelUtils.columnNumber);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult iTestResult) {
System.out.println("Test failed but it is in defined success ratio " + getTestMethodName(iTestResult));
}
}
Step 9 – Create a BaseTests Class
This BaseTests class contains the setup and tearDown methods to initialize the driver at the start of the test and exit the driver at the end of the test.
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import java.time.Duration;
public class BaseTests {
public static WebDriver driver;
public final static int TIMEOUT = 10;
@BeforeMethod
public void setup() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
options.addArguments("--no-sandbox");
options.addArguments("--disable-dev-shm-usage");
options.addArguments("--headless");
driver = new ChromeDriver(options);
driver.manage().window().maximize();
driver.get("https://opensource-demo.orangehrmlive.com/");
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(TIMEOUT));
}
@AfterMethod
public void tearDown() {
driver.quit();
}
}
Step 10 – Create a Test Excel File
Create a test file – testdata.xlsx and place it in src/test/resources. I have stored the following data in the file.
- Test Case Name – Name of the test case
- Username
- Password
- ExpectedResponse – This is the response we expect to get from the execution for the particular test.
- ActualResponse – This is the response we get after the execution of the particular test
- Status – This could be pass, fail, skip
![](https://qaautomation.expert/wp-content/uploads/2024/06/image-2.png?w=807)
Step 11 – Create the Tests in src/test/java
In the below LoginPageTests class, we have 4 different tests and we are failing test – validCredentials() to show that the test result will be saved in testdata.xlsx file for both passed and failed tests.
package com.example.tests;
import com.example.pages.HomePage;
import com.example.pages.LoginPage;
import com.example.utils.ExcelUtils;
import com.example.utils.TestListener;
import org.openqa.selenium.WebDriver;
import org.testng.Assert;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import java.io.IOException;
@Listeners({TestListener.class })
public class LoginPageTests extends BaseTests{
String actualResponse;
@BeforeTest
public void setupTestData() throws IOException {
System.out.println("Setup Test Data");
ExcelUtils.setExcelFileSheet("LoginData");
}
@Test
public void invalidCredentials() throws IOException {
LoginPage objLoginPage = new LoginPage(driver);
objLoginPage.login(ExcelUtils.getCellData(1,1), ExcelUtils.getCellData(1,2));
actualResponse = objLoginPage.getErrorMessage();
ExcelUtils.setCellData(actualResponse,1,4);
objLoginPage.saveTestResults(1,5);
Assert.assertEquals(actualResponse,ExcelUtils.getCellData(1,3));
}
@Test
public void missingUsername() throws IOException {
LoginPage objLoginPage = new LoginPage(driver);
objLoginPage.login(ExcelUtils.getCellData(2,1), ExcelUtils.getCellData(2,2));
actualResponse = objLoginPage.getMissingUsernameText();
ExcelUtils.setCellData(actualResponse,2,4);
objLoginPage.saveTestResults(2,5);
Assert.assertEquals(actualResponse,ExcelUtils.getCellData(2,3));
}
@Test
public void missingPassword() throws IOException {
LoginPage objLoginPage = new LoginPage(driver);
objLoginPage.login(ExcelUtils.getCellData(3,1), ExcelUtils.getCellData(3,2));
actualResponse = objLoginPage.getMissingPasswordText();
ExcelUtils.setCellData(actualResponse,3,4);
objLoginPage.saveTestResults(3,5);
Assert.assertEquals(actualResponse,ExcelUtils.getCellData(3,3));
}
//Fail this test
@Test
public void validCredentials() throws IOException {
LoginPage objLoginPage = new LoginPage(driver);
objLoginPage.login(ExcelUtils.getCellData(4,1), ExcelUtils.getCellData(4,2));
HomePage objHomePage = new HomePage(driver);
actualResponse = objHomePage.getHomePageText();
ExcelUtils.setCellData(actualResponse,4,4);
objLoginPage.saveTestResults(4,5);
Assert.assertEquals(actualResponse,ExcelUtils.getCellData(4,3));
}
}
Step 12 – Create testng.xml at the root of the project
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Data Driven Framework">
<test name="Login Test">
<classes>
<class name="com.example.tests.LoginPageTests"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
Step 13 – Run the tests through testng.xml
Right-click on the testng.xml and select “Run ..\testng.xml”.
![](https://qaautomation.expert/wp-content/uploads/2024/06/image-3.png?w=323)
The output of the above execution is
![](https://qaautomation.expert/wp-content/uploads/2024/06/image-4.png?w=1200)
As expected, 3 test are passed and 1 test is failed.
The testdata.xlsx file will be updated with the actual response and the test execution status as shown in the below image.
![](https://qaautomation.expert/wp-content/uploads/2024/06/image-6.png?w=837)
Note – Make sure to close the excel workbook before starting the test execution, otherwise the test execution will be in the hung state.
Step 14 – View TestNG Reports
If you are using IntelliJ, the HTML Reports do not generate automatically. Go to the Configuration -> Listeners -> select Use default Reporters.
![](https://qaautomation.expert/wp-content/uploads/2024/06/image-11.png?w=585)
The TestNG Reports will be generated in test-output folder.
![](https://qaautomation.expert/wp-content/uploads/2024/06/image-8.png?w=317)
We are concerned about 2 reports – index.html and emailable-report.html.
index.html
![](https://qaautomation.expert/wp-content/uploads/2024/06/image-9.png?w=1200)
emailable-report.html
![](https://qaautomation.expert/wp-content/uploads/2024/06/image-10.png?w=1067)
Summary:
- The test scripts in Data Driven Framework can be reused with different sets of test data.
- The Test data can be easily modified without modifying the actual code implementation.
- This framework has used excel as an external source to store the test data and test results.
The complete code can be found here – /vibssingh/Selenium-Data-Driven-Framework.
That’s it! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!