</>

Technology

Playwright

Difficulty

Intermediate

Interview Question

How do you implement data-driven testing in Playwright?

Answer

Data-Driven Testing in Playwright

Method 1 — test.each() (Parameterized Tests)

TypeScript
import { test, expect } from '@playwright/test';

// Array of test cases
const loginCases = [
  { email: 'user@test.com',  password: 'pass123',   expected: '/dashboard', desc: 'valid user' },
  { email: 'admin@test.com', password: 'admin123',  expected: '/admin',     desc: 'admin user' },
  { email: 'wrong@test.com', password: 'wrongpass', expected: '/login',     desc: 'invalid user' },
];

for (const { email, password, expected, desc } of loginCases) {
  test(`login: ${desc}`, async ({ page }) => {
    await page.goto('/login');
    await page.getByLabel('Email').fill(email);
    await page.getByLabel('Password').fill(password);
    await page.getByRole('button', { name: 'Sign in' }).click();
    await expect(page).toHaveURL(expected);
  });
}

Method 2 — Dynamic Test from JSON File

TypeScript
// test-data/users.json
// [{"role":"admin","email":"admin@t.com","password":"admin123"},...]

import userData from '../test-data/users.json';

for (const user of userData) {
  test(`login as ${user.role}`, async ({ page }) => {
    await page.goto('/login');
    await page.getByLabel('Email').fill(user.email);
    await page.getByLabel('Password').fill(user.password);
    await page.getByRole('button', { name: 'Sign in' }).click();
    await expect(page).toHaveURL(`/${user.role}`);
  });
}

Method 3 — CSV Data

TypeScript
import * as fs from 'fs';
import * as path from 'path';

function readCSV(filePath: string): Record<string, string>[] {
  const content = fs.readFileSync(filePath, 'utf-8');
  const lines = content.trim().split('\n');
  const headers = lines[0].split(',');
  return lines.slice(1).map(line => {
    const values = line.split(',');
    return Object.fromEntries(headers.map((h, i) => [h.trim(), values[i]?.trim()]));
  });
}

const testData = readCSV(path.join(__dirname, '../test-data/products.csv'));

for (const row of testData) {
  test(`search for ${row.productName}`, async ({ page }) => {
    await page.goto('/');
    await page.getByRole('searchbox').fill(row.productName);
    await page.getByRole('button', { name: 'Search' }).click();
    await expect(page.locator('.result-count')).toContainText(`${row.expectedCount} results`);
  });
}

Method 4 — Form Validation Data-Driven

TypeScript
const formErrors = [
  { field: 'email',    value: '',              error: 'Email is required' },
  { field: 'email',    value: 'not-an-email',  error: 'Invalid email format' },
  { field: 'password', value: '123',           error: 'Password too short' },
  { field: 'phone',    value: 'abc',           error: 'Invalid phone number' },
];

for (const { field, value, error } of formErrors) {
  test(`form validation: ${field} - ${error}`, async ({ page }) => {
    await page.goto('/register');
    await page.getByLabel(field).fill(value);
    await page.getByRole('button', { name: 'Submit' }).click();
    await expect(page.getByText(error)).toBeVisible();
  });
}

Using Environment-Specific Data

TypeScript
// test-data/credentials.ts
export const credentials = {
  staging: { email: 'test@staging.com', password: 'staging123' },
  prod:    { email: 'test@prod.com',    password: 'prod456' },
};

// In test
const env = process.env.TEST_ENV || 'staging';
const creds = credentials[env as 'staging' | 'prod'];

Follow AutomateQA

Related Topics