Test Data and Fixtures
Mission
Create project test data that is deterministic, realistic where it matters, free of production residue, and regenerable on demand. Test data is committed infrastructure, not an ad hoc side effect: every fixture is authored against truth, checked for hygiene, and owned by the team that maintains it.
Match the fixture to the system's failure modes. Static seeds fit CRUD flows, factories fit variation-heavy logic, fake services fit integration seams, cassettes fit external API consumers, synthetic datasets fit volume and distribution work. Per-system-type test strategy is the quality-engineer skill's domain, and sandbox route design belongs to sandbox-experience; this skill produces the data those strategies consume.
Read references/standards.md for the canonical thresholds, severity vocabulary, and release gates.
Fixture authoring
The project test-data create pattern: scope the tree, choose the types, author from truth, keep deterministic, sanitize, verify, and wire regeneration.
1. Scope the fixture tree
Choose one canonical test-data location per repository: testdata/, fixtures/, or tests/fixtures/. Put factories and generators beside the fixtures in test support, never in production code.
Rules:
- one location, stable names, one owner
- never ship fixtures in production builds or read them from application runtime paths
- never commit test data the application would treat as real at runtime
- name files by role (
users_seed.csv, orders_seed.json), not by author or date
- a fixture without a documented regeneration path is a liability
2. Choose the fixture type by need
| Need |
Type |
| fixed, versionable baseline data |
static fixture files |
| per-test variation over a shared shape |
factories |
| canonical reference rows for local dev and CI |
seed data |
| replace a dependency at an integration seam |
fake services / mock servers |
| capture and replay external API interactions |
record-replay cassettes |
| expected output for formatters, compilers, report generators |
golden files |
| volume, distribution, or privacy-free realism |
synthetic datasets |
| real behavior with real data removed |
sanitized production snapshots |
Read references/factories-and-seeds.md when writing factories or seed data. Read references/mock-servers.md when deciding between a fake, a mock, or a recorded dependency. Read references/record-replay.md when capturing external API interactions. Read references/golden-files.md when snapshotting expected output. Read references/synthetic-datasets.md when generating data at volume. Read references/sanitization.md before any fixture that touches real data.
3. Author from truth
Ground every fixture in the real schema, API contract, or spec:
- Read the schema or contract first; never invent fields, defaults, or enums.
- Use real shapes with realistic but safe values.
- Keep each fixture minimal: only the data the test path needs.
- Reference shared constants from one source; do not duplicate values by hand.
- Make failure cases explicit fixtures, not mutations of happy-path data.
4. Keep fixtures deterministic
- fix every seed, timestamp, and generated identifier
- random variation is explicit and seeded, never implicit
- committed fixtures do not depend on wall clock, hostname, locale, or database ordering
- expected values are asserted against the fixture, not computed from live state
- document the generation command so regeneration reproduces the same bytes
5. Sanitize anything that touches real data
Before a fixture can include production-derived data, run the procedure in references/sanitization.md: inventory PII and secrets, replace with safe equivalents, preserve distributional realism where the tests need it, verify no original value survives, and record the sanitization in the report. A fixture containing a real email, key, card number, or production marker is a hygiene failure, not a test asset.
6. Verify hygiene
Run scripts/check_fixture_hygiene.py <tree> before committing and on every relevant change. The checker scans for real-looking email addresses, key-like strings, credit-card patterns, and unsanitized production markers, and exits 1 on any finding. Zero findings is the contract; an exception requires a filed hygiene record, never a silent skip.
7. Wire regeneration and ownership
- commit the generator or the regeneration command with the fixtures
- add a smoke test that fails when a fixture drifts from its schema
- record owner and update cadence in the report
- when a golden file changes, review the change; regenerating to silence a review is a defect
Fixture contract
A fixture is correct when:
- it matches the schema or contract it feeds, including nullability and constraints
- it is deterministic and regenerable from a documented command
- it contains no real emails, keys, secrets, card numbers, or production markers
- its purpose is named and discoverable from the tree
- consumers reference the canonical tree, not copies
Factory contract
- one factory per domain shape, with a single source of truth for defaults
- defaults are valid, safe, and deterministic; overrides are explicit arguments
- factory-produced values never contain real personal data or secrets
- randomized fields use a seeded RNG with a documented seed
- factories live in test support, never in production code paths
Mock server contract
Read references/mock-servers.md.
A fake service or mock server must:
- mimic documented behavior and error semantics, not incidental implementation
- cover the success path and the failure paths the consumer handles
- hold no real credentials; auth is simulated
- be started and stopped by the test harness, never by external convention
- prefer a fake with real behavior over a mock with canned responses when the seam allows
Record-replay contract
Read references/record-replay.md.
Cassettes must:
- be captured against a sandbox or test environment, never production
- be scrubbed of secrets, tokens, and personal data before commit
- carry the recorded date and provider version so staleness is visible
- be re-recorded deliberately when the contract changes, never silently
- not be used to assert exact bytes unless byte-exactness is the contract
Golden file contract
Read references/golden-files.md.
Golden files must:
- be produced by a committed generator, with the generation command documented
- change only through regeneration, reviewed as a diff
- be updated in the same change as the code that alters the output
- have a stated update policy (auto-bless vs. human-reviewed) per directory
- never be hand-edited to pass; hand-editing a golden file hides drift
Required output
For every fixture-authoring task, produce:
- Fixture tree — the created or updated files, scoped and named per step 1
- Hygiene check —
scripts/check_fixture_hygiene.py output with zero findings, or a filed exception
- Regeneration path — the command that reproduces the fixtures, with owner
- Sanitization record — for any real-data source: the source, the transforms applied, and how the original values were verified absent
- Report —
assets/fixture-report-template.md filled in for large or cross-cutting work
Definition of done
Fixture authoring is done when:
- every fixture is grounded in schema or contract truth
- the tree is scoped to one canonical location with named roles and an owner
- committed fixtures are deterministic and regenerable from a documented command
- the hygiene checker passes with zero findings
- real-data fixtures carry a sanitization record
- consumers reference the canonical tree; no copies drift
- golden files change only through reviewed regeneration
- cross-skill boundaries are respected:
sandbox-experience owns sandbox route design, quality-engineer owns per-system-type test strategy, and this skill owns the data itself
1---2name: test-data-and-fixtures3description: Author fixtures, seed data, factories, fake services, mock servers, record-replay cassettes, golden files, synthetic datasets, and sanitization, with a project test-data create pattern. For sandbox route design use sandbox-experience; for per-system-type test strategy use quality-engineer.4license: MIT5---67# Test Data and Fixtures89## Mission1011Create project test data that is deterministic, realistic where it matters, free of production residue, and regenerable on demand. Test data is committed infrastructure, not an ad hoc side effect: every fixture is authored against truth, checked for hygiene, and owned by the team that maintains it.1213Match the fixture to the system's failure modes. Static seeds fit CRUD flows, factories fit variation-heavy logic, fake services fit integration seams, cassettes fit external API consumers, synthetic datasets fit volume and distribution work. Per-system-type test strategy is the `quality-engineer` skill's domain, and sandbox route design belongs to `sandbox-experience`; this skill produces the data those strategies consume.1415Read `references/standards.md` for the canonical thresholds, severity vocabulary, and release gates.1617## Fixture authoring1819The project test-data create pattern: scope the tree, choose the types, author from truth, keep deterministic, sanitize, verify, and wire regeneration.2021### 1. Scope the fixture tree2223Choose one canonical test-data location per repository: `testdata/`, `fixtures/`, or `tests/fixtures/`. Put factories and generators beside the fixtures in test support, never in production code.2425Rules:2627- one location, stable names, one owner28- never ship fixtures in production builds or read them from application runtime paths29- never commit test data the application would treat as real at runtime30- name files by role (`users_seed.csv`, `orders_seed.json`), not by author or date31- a fixture without a documented regeneration path is a liability3233### 2. Choose the fixture type by need3435| Need | Type |36|---|---|37| fixed, versionable baseline data | static fixture files |38| per-test variation over a shared shape | factories |39| canonical reference rows for local dev and CI | seed data |40| replace a dependency at an integration seam | fake services / mock servers |41| capture and replay external API interactions | record-replay cassettes |42| expected output for formatters, compilers, report generators | golden files |43| volume, distribution, or privacy-free realism | synthetic datasets |44| real behavior with real data removed | sanitized production snapshots |4546Read `references/factories-and-seeds.md` when writing factories or seed data. Read `references/mock-servers.md` when deciding between a fake, a mock, or a recorded dependency. Read `references/record-replay.md` when capturing external API interactions. Read `references/golden-files.md` when snapshotting expected output. Read `references/synthetic-datasets.md` when generating data at volume. Read `references/sanitization.md` before any fixture that touches real data.4748### 3. Author from truth4950Ground every fixture in the real schema, API contract, or spec:51521. Read the schema or contract first; never invent fields, defaults, or enums.532. Use real shapes with realistic but safe values.543. Keep each fixture minimal: only the data the test path needs.554. Reference shared constants from one source; do not duplicate values by hand.565. Make failure cases explicit fixtures, not mutations of happy-path data.5758### 4. Keep fixtures deterministic5960- fix every seed, timestamp, and generated identifier61- random variation is explicit and seeded, never implicit62- committed fixtures do not depend on wall clock, hostname, locale, or database ordering63- expected values are asserted against the fixture, not computed from live state64- document the generation command so regeneration reproduces the same bytes6566### 5. Sanitize anything that touches real data6768Before a fixture can include production-derived data, run the procedure in `references/sanitization.md`: inventory PII and secrets, replace with safe equivalents, preserve distributional realism where the tests need it, verify no original value survives, and record the sanitization in the report. A fixture containing a real email, key, card number, or production marker is a hygiene failure, not a test asset.6970### 6. Verify hygiene7172Run `scripts/check_fixture_hygiene.py <tree>` before committing and on every relevant change. The checker scans for real-looking email addresses, key-like strings, credit-card patterns, and unsanitized production markers, and exits 1 on any finding. Zero findings is the contract; an exception requires a filed hygiene record, never a silent skip.7374### 7. Wire regeneration and ownership7576- commit the generator or the regeneration command with the fixtures77- add a smoke test that fails when a fixture drifts from its schema78- record owner and update cadence in the report79- when a golden file changes, review the change; regenerating to silence a review is a defect8081## Fixture contract8283A fixture is correct when:8485- it matches the schema or contract it feeds, including nullability and constraints86- it is deterministic and regenerable from a documented command87- it contains no real emails, keys, secrets, card numbers, or production markers88- its purpose is named and discoverable from the tree89- consumers reference the canonical tree, not copies9091## Factory contract9293- one factory per domain shape, with a single source of truth for defaults94- defaults are valid, safe, and deterministic; overrides are explicit arguments95- factory-produced values never contain real personal data or secrets96- randomized fields use a seeded RNG with a documented seed97- factories live in test support, never in production code paths9899## Mock server contract100101Read `references/mock-servers.md`.102103A fake service or mock server must:104105- mimic documented behavior and error semantics, not incidental implementation106- cover the success path and the failure paths the consumer handles107- hold no real credentials; auth is simulated108- be started and stopped by the test harness, never by external convention109- prefer a fake with real behavior over a mock with canned responses when the seam allows110111## Record-replay contract112113Read `references/record-replay.md`.114115Cassettes must:116117- be captured against a sandbox or test environment, never production118- be scrubbed of secrets, tokens, and personal data before commit119- carry the recorded date and provider version so staleness is visible120- be re-recorded deliberately when the contract changes, never silently121- not be used to assert exact bytes unless byte-exactness is the contract122123## Golden file contract124125Read `references/golden-files.md`.126127Golden files must:128129- be produced by a committed generator, with the generation command documented130- change only through regeneration, reviewed as a diff131- be updated in the same change as the code that alters the output132- have a stated update policy (auto-bless vs. human-reviewed) per directory133- never be hand-edited to pass; hand-editing a golden file hides drift134135## Required output136137For every fixture-authoring task, produce:1381391. **Fixture tree** — the created or updated files, scoped and named per step 11402. **Hygiene check** — `scripts/check_fixture_hygiene.py` output with zero findings, or a filed exception1413. **Regeneration path** — the command that reproduces the fixtures, with owner1424. **Sanitization record** — for any real-data source: the source, the transforms applied, and how the original values were verified absent1435. **Report** — `assets/fixture-report-template.md` filled in for large or cross-cutting work144145## Definition of done146147Fixture authoring is done when:148149- every fixture is grounded in schema or contract truth150- the tree is scoped to one canonical location with named roles and an owner151- committed fixtures are deterministic and regenerable from a documented command152- the hygiene checker passes with zero findings153- real-data fixtures carry a sanitization record154- consumers reference the canonical tree; no copies drift155- golden files change only through reviewed regeneration156- cross-skill boundaries are respected: `sandbox-experience` owns sandbox route design, `quality-engineer` owns per-system-type test strategy, and this skill owns the data itself