Files
english/.opencode/skills/web-testing/references/test-data-management.md
2026-04-12 01:06:31 +07:00

132 lines
2.9 KiB
Markdown

# Test Data Management
## Faker.js (Dynamic Data Generation)
```typescript
import { faker } from '@faker-js/faker';
// Reproducible data (seeding)
faker.seed(123);
const user = {
id: faker.string.uuid(),
name: faker.person.fullName(),
email: faker.internet.email(),
avatar: faker.image.avatar(),
createdAt: faker.date.past(),
};
```
## Factory Pattern (Fishery)
```typescript
import { Factory } from 'fishery';
import { faker } from '@faker-js/faker';
// Define factory
const userFactory = Factory.define<User>(() => ({
id: faker.string.uuid(),
name: faker.person.fullName(),
email: faker.internet.email(),
role: 'user',
}));
// Usage
const user = userFactory.build();
const admin = userFactory.build({ role: 'admin' });
const users = userFactory.buildList(5);
```
## Factory with Associations
```typescript
const postFactory = Factory.define<Post>(({ associations }) => ({
id: faker.string.uuid(),
title: faker.lorem.sentence(),
author: associations.author || userFactory.build(),
}));
const post = postFactory.build({
author: userFactory.build({ role: 'admin' }),
});
```
## Fixtures (Static Baseline Data)
```typescript
// fixtures/users.ts
export const testUsers = {
admin: {
id: 'admin-001',
email: 'admin@test.com',
role: 'admin',
},
member: {
id: 'member-001',
email: 'member@test.com',
role: 'member',
},
};
// In tests
import { testUsers } from './fixtures/users';
```
## Combined Pattern (Fixtures + Factories)
```typescript
// Baseline fixtures for known states
const baseUser = testUsers.admin;
// Factory for dynamic variations
const dynamicUser = userFactory.build({
...baseUser,
email: faker.internet.email(), // Override specific fields
});
```
## Database Seeding
```typescript
// seed.ts
async function seedTestData(db: Database, workerIndex: number) {
// Worker-isolated data
const prefix = `w${workerIndex}`;
await db.users.insertMany([
{ id: `${prefix}-user-1`, email: `user1-${prefix}@test.com` },
{ id: `${prefix}-user-2`, email: `user2-${prefix}@test.com` },
]);
}
async function clearTestData(db: Database, workerIndex: number) {
const prefix = `w${workerIndex}`;
await db.users.deleteMany({ id: { $regex: `^${prefix}` } });
}
```
## Best Practices
- **Reproducibility:** Seed Faker for consistent test data
- **Isolation:** Prefix data with worker index for parallelism
- **Cleanup:** Always clean up in afterEach/afterAll
- **Minimal data:** Only create what's needed for test
- **Type safety:** Type your factories
## Anti-Patterns
```typescript
// BAD: Hardcoded values
const user = { email: 'test@test.com' }; // Collisions!
// GOOD: Dynamic generation
const user = { email: faker.internet.email() };
// BAD: Shared mutable state
let globalUser;
beforeAll(() => { globalUser = createUser(); });
// GOOD: Fresh data per test
beforeEach(() => { user = userFactory.build(); });
```