Intermediate Chapter 12 · 11 min read

Data-Driven Testing

Run the same test with multiple data sets using parameterization, CSV files, JSON fixtures, and dynamic test generation.

Data-Driven API Testing

Data-driven testing runs the same test logic with multiple inputs and expected outputs. Instead of writing separate tests for each scenario, you define a dataset and let the framework iterate through it.

Approaches

You can parameterize tests with inline data, external JSON/CSV files, or dynamically generated test data. Each approach has trade-offs between simplicity, maintainability, and flexibility.

When to Use

Data-driven testing shines when you need to validate the same endpoint with many input combinations: different user types, various field values, boundary conditions, or locale-specific data.

data-driven.test.js
// Inline parameterized tests
const testCases = [
  { id: 1, expectedUserId: 1 },
  { id: 5, expectedUserId: 1 },
  { id: 11, expectedUserId: 2 },
  { id: 51, expectedUserId: 6 },
  { id: 100, expectedUserId: 10 }
];

for (const tc of testCases) {
  const resp = await fetch(
    `https://jsonplaceholder.typicode.com/posts/${tc.id}`
  );
  const post = await resp.json();
  console.assert(
    post.userId === tc.expectedUserId,
    `Post ${tc.id} should belong to user ${tc.expectedUserId}`
  );
}
console.log(`Validated ${testCases.length} posts`);

// Data from external JSON
const userTests = [
  { name: 'Leanne Graham', email: 'Sincere@april.biz' },
  { name: 'Ervin Howell', email: 'Shanna@melissa.tv' },
  { name: 'Clementine Bauch', email: 'Nathan@yesenia.net' }
];

const usersResp = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await usersResp.json();

for (const tc of userTests) {
  const user = users.find(u => u.name === tc.name);
  console.assert(user, `User "${tc.name}" should exist`);
  console.assert(user.email === tc.email, `Email should match for ${tc.name}`);
}

// CRUD test with multiple payloads
const createPayloads = [
  { title: 'First Post', body: 'Content 1', userId: 1 },
  { title: 'Second Post', body: 'Content 2', userId: 2 },
  { title: 'With Unicode: cafe\u0301', body: '\u2603', userId: 3 }
];

for (const payload of createPayloads) {
  const resp = await fetch('https://jsonplaceholder.typicode.com/posts', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload)
  });
  console.assert(resp.status === 201, `Create failed for: ${payload.title}`);
}
console.log('All data-driven tests passed!');
DataDrivenTest.java
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.Assert;

public class DataDrivenTest {

    private static final String BASE = "https://jsonplaceholder.typicode.com";

    @DataProvider(name = "postData")
    public Object[][] postData() {
        return new Object[][] {
            { 1, 1 },      // postId, expectedUserId
            { 5, 1 },
            { 11, 2 },
            { 51, 6 },
            { 100, 10 }
        };
    }

    @Test(dataProvider = "postData")
    public void testPostBelongsToUser(int postId, int expectedUserId) {
        given().baseUri(BASE)
        .when().get("/posts/" + postId)
        .then()
            .statusCode(200)
            .body("userId", equalTo(expectedUserId));
    }

    @DataProvider(name = "userData")
    public Object[][] userData() {
        return new Object[][] {
            { "Leanne Graham", "Sincere@april.biz" },
            { "Ervin Howell", "Shanna@melissa.tv" },
            { "Clementine Bauch", "Nathan@yesenia.net" }
        };
    }

    @Test(dataProvider = "userData")
    public void testUserDetails(String name, String email) {
        given().baseUri(BASE)
            .queryParam("name", name)
        .when().get("/users")
        .then()
            .statusCode(200)
            .body("[0].email", equalTo(email));
    }

    @DataProvider(name = "createPayloads")
    public Object[][] createPayloads() {
        return new Object[][] {
            { "First Post", "Content 1", 1 },
            { "Second Post", "Content 2", 2 },
            { "Unicode Post \u2603", "Body \u2603", 3 }
        };
    }

    @Test(dataProvider = "createPayloads")
    public void testCreatePost(String title, String body, int userId) {
        String payload = String.format(
            "{\"title\": \"%s\", \"body\": \"%s\", \"userId\": %d}",
            title, body, userId
        );

        given().baseUri(BASE)
            .contentType("application/json")
            .body(payload)
        .when().post("/posts")
        .then()
            .statusCode(201)
            .body("title", equalTo(title));
    }
}
test_data_driven.py
import requests
import pytest

BASE_URL = 'https://jsonplaceholder.typicode.com'

# Inline parameterization with pytest
@pytest.mark.parametrize('post_id, expected_user_id', [
    (1, 1),
    (5, 1),
    (11, 2),
    (51, 6),
    (100, 10),
])
def test_post_belongs_to_user(post_id, expected_user_id):
    response = requests.get(f'{BASE_URL}/posts/{post_id}')
    assert response.status_code == 200
    assert response.json()['userId'] == expected_user_id

@pytest.mark.parametrize('name, email', [
    ('Leanne Graham', 'Sincere@april.biz'),
    ('Ervin Howell', 'Shanna@melissa.tv'),
    ('Clementine Bauch', 'Nathan@yesenia.net'),
])
def test_user_details(name, email):
    response = requests.get(f'{BASE_URL}/users', params={'name': name})
    users = response.json()
    assert len(users) > 0
    assert users[0]['email'] == email

@pytest.mark.parametrize('payload', [
    {'title': 'First Post', 'body': 'Content 1', 'userId': 1},
    {'title': 'Second Post', 'body': 'Content 2', 'userId': 2},
    {'title': 'Unicode Post \u2603', 'body': '\u2603', 'userId': 3},
])
def test_create_post(payload):
    response = requests.post(f'{BASE_URL}/posts', json=payload)
    assert response.status_code == 201
    assert response.json()['title'] == payload['title']

# Data from external file (conftest.py fixture)
# @pytest.fixture
# def test_data():
#     import json
#     with open('test_data/users.json') as f:
#         return json.load(f)

API Testing Intermediate Data-Driven Testing

Written by PV

© 2026 All Rights Reserved