Answer
Data-Driven API Testing with Rest Assured + TestNG
Data-driven testing runs the same test logic with multiple sets of data, maximizing test coverage with minimal code.
Method 1: @DataProvider with Inline Data
Java
public class DataDrivenUserTest {
@DataProvider(name = "createUserData")
public Object[][] createUserData() {
return new Object[][] {
// name, email, status, expectedCode
{ "John Doe", "john@example.com", "active", 201 },
{ "Jane Smith", "jane@example.com", "active", 201 },
{ "", "invalid", "active", 400 }, // empty name
{ "Alice", "not-an-email", "active", 400 }, // bad email
{ "Bob", "bob@example.com", "invalid", 400 } // bad status
};
}
@Test(dataProvider = "createUserData")
public void testCreateUser(String name, String email, String status, int expectedCode) {
String body = String.format(
"{ \"name\": \"%s\", \"email\": \"%s\", \"status\": \"%s\" }",
name, email, status
);
given()
.contentType(ContentType.JSON)
.body(body)
.when()
.post("/api/users")
.then()
.statusCode(expectedCode);
}
}
Method 2: @DataProvider from CSV File
Java
@DataProvider(name = "csvUserData")
public Object[][] csvUserData() throws IOException {
List<Object[]> data = new ArrayList<>();
try (CSVReader reader = new CSVReader(
new FileReader("src/test/resources/testdata/users.csv"))) {
String[] row;
reader.readNext(); // skip header
while ((row = reader.readNext()) != null) {
data.add(new Object[]{ row[0], row[1], Integer.parseInt(row[2]) });
}
}
return data.toArray(new Object[0][]);
}
// users.csv:
// name,email,expectedStatus
// John,john@test.com,201
// ,invalid,400
Method 3: @DataProvider from JSON File
Java
// testdata/users.json
// [
// { "name": "Alice", "email": "alice@test.com", "expected": 201 },
// { "name": "", "email": "bad", "expected": 400 }
// ]
@DataProvider(name = "jsonUserData")
public Object[][] jsonUserData() throws IOException {
String content = new String(Files.readAllBytes(
Paths.get("src/test/resources/testdata/users.json")));
JSONArray jsonArray = new JSONArray(content);
Object[][] data = new Object[jsonArray.length()][3];
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject obj = jsonArray.getJSONObject(i);
data[i][0] = obj.getString("name");
data[i][1] = obj.getString("email");
data[i][2] = obj.getInt("expected");
}
return data;
}
Method 4: Parallel Data-Driven Tests
Java
@DataProvider(name = "parallelData", parallel = true)
public Object[][] parallelData() {
return new Object[][] {
{ "user1@test.com", 200 },
{ "user2@test.com", 200 },
{ "user3@test.com", 200 }
};
}
@Test(dataProvider = "parallelData")
public void testGetUserByEmail(String email, int expectedCode) {
given()
.queryParam("email", email)
.when()
.get("/api/users/search")
.then()
.statusCode(expectedCode);
}
testng.xml Configuration for Data-Driven
XML
<suite name="API Data-Driven Tests" parallel="tests" thread-count="4">
<test name="User API Tests">
<classes>
<class name="tests.DataDrivenUserTest"/>
</classes>
</test>
</suite>
Test Results View
Running with 5 data sets shows 5 separate results:
CODE
testCreateUser[0] - PASS (John Doe → 201)
testCreateUser[1] - PASS (Jane Smith → 201)
testCreateUser[2] - PASS (empty name → 400)
testCreateUser[3] - PASS (bad email → 400)
testCreateUser[4] - PASS (bad status → 400)
