Q3 of 17 · Framework design
What is a data-driven testing framework and how do you implement it?
Framework designMidframework-designdata-drivenparameterised-testingtest-data
Short answer
Short answer: A data-driven framework separates test logic from test data. Tests read inputs and expected outputs from an external source (CSV, Excel, JSON, database) and run the same logic for each data row, enabling non-engineers to add test cases without touching code.
Detail
Core idea: the test script is a template; the data file is the input. Adding a new test case means adding a row, not writing code.
Implementation with Playwright + JSON:
// testData/loginTests.json
[
{ "email": "valid@example.com", "password": "correct", "expectedUrl": "/dashboard", "scenario": "valid login" },
{ "email": "valid@example.com", "password": "wrong", "expectedError": "Invalid credentials", "scenario": "wrong password" },
{ "email": "notanemail", "password": "any", "expectedError": "Invalid email format", "scenario": "bad email format" }
]
// login.spec.ts
import testCases from '../testData/loginTests.json';
for (const tc of testCases) {
test(tc.scenario, async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.navigate();
await loginPage.enterEmail(tc.email);
await loginPage.enterPassword(tc.password);
await loginPage.submit();
if (tc.expectedUrl) {
await expect(page).toHaveURL(tc.expectedUrl);
} else {
await expect(loginPage.errorMessage).toHaveText(tc.expectedError);
}
});
}
JUnit 5 — @ParameterizedTest + @CsvSource:
@ParameterizedTest(name = "{2}")
@CsvSource({
"valid@example.com, correct, dashboard",
"valid@example.com, wrong, Invalid credentials",
"notanemail, any, Invalid email format"
})
void loginTests(String email, String password, String expectedOutcome) {
// test logic using the parameters
}
When data-driven shines:
- Boundary value / equivalence partition testing with many input combinations
- Form validation across dozens of field variations
- API contract testing with varied request payloads
Trade-off: When "data" variations also require different test logic, force-fitting into a data-driven approach creates conditional branches inside tests — that's a smell. Use separate tests instead.
// WHAT INTERVIEWERS LOOK FOR
External data source (JSON/CSV/DB), test-as-template structure, example in at least one language. The 'different logic = different test' trade-off.