1. Fixtures β static, shared, declarative
Hand-crafted JSON/YAML describing a known state. Loaded before tests, torn down after.
When to reach for it: Small, stable datasets where readability beats flexibility. Golden paths (a logged-in user, a seeded product catalogue) where every test wants the same starting point.
// fixtures/users.json
[
{ "id": "u-1", "email": "alice@test.dev", "role": "admin" },
{ "id": "u-2", "email": "bob@test.dev", "role": "member" }
]
// In Playwright fixture
import users from './fixtures/users.json';
test.beforeEach(async ({ request }) => {
await request.post('/api/test/seed', { data: { users } });
});
test('admin can delete users', async ({ page }) => {
await loginAs(page, 'alice@test.dev'); // from fixture
// ...
});Trade-off
Readable + shareable across tests. Brittle to schema changes β every time the User model grows a required field, every fixture breaks. Not suitable for dynamic data (timestamps, unique emails).
Common pitfall
Checked into VCS but with production-like data β CSV of 'sample orders' with real customer names or payment card patterns. Scrub anything that resembles PII before commit, even if 'it's only test data'.