test-data-builder
Skill0 starsChanged 39 days agoMITView on GitHub
Builds realistic domain fixtures, factories, and edge-case datasets with the builder pattern and valid defaults, so each test owns exactly the data it asserts on. Use when someone asks "how should I set up test data", "my fixtures broke half the suite", "make a factory for this model", "why is this test flaky only in CI", or a test needs domain objects, seed data, or boundary inputs. Do NOT use when a test needs to fake a network call, database client, clock, or third-party SDK - use mock-stub-designer instead; do NOT use for designing the assertions or test cases themselves - use tdd-expert instead.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- imohammadfaraz/claude-skills-for-product-managertheir own version, first seen Nov 1, 2026
- nek1987/auto-agent-harnesstheir own version, first seen Oct 11, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- imohammadfaraz/claude-skills-for-product-manager★ 19same name
- nek1987/auto-agent-harness★ 4same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository8 other files it gives its agents.
- contract-test-writerSkill
- coverage-gap-finderSkill
- e2e-scenario-authorSkill
- flaky-test-detanglerSkill
- mock-stub-designerSkill
- mutation-test-runnerSkill
- playwright-testingSkill
- tdd-expertSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 6 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 86
Do not build elaborate object graphs a test never asserts on - every extra field is a false signal about what the test checks.
- Distinctive: line 87
Do not wrap a one-field value object in a builder.
- Distinctive: line 88
Do not let a builder reach across the boundary to fake network, DB clients, clocks, or third-party SDKs - that is mock-stub-designer's job, …
- Distinctive: line 89
Do not seed randomness from the wall clock or leave it unseeded in CI - an unreproducible flake costs more than the realism buys.
- Distinctive: line 90
Do not "fix" a broken shared fixture by adding another record to it.
- Distinctive: line 94
Every factory's defaults alone produce a valid, persistable object.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Test Data Builder
Produce per-test domain data that is realistic, deterministic, and isolated. The costly failure this prevents is the shared fixture file that becomes an append-only god object: one test tweaks a record, three unrelated tests start flaking, and nobody can delete a fixture row because nobody knows who depends on it. Builders with valid defaults make every test self-describing and every failure reproducible.
Operating procedure
Order matters: defaults must be valid before overrides mean anything, and determinism must be in place before you add realistic randomness.
Step 1: Gather inputs
Collect before writing a factory. Defaults in parentheses; label guesses as guesses.
- The domain object(s) under test and their required fields.
- The stack's factory library (FactoryBot for Ruby, Fishery or test-data-bot for TypeScript, factory_boy for Python, Bogus/AutoFixture for .NET; default: hand-rolled builder if none exists).
- Whether tests touch a real database, and the isolation mechanism available (per-test transaction rollback preferred).
- The invariants a "valid" object must satisfy - validations, foreign keys, non-null constraints.
Step 2: Build per test, never share a global fixture
Construct the objects each test needs inside that test via a factory or builder (FactoryBot, Fishery, test-data-bot, Mother objects). Do not load one static fixture file for the suite - shared mutable fixtures silently couple tests, and the coupling only surfaces as ordering-dependent flakes.
Step 3: Expose a builder with valid defaults; override only what the test cares about
Write aUser().withRole('admin').build() so the override is the test's documentation and the reader ignores the irrelevant fields. Defaults must always produce a valid, persistable object: when a new required field is added to the schema, set it once in the factory and zero unrelated tests break.
Bad - the reader cannot tell which of nine fields the test is actually about, and the next required field breaks this test and forty like it:
const user = new User({
id: 42, name: 'Test User', email: 'test@test.com',
role: 'admin', locale: 'en', createdAt: new Date(),
emailVerified: true, plan: 'free', avatarUrl: null,
})
expect(canDeleteWorkspace(user)).toBe(true)Good - one override, and it is the point of the test:
// user-builder.ts - valid defaults live in exactly one place
export const aUser = () => {
let attrs: UserAttrs = {
id: seq(), name: faker.person.fullName(),
email: faker.internet.email(), role: 'member',
locale: 'en', createdAt: fixedNow, emailVerified: true,
plan: 'free', avatarUrl: null,
}
return {
withRole: (role: Role) => { attrs = { ...attrs, role }; return api },
unverified: () => { attrs = { ...attrs, emailVerified: false }; return api },
build: () => new User(attrs),
}
// (api = the object above; shown flat for brevity)
}
// the test
const admin = aUser().withRole('admin').build()
expect(canDeleteWorkspace(admin)).toBe(true)Step 4: Make data realistic but deterministic
Use Faker (Faker, faker.js, Bogus) for names, emails, and addresses so fixtures resemble production and surface encoding and length bugs that "test" never would. Seed the faker with a fixed seed in CI so a failing run reproduces exactly. The rule: randomness may vary the shape of inputs; it must never decide whether an assertion passes.
Step 5: Build the inputs that break code
Deliberately construct: empty strings, unicode and emoji, very long strings, leading/trailing whitespace, nulls, zero, negative numbers, max integers, timezone-boundary dates, and duplicate keys. For ranges, always build the boundary value and the just-over-boundary value - off-by-one bugs live exactly there. Name each edge-case test after the boundary it exercises. For input spaces too large to enumerate, reach for property-based generators (Hypothesis, fast-check) instead of hand-picking.
Step 6: Keep persistence cheap and isolated
Build in memory by default; only persist (create vs build) when the test needs a real row. Wrap DB-touching tests in a transaction rolled back per test so factories never leak state between tests. Do not rely on sequences or global counters surviving across tests - the suite must pass in any order and in parallel.
Deliverable
Produce, for each domain object under test: a builder or factory whose bare defaults yield a valid persistable object, override methods named for intent (unverified(), withRole()), a seeded-faker configuration for CI, and an edge-case dataset covering the boundaries in Step 5 with each case named for its boundary.
Do NOT
- Do not build elaborate object graphs a test never asserts on - every extra field is a false signal about what the test checks.
- Do not wrap a one-field value object in a builder; a literal is clearer than ceremony.
- Do not let a builder reach across the boundary to fake network, DB clients, clocks, or third-party SDKs - that is mock-stub-designer's job, and mixing the two makes builders untestable.
- Do not seed randomness from the wall clock or leave it unseeded in CI - an unreproducible flake costs more than the realism buys.
- Do not "fix" a broken shared fixture by adding another record to it; migrate the affected tests to builders instead.
Quality bar
- Every factory's defaults alone produce a valid, persistable object.
- A reader can tell what a test asserts from its overrides without opening the factory file.
- The suite passes identically on repeated runs and in any order; no test depends on another's data.
- Edge-case tests name the specific boundary they exercise.
- Adding a required field to the schema touches exactly one factory, zero tests.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

