Test Data Management
Most flaky and failing suites are really test data problems. Good data management makes tests independent and repeatable.
On this page · 5 min · Intermediate
On this page
- Learning objectives
- Explanation
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Intermediate
- Updated
- Oct 29, 2026
Related tutorials
Learning objectives#
- Create unique data per test
- Use builders and factories
- Seed data through APIs instead of the UI
- Clean up and isolate environments
Explanation#
Each test should create its own data (unique emails, product names) so tests can run in parallel and in any order.
Builders/factories produce valid objects with sensible defaults; tests override only what matters.
Seed data through APIs or SQL — faster and more reliable than clicking through the UI.
Never depend on production data. Keep credentials and URLs in environment config.
Code example: A data factory for tests#
import { randomUUID } from 'node:crypto';
import type { APIRequestContext } from '@playwright/test';
export function aCustomer(overrides: Partial<{ name: string; email: string }> = {}) {
const id = randomUUID().slice(0, 8);
return { name: `Test User ${id}`, email: `qa+${id}@example.com`, password: 'Passw0rd!', ...overrides };
}
export async function createCustomer(request: APIRequestContext, overrides = {}) {
const customer = aCustomer(overrides);
const res = await request.post('/api/test-support/customers', { data: customer });
if (!res.ok()) throw new Error(`Seeding failed: ${res.status()}`);
return { ...customer, id: (await res.json()).id as number };
}
// In a test:
// const asha = await createCustomer(request, { name: 'Asha' });
// ...test... then await request.delete(`/api/test-support/customers/${asha.id}`);
Every test gets its own customer with a unique email, created in milliseconds through the API.
This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.
Step-by-step explanation#
- randomUUID makes names and emails unique.
- Defaults keep tests short; overrides express intent.
- A test-only API seeds data quickly.
- Tests delete what they created.
Real-world use case#
Parallel test runs stop colliding because no two tests share the same account.
Common mistakes#
Parallel tests change each other’s state.
Slow and flaky. Use APIs or SQL.
Best practices#
- Unique data per test
- Builders with defaults
- Seed via API/SQL
- Protect test-support endpoints from production
Remember this#
Own your data per test.
Builders: defaults + overrides.
Seed by API, not by clicking.
Practice exercise#
Your task: Why should test-support endpoints be disabled in production?
Show solution
They bypass normal rules (e.g. create users directly) and would be a security hole.
Mini quiz#
What makes tests safe to run in parallel?
Want more? Practise all Automation Testing MCQs · Automation Testing interview questions
My notes#
Saved in this browser.