Learn to build a data-driven framework in Selenium for scalable testing. Follow this step-by-step guide using Selenium 4, TestNG, Java, and Maven with examples. Let’s dive into data-driven testing in Selenium today!

What is a Data-Driven Framework in Selenium?
A data-driven framework in Selenium is a design pattern that separates test scripts from test data. It allows you to run the same test case with multiple inputs stored in external files (CSV, Excel, etc.), enhancing reusability and scalability. This approach answers the question: “What is data-driven testing in Selenium?” by emphasizing dynamic data injection over hardcoded values.
What is Data-Driven Testing in Selenium?
Data-driven testing in Selenium automates workflows using external datasets to validate various scenarios. For example, testing a flight booking form with 100+ passenger details without rewriting test scripts. This method directly addresses “what is data-driven framework in Selenium” by focusing on efficiency and maintainability.
Why Use a Data-Driven Framework?
✅ Scalability: Test 1,000+ scenarios with one script.
✅ Reusability: Swap datasets without code changes.
✅ Maintainability: Update test data in CSV/Excel, not scripts.
✅ Efficiency: Reduce execution time by 70% (industry average).
Key Components of a Data-Driven Framework in Selenium
- External Data Sources (CSV/Excel)
- TestNG DataProvider for dynamic data injection.
- Selenium WebDriver 4 for browser automation.
- Apache Commons IO for screenshot logging.
Step-by-Step: Build a Data-Driven Testing Framework
Step 1: Add Maven Dependencies
Include Selenium 4, TestNG, and WebDriverManager in pom.xml
:
<!-- Selenium 4 --> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>4.9.1</version> </dependency> <!-- TestNG for Data-Driven Testing --> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.4.0</version> </dependency>
Step 2: Create a CSV Test Data File
Store inputs in src/test/resources/flightData.csv
:
source,destination,departDate,returnDate New York,Los Angeles,2025-03-15,2025-03-22 Chicago,Miami,2025-04-01,2025-04-10
Step 3: Implement TestNG DataProvider
@DataProvider(name = "FlightData") public Object[][] getData() throws IOException { BufferedReader br = new BufferedReader(new FileReader("flightData.csv")); List<Object[]> data = new ArrayList<>(); String line; while ((line = br.readLine()) != null) { data.add(line.split(",")); } return data.toArray(new Object[0][]); }
Step 4: Run Data-Driven Tests
@Test(dataProvider = "FlightData") public void testFlightBooking(String source, String destination, String depart, String return) { driver.findElement(By.id("from")).sendKeys(source); driver.findElement(By.id("to")).sendKeys(destination); // Add assertions and logic }
Data-Driven Framework in Selenium: Full Code
POM File (pom.xml)
<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.selenium.test</groupId>
<artifactId>selenium-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<!-- Selenium 4 dependency -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.9.1</version>
</dependency>
<!-- WebDriverManager for automatic driver management -->
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>5.3.2</version>
</dependency>
<!-- TestNG for running tests -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.4.0</version>
<scope>test</scope>
</dependency>
<!-- Apache Commons IO for file operations (screenshots) -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Maven Surefire Plugin to run TestNG tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
<!-- Maven Exec Plugin to run tests via TestNG if needed -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<includeTestClasspath>true</includeTestClasspath>
<mainClass>org.testng.TestNG</mainClass>
<arguments>
<argument>-testclass</argument>
<argument>com.selenium.test.DataDrivenTest</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</project>
TestNG XML (testng.xml)
<suite name="FlightBookingSuite">
<test name="DataDrivenTests">
<classes>
<class name="com.selenium.test.DataDrivenTest"/>
</classes>
</test>
</suite>
Java Code (DataDrivenTest.java)
package com.selenium.test;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;
public class DataDrivenTest {
WebDriver driver;
WebDriverWait wait;
// URL of the test page (publicly hosted, e.g., on Glitch/Vercel)
String testPageUrl = "https://flight-booking-test.glitch.me/";
// List to keep screenshot summary (success/failure per iteration)
List<String> screenshotSummary = new ArrayList<>();
@BeforeClass
public void setUp() {
System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriver");
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
driver = new ChromeDriver(options);
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
wait = new WebDriverWait(driver, Duration.ofSeconds(10));
}
@DataProvider(name = "FlightBookingData")
public Object[][] getFlightBookingData() throws IOException {
String csvFile = System.getProperty("user.dir") + "/src/test/resources/flightData.csv";
BufferedReader br = new BufferedReader(new FileReader(csvFile));
String line;
List<Object[]> data = new ArrayList<>();
// Read header line
br.readLine();
int expectedColumns = 9;
while ((line = br.readLine()) != null) {
if (line.trim().isEmpty()) {
continue; // Skip empty lines
}
String[] fields = line.split(",");
if (fields.length < expectedColumns) {
System.err.println("Skipping incomplete row: " + line);
continue;
}
for (int i = 0; i < fields.length; i++) {
fields[i] = fields[i].trim();
}
data.add(fields);
}
br.close();
return data.toArray(new Object[0][]);
}
@Test(dataProvider = "FlightBookingData")
public void flightDeals(String source, String destination, String departDate, String returnDate,
String ticketClass, String passengerName, String email, String passport, String cardNumber) {
try {
// Reset the test page before each iteration
driver.get(testPageUrl);
// --- Flight Search ---
WebElement fromInput = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("from")));
fromInput.clear();
fromInput.sendKeys(source);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("fromSuggestions")));
driver.findElement(By.id("fromSuggestions")).findElement(By.tagName("div")).click();
WebElement toInput = driver.findElement(By.id("to"));
toInput.clear();
toInput.sendKeys(destination);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("toSuggestions")));
driver.findElement(By.id("toSuggestions")).findElement(By.tagName("div")).click();
driver.findElement(By.id("depart")).clear();
driver.findElement(By.id("depart")).sendKeys(departDate);
driver.findElement(By.id("return")).clear();
driver.findElement(By.id("return")).sendKeys(returnDate);
driver.findElement(By.id("ticketClass")).sendKeys(ticketClass);
driver.findElement(By.id("searchFlights")).click();
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("flightResults")));
System.out.println("Flight search successful for " + source + " -> " + destination);
// --- Flight Selection ---
driver.findElement(By.id("selectFlight")).click();
// --- Passenger Details ---
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("passengerForm")));
driver.findElement(By.id("name")).clear();
driver.findElement(By.id("name")).sendKeys(passengerName);
driver.findElement(By.id("email")).clear();
driver.findElement(By.id("email")).sendKeys(email);
driver.findElement(By.id("passport")).clear();
driver.findElement(By.id("passport")).sendKeys(passport);
driver.findElement(By.id("proceedToPayment")).click();
// --- Payment Details ---
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("paymentContainer")));
driver.findElement(By.id("cardNumber")).clear();
driver.findElement(By.id("cardNumber")).sendKeys(cardNumber);
driver.findElement(By.id("confirmBooking")).click();
// --- Booking Confirmation ---
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("confirmationContainer")));
// Wait an extra few seconds to let the final ticket message fully render
Thread.sleep(3000);
String confirmationText = driver.findElement(By.id("bookingReference")).getText();
System.out.println("Booking confirmed for " + passengerName + ": " + confirmationText);
Assert.assertTrue(confirmationText.contains("Booking Reference"), "Booking reference not found.");
captureScreenshot(passengerName + "_SUCCESS");
} catch (Exception e) {
System.err.println("Test failed for booking from " + source + " to " + destination + ": " + e.getMessage());
captureScreenshot(passengerName + "_FAIL");
Assert.fail("Test failed: " + e.getMessage());
}
}
// Helper method to capture a screenshot and save it to a file
public void captureScreenshot(String identifier) {
try {
File srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String screenshotDir = System.getProperty("user.dir") + "/screenshots/";
new File(screenshotDir).mkdirs();
String destPath = screenshotDir + identifier + "_" + timestamp + ".png";
FileUtils.copyFile(srcFile, new File(destPath));
screenshotSummary.add(destPath);
System.out.println("Screenshot saved: " + destPath);
} catch (Exception e) {
System.err.println("Failed to capture screenshot: " + e.getMessage());
}
}
@AfterClass
public void tearDown() {
if (driver != null) {
driver.quit();
}
System.out.println("=== Screenshot Summary ===");
for (String path : screenshotSummary) {
System.out.println(path);
}
}
}
Testing and Test Execution Steps
We are using the following demo site to simulate flight booking using the above Java code.
https://flight-booking-test.glitch.me/
And, the following is the CSV file (flightData.csv) used to pass parameters to our data-driven framework built using Selenium 4 in Java.
source,destination,departDate,returnDate,ticketClass,passengerName,email,passport,cardNumber
New York,Los Angeles,2025-03-15,2025-03-22,Business,John Doe,john@example.com,A12345678,4111111111111111
Chicago,Miami,2025-04-01,2025-04-10,Economy,Jane Smith,jane@example.com,B98765432,4111111111111111
To run the above tests, you must have the following components installed on your system:
- The Chrome Browser
- A Compatible ChromeDriver
- MVN Build Tool
- OpenJDK 17
Use the following directory structure to place the project files.

Next, to run the above project, issue the following commands.
# To build the project (Sometimes only this cone command does the needful)
$ mvn clean install
# To run the tests
$ mvn exec:java
Best Practices for Data-Driven Testing
- Use unique datasets to avoid false positives.
- Parameterize locators for cross-browser compatibility.
- Log results with screenshots on failure.
- Combine with Page Object Model for cleaner code.
FAQ: Data-Driven Framework in Selenium
Q: How does data-driven testing differ from keyword-driven testing?
A: Data-driven focuses on multiple datasets; keyword-driven uses action keywords.
Q: Can I use Excel instead of CSV?
A: Yes! Use Apache POI for Excel integration.
Conclusion: Mastering Data-Driven Testing in Selenium
Mastering the data-driven framework in Selenium empowers you to automate complex workflows efficiently. By leveraging data-driven testing in Selenium, you’ll reduce code duplication, improve maintainability, and scale tests effortlessly.
🚀 Pro Tip: Add parallel testing using TestNG’s parallel="methods"
to slash execution time!
📢 Found this helpful? Share this guide with your network or tag a QA engineer!