Inline Object[][] works for 5-10 rows. But when you have 50+ test data combinations, or when the business team needs to add test cases, you move data to external files. CSV is the simplest format — just commas and newlines. No libraries needed. Every spreadsheet app can export CSV. And it plays nicely with Git version control.
Create a folder src/test/resources/test-data/ in your project. This is the standard location for test data files.
searchTerm,expectResults,minCount
laptop,true,3
headphones,true,2
smartphone,true,5
xyznoexist,false,0
,false,0
LAPTOP,true,3
"laptop case",true,1
<script>alert(1)</script>,false,0import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.Assert;
public class ShoppingSearchCsvTest extends BaseTest {
@DataProvider(name = "searchDataFromCsv")
public Object[][] readSearchData() throws IOException {
List<Object[]> data = new ArrayList<>();
String csvFile = "src/test/resources/test-data/search-terms.csv";
try (BufferedReader br = new BufferedReader(
new FileReader(csvFile))) {
String line;
boolean isHeader = true;
while ((line = br.readLine()) != null) {
// Skip the header row
if (isHeader) {
isHeader = false;
continue;
}
// -1 keeps trailing empty strings
String[] values = line.split(",", -1);
String searchTerm = values[0];
boolean expectResults = Boolean.parseBoolean(values[1]);
int minCount = Integer.parseInt(values[2]);
data.add(new Object[] {
searchTerm, expectResults, minCount
});
}
}
return data.toArray(new Object[0][]);
}
@Test(dataProvider = "searchDataFromCsv")
public void testShoppingSearch(String searchTerm,
boolean expectResults,
int minCount) {
navigateTo("/shopping");
ShopHomePage homePage = new ShopHomePage(driver);
CatalogPage catalog = homePage.searchFor(searchTerm);
if (expectResults) {
Assert.assertTrue(catalog.getProductCount() >= minCount,
"Search for '" + searchTerm
+ "' should return at least " + minCount
+ " results but got " + catalog.getProductCount());
} else {
Assert.assertTrue(
catalog.isNoResultsDisplayed()
|| catalog.getProductCount() == 0,
"Search for '" + searchTerm
+ "' should return no results");
}
}
}The split(",", -1) is critical. Without -1, if your last column is empty (like an empty searchTerm), Java drops it silently. You get an ArrayIndexOutOfBoundsException and waste an hour debugging. Always use -1 with split.
Q: How do you read test data from a CSV file in your framework?
A: I use BufferedReader to read the CSV file line by line. I skip the header row, split each line by comma using split(",", -1) to preserve empty values, parse the values into the correct types, and collect them into a List<Object[]>. The DataProvider method converts this List to Object[][] and returns it. For CSV files with commas inside values, I use OpenCSV library instead of manual splitting.
Keep your CSV files in src/test/resources/test-data/. This folder gets included in the classpath automatically by Maven. Name files descriptively: login-data.csv, search-terms.csv, transfer-scenarios.csv.
Key Point: CSV is the simplest external data source. Use split(",", -1) to avoid losing empty values.