From harness-claude
Builds maintainable test data using factory functions, builders, and faker.js for unit/integration tests, reducing duplication and generating realistic data for edge cases.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Build maintainable test data using factory functions, builders, and faker.js
Generates realistic test data, fixtures, factories, seeds, and edge cases using Faker.js, Fishery, pytest fixtures for JS/TS/Python apps and databases.
Generates realistic, consistent test data using factories, fixtures, builders, and faker libraries for unit/integration tests, mocks, seeds, and edge cases.
Establishes patterns for test factories, fixtures, database seeding, and test data isolation to create realistic, composable data without coupling tests to database states.
Share bugs, ideas, or general feedback.
Build maintainable test data using factory functions, builders, and faker.js
function createUser(overrides?: Partial<User>): User {
return {
id: crypto.randomUUID(),
name: 'Test User',
email: `user-${crypto.randomUUID().slice(0, 8)}@test.com`,
role: 'user',
createdAt: new Date(),
...overrides,
};
}
// Usage
const admin = createUser({ role: 'admin', name: 'Admin' });
const alice = createUser({ name: 'Alice' });
import { faker } from '@faker-js/faker';
function createUser(overrides?: Partial<User>): User {
return {
id: faker.string.uuid(),
name: faker.person.fullName(),
email: faker.internet.email(),
role: 'user',
avatar: faker.image.avatar(),
createdAt: faker.date.past(),
...overrides,
};
}
class UserBuilder {
private data: Partial<User> = {};
withName(name: string): this {
this.data.name = name;
return this;
}
withRole(role: Role): this {
this.data.role = role;
return this;
}
withEmail(email: string): this {
this.data.email = email;
return this;
}
asAdmin(): this {
this.data.role = 'admin';
return this;
}
build(): User {
return createUser(this.data);
}
}
// Usage
const admin = new UserBuilder().withName('Alice').asAdmin().build();
function createPost(
overrides?: Partial<Post> & { author?: Partial<User> }
): Post & { author: User } {
const author = createUser(overrides?.author);
return {
id: crypto.randomUUID(),
title: faker.lorem.sentence(),
content: faker.lorem.paragraphs(3),
authorId: author.id,
published: false,
createdAt: new Date(),
...overrides,
author,
};
}
function createUsers(count: number, overrides?: Partial<User>): User[] {
return Array.from({ length: count }, () => createUser(overrides));
}
const tenAdmins = createUsers(10, { role: 'admin' });
faker.seed(42); // Same seed = same data every run
function createDeterministicUser(): User {
return createUser(); // Always generates the same sequence
}
async function createDbUser(prisma: PrismaClient, overrides?: Partial<User>) {
const data = createUser(overrides);
return prisma.user.create({
data: {
email: data.email,
name: data.name,
role: data.role,
},
});
}
// In tests
const user = await createDbUser(prisma, { role: 'admin' });
// test/factories/index.ts
export { createUser, createUsers, UserBuilder } from './user-factory';
export { createPost, createPosts } from './post-factory';
export { createOrder } from './order-factory';
Test factories centralize test data creation, providing consistent defaults while allowing per-test customization. They eliminate the "copy-paste test setup" anti-pattern.
Factory vs fixture vs seed:
Faker.js tips:
faker.seed(n) makes all subsequent calls deterministic — use for reproducible testsfaker.helpers.arrayElement(['a', 'b', 'c']) picks randomly from a listfaker.helpers.multiple(fn, { count: 5 }) generates multiple valuesFactory design principles:
Trade-offs: