MCPInstall

test-data-management

Create and manage test data with factory patterns, fixture strategies, data anonymization, and synthetic data generation. Covers Fishery (TypeScript), FactoryBot (Ruby), Factory Boy (Python), database seeding, cleanup strategies, and GDPR-compliant data handling. Use when: "test data," "fixtures," "factories," "seed data," "synthetic data," "test database," "data anonymization." Not for: migration/integrity testing of the DB itself — use database-testing; environment provisioning and database branching strategy — use test-environments. Related: test-environments, database-testing, api-testing, unit-testing.

Installs
1.4K
Last 24h
+13
Trending rank
#7522
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/petrkindlmann/qa-skills --skill test-data-management
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads test-data-management automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

<objective> Create, maintain, and clean up test data that is deterministic, isolated, realistic, and safe. Good test data is the foundation of reliable tests -- without it, tests are either flaky (shared mutable state), unrealistic (hardcoded nonsense values), or dangerous (production PII in test environments). This skill delivers factories, fixtures, idempotent seeds, anonymization pipelines, and cleanup strategies that survive parallel execution. </objective>

Quick Route

SituationGo to
Need fresh entity data with per-test overridesFactory Patterns → references/factories.md
Mocking an API response or golden fileFixture Strategies → references/factories.md
Copying production data anywhere non-prodData Anonymization
Populating a test DB / reference data idempotentlyDatabase Seeding → references/seeding-and-synthetic.md
Cleaning up after tests / parallel isolationCleanup Strategies → references/seeding-and-synthetic.md
Generating edge cases and boundary valuesSynthetic Data → references/seeding-and-synthetic.md

Discovery Questions

Before designing a test data strategy, understand the current state. Check .agents/qa-project-context.md first -- if it exists and is filled in, use it as the foundation and skip questions already answered there; an unfilled template answers nothing, so treat it as absent.

Current Data Practices

  • How is test data created today? (manually, scripts, copy of production, none)
  • Do tests share data or does each test create its own?
  • How is test data cleaned up? (truncate, rollback, manual, never)
  • Are there seed scripts? Are they idempotent?

Privacy and Compliance

  • Does the product handle PII? (names, emails, addresses, phone numbers, SSNs)
  • Are there GDPR, HIPAA, PCI-DSS, or other data protection requirements?
  • Is production data ever used in test environments?

Scale and Complexity

  • How large are the test datasets? (dozens of records, thousands, millions)
  • How complex are the data relationships? (simple CRUD, deep nested hierarchies, polymorphic)
  • Are there cross-service data dependencies? (microservices sharing data)

Core Principles

1. Each Test Owns Its Data

Tests that rely on pre-existing shared data are fragile. When Test A modifies shared data, Test B breaks. Every test should create exactly the data it needs, verify against that data, and clean up after itself. This enables parallel execution and eliminates ordering dependencies.

2. Factories Over Fixtures for Dynamic Data

Static fixtures (JSON/YAML files) are appropriate for reference data that does not change (country codes, currency lists). For entity data that tests create and manipulate (users, orders, products), use factory functions that generate fresh instances with sensible defaults and allow per-test overrides.

3. Anonymize Production Data Before Use

Production databases contain the most realistic data, but they also contain real user information. Never copy production data to test environments without anonymization. Replace PII with synthetic equivalents while preserving data distributions and relationships.

4. Deterministic Data Enables Reproducible Tests

Tests should produce the same results regardless of when or where they run. Avoid Math.random(), Date.now(), or auto-increment IDs in assertions. Use seeded random generators (faker.seed(n)), fixed timestamps, factory sequences, and -- when an ID must be a UUID you assert on -- a seeded faker.string.uuid() so it stays stable across runs. State the factory's promise in the server's canonical form: if the application sorts items by SKU, trims names or lower-cases emails, the promise does the same, or "reads back equal to the promise" fails on a detail the contract does not consider a difference.

5. Minimize Data, Maximize Signal

Create only the data each test needs. A test for user search does not need a complete user profile with billing address, payment method, and order history. Over-specified test data obscures the intent of the test and increases maintenance burden.


Factory Patterns

Factories are functions that produce test data with sensible defaults, allowing individual tests to override only what matters for their scenario. Fishery (2.4.0) is the default for TypeScript, FactoryBot (6.6.0) for Ruby, factory-boy (3.3.3) for Python; all pair with faker (v10.4.0) for realistic field values.

See references/factories.md for the full Fishery (with associations and deterministic UUIDs), FactoryBot (User + Product out_of_stock/discounted traits), Factory Boy (class Params + Trait), and Playwright fixture implementations. The shape every factory follows:

  • Defaults + overrides — Factory.define produces sensible defaults; tests pass overrides for the one field they care about (userFactory.build({ role: 'admin' })).
  • Sequences for unique fields — sequence (Fishery), sequence(:email) (FactoryBot), factory.Sequence (Factory Boy) — never hardcode IDs or emails.
  • Traits for variants — name common states (:admin, :inactive, out_of_stock, discounted) instead of spawning a fixture file per combination.
  • Associations — one factory builds another (an order builds its user), keeping referential structure without manual wiring. When the application cannot create the parent (seeded accounts only, no sign-up API), invert the direction: the factory takes a confirmed parent as input (orderFactory.build({ user })) and never invents one.
  • No library available — none of this needs Fishery or Faker. A seeded generator (hash the test or scope name into a 32-bit seed, step it with a small PRNG such as mulberry32, fork a stream per factory so one factory's extra draw cannot shift another's values) plus a per-factory sequence gives build, buildList, defaults and overrides in about forty lines of plain code. Reach for the library when the realistic field values matter, not for the mechanics.

When to Use Factories vs Fixtures

ScenarioFactoriesStatic Fixtures
Entity data that tests create/modifyYesNo
Reference data (countries, currencies, configs)NoYes
Data with many variations per testYesNo -- file explosion
Data with complex relationshipsYes -- associationsNo -- hard to maintain
API response mocksNoYes -- JSON fixtures
Snapshot/golden file comparisonsNoYes

Decision rule: If the data has a lifecycle (created, modified, deleted during tests), use a factory. If the data is read-only reference material, use a fixture file.


Fixture Strategies

Three fixture shapes, all in references/factories.md:

  • Static fixtures (JSON/YAML) — best for API response mocks (page.route + route.fulfill), config data, and golden file comparisons.
  • Dynamic fixtures (Playwright) — test.extend creates data via API before the test and deletes it after await use(...). The standard per-test setup/teardown.
  • Fixture composition — combine factory-built data (userFactory.build(), orderFactory.buildList(3)) inside a single test.extend that seeds and cleans up in one step.

Data Anonymization

When production data is needed for realistic testing, anonymize it before use.

PII Masking Rules

Data TypeAnonymization MethodExample
EmailFaker email with original domain patternjane.doe@acme.com -> user-7291@test.example.com
Full nameFaker nameJane Doe -> Alice Johnson
Phone numberFaker phone, preserve format+1-555-123-4567 -> +1-555-987-6543
AddressFaker address, preserve country/region123 Main St, NYC -> 456 Oak Ave, NYC
SSN/National IDTest pattern123-45-6789 -> 000-00-0001
Credit cardTest card numbers4111-... -> 4242-4242-4242-4242
Date of birthShift by fixed offset1990-03-15 -> 1987-07-22

The anonymization pipeline -- seeded Faker for determinism, an in-memory lookup table, parent-records-first ordering, and a wrapping transaction -- is in references/seeding-and-synthetic.md (Anonymization with Faker.js, Referential Integrity During Anonymization). Anonymizing a user's email must also update that email everywhere it is referenced (orders, comments, audit logs); process parents first, children second, using the same lookup, all inside one transaction.

GDPR Compliance Checklist

  • No real PII exists in any non-production environment
  • Anonymization is irreversible (no lookup table mapping back to originals is stored)
  • Anonymization preserves data distributions (age ranges, geographic spread) for realistic testing
  • Anonymized data cannot be re-identified through combination of quasi-identifiers
  • Data retention policies apply to test environments (auto-delete after N days)
  • The anonymization pipeline runs automatically, not manually (eliminates human error)

Database Seeding

Idempotent Seed Scripts

Seed scripts must be safe to run multiple times without duplicating data. Use upsert -- INSERT ... ON CONFLICT (natural_key) DO UPDATE SET ... -- keyed on a stable natural key, not the primary key. A DELETE-then-INSERT "reset" is not idempotent: it breaks foreign keys and reassigns serial IDs. See references/seeding-and-synthetic.md (Idempotent Seed Scripts) for the full INSERT ... ON CONFLICT (code) DO UPDATE countries/currencies example and the reasoning.

Database Branching (DB-as-a-Service)

If your prod DB lives on Neon, Supabase, or PlanetScale, branching can give a PR its own database instead of seeding from scratch -- but the providers differ on whether the branch carries data:

  • Neon Branching — copy-on-write Postgres branches in seconds, with data; ideal for ephemeral preview envs. The strongest "PR gets a real DB copy" story.
  • Supabase Branching — supabase branches create pr-123 clones schema and (optionally, from a backup) data; preview env points at the branch URL.
  • PlanetScale Branching — MySQL branches are schema-only by default (no data), so you still seed the branch. Note: PlanetScale removed its free Hobby tier (April 2024); MySQL now starts at ~$39/mo, Postgres ~$5/mo.

Pair with the Preview Environments pattern in test-environments.

Avoid: Snaplet (hosted) — shut down 31 Aug 2024; the team joined Supabase. @snaplet/seed lives on as supabase-community/seed (community-maintained, last meaningful release v0.98.0, July 2024, no feature work since). For new projects, prefer the DB-branching providers above plus factory-generated seeds.

Per-Test vs Per-Suite Data

StrategyWhen to UseProsCons
Per-test setup/teardownTests that modify dataFull isolation, parallel-safeSlower, more setup code
Per-suite seedRead-only reference dataFast, simpleCannot be modified by tests
Per-worker seedPlaywright parallel workersBalances speed and isolationRequires worker-scoped fixtures
Global seedEnvironment bootstrapRuns once, sets up baselineMust be idempotent, shared state risk

For the worker-scoped fixture (test.extend with { scope: 'worker' }) that powers per-worker seeding, see references/factories.md (Worker-Scoped Seeding).

Cleanup Strategies

StrategyWhen to useSpeed
Transaction rollbackUnit/integration tests with direct DB accessFastest
Truncation (TRUNCATE ... CASCADE)Resetting tables between suitesMedium
API-based cleanupE2E tests with no direct DB accessSlowest

Transaction rollback cannot clean up E2E tests -- the app opens its own DB connections, so a test-side transaction can't undo the app's writes; use API-based cleanup (delete in reverse creation order) there. Some systems delete nothing (ledgers, orders, audit records): there the strategy is a fresh instance or namespace per test where the runtime allows it, and otherwise a ledger of every record the application confirmed, assertions scoped to that ledger (own records visible, foreign records never asserted on), and a reconcile step that checks the durable state against baseline plus ledger instead of against an empty table. All three implementations are in references/seeding-and-synthetic.md (Cleanup Strategies).


Synthetic Data Generation

Factories should make it easy to generate edge cases and boundary values without hand-writing them per test. The reusable arrays and helpers -- edgeCaseStrings (empty, whitespace, very long, XSS, SQL injection, null/control chars, RTL override), edgeCaseDates, and boundaryValues(min, max) driving a test.each -- are in references/seeding-and-synthetic.md (Synthetic Data Generation).


Anti-Patterns

Shared Mutable Test Data

Multiple tests reading and writing the same database rows. Test A creates a user, Test B modifies it, Test C asserts on the original state and fails. Fix by having each test create its own data through factories.

Production Data Without Anonymization

Copying the production database to staging for "realistic testing." This violates GDPR, risks data breaches in less-secured environments, and creates compliance liability. Always anonymize before use, or generate synthetic data that matches production distributions.

Non-Deterministic Data

Using Math.random() or Date.now() in test data creation without seeding. Tests pass on Monday and fail on Tuesday because the random name generated happens to exceed a field length limit. Use seeded Faker instances and fixed timestamps.

No Cleanup Strategy

Tests that create data and never clean it up. The test database grows until it affects performance, or stale data causes false positives in other tests. Every data creation must have a corresponding cleanup, or, where the application cannot delete, a ledger and scoped assertions that make the leftover data harmless (see Cleanup Strategies).

Fixture File Explosion

Creating a separate JSON fixture file for every test variation. Instead of user-admin.json, user-inactive.json, user-admin-inactive.json, use a factory with traits. Fixtures should be reserved for static reference data and API response mocks.

Over-Specified Test Data

Creating a complete user object with 30 fields when the test only cares about role. This obscures intent and makes tests brittle. Factories with sensible defaults solve this: override only what the test cares about.

Hard-Coded IDs

Using userId: '1' in tests. This couples tests to database state and breaks when running in parallel (ID collision) or against a database with existing data. Use factory sequences or seeded UUIDs (see Core Principle 4).


Verification

Prove the data layer is deterministic, isolated, and PII-free, smallest check first:

  1. Seeds are idempotent — run the seed twice back-to-back and diff the row counts: psql -c "SELECT count(*) FROM countries" && <seed> && psql -c "SELECT count(*) FROM countries" returns the same number both times and exits 0. A growing count means a missing ON CONFLICT. An application that seeds itself at start has no script to run twice; restart it on the same database and compare the durable state before and after, and say that this is the analogue, not the recipe.
  2. No shared mutable state — run the suite under parallelism and randomized order: npx playwright test --workers=4 (or pytest -n auto -p randomly) stays green. Playwright has no shuffle flag; use --workers=N with fullyParallel: true and --repeat-each=2, and run the files in reverse with an explicit list for the ordering check. A failure that only appears here is an ordering or shared-data dependency.
  3. Determinism holds — run the same data-generating test twice; with faker.seed(n) set, generated names/IDs/UUIDs match across runs. If they drift, an unseeded Faker call or Date.now()/crypto.randomUUID() leaked in.
  4. No real PII — grep -rE '@(gmail|outlook|yahoo)\.com|[0-9]{3}-[0-9]{2}-[0-9]{4}' tests/ fixtures/ returns nothing (real-looking emails and SSNs). Anything it finds is an anonymization gap.
  5. Cleanup returns to baseline — snapshot row counts before the suite, run it, snapshot again: the test DB is back to baseline with no orphaned records.

Done When

  • Every entity type the suite creates has a factory or fixture (no inline ad-hoc object literals in tests for shared entities -- grep the test dir for hand-built fixtures and confirm none remain).
  • Test data is isolated per test -- the suite passes with parallelism on (--workers=N / pytest -n auto) and under randomized order (-p randomly; Playwright has no shuffle, so a reversed explicit file list with --repeat-each), proving no shared mutable state or ordering dependency.
  • Seed scripts are idempotent -- running the seed twice in a row produces the same row count and exits 0; the CI job runs them with no manual intervention.
  • No real PII used in test fixtures -- all sensitive data anonymized or synthetic (grep for production domains / real-looking SSNs returns nothing).
  • Data cleanup verified -- row counts in the test DB return to baseline after the suite (no orphaned records accumulate across runs).

Reference Files (in references/)

  • factories.md — Full Fishery (associations, deterministic UUIDs), FactoryBot (User + Product traits), Factory Boy (Params/Trait), static/dynamic/composed Playwright fixtures, and the worker-scoped seeding fixture.
  • seeding-and-synthetic.md — Idempotent ON CONFLICT seed script, Faker.js anonymization + referential-integrity pipeline, cleanup strategies (rollback / truncate / API), and synthetic edge-case + boundary-value generators.

Related Skills

  • unit-testing -- Unit tests are the primary consumer of factory-generated data; this skill provides the data layer.
  • api-testing -- API tests use both factories (for request bodies) and fixtures (for mocked responses).
  • playwright-automation -- E2E tests need test data seeded via API or fixtures before browser interaction.
  • test-reliability -- Deterministic test data eliminates a major source of test flakiness.
  • test-environments -- Owns environment provisioning and database-branching strategy (Neon, Supabase, PlanetScale) for preview envs; this skill owns the data that fills them.
  • database-testing -- Migration testing, data-integrity assertions, and Testcontainers for the database layer specifically -- go there to test the DB, come here to populate it.
  • ci-cd-integration -- Database seeding and cleanup must be integrated into CI pipeline stages.

FAQ

What does the test-data-management skill do?

Create and manage test data with factory patterns, fixture strategies, data anonymization, and synthetic data generation. Covers Fishery (TypeScript), FactoryBot (Ruby), Factory Boy (Python), database seeding, cleanup strategies, and GDPR-compliant data handling. Use when: "test data," "fixtures," "factories," "seed data," "synthetic data," "test database," "data anonymization." Not for: migration/integrity testing of the DB itself — use database-testing; environment provisioning and database branching strategy — use test-environments. Related: test-environments, database-testing, api-testing, unit-testing.

How do I install test-data-management?

Run npx skills add https://github.com/petrkindlmann/qa-skills --skill test-data-management in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/test-data-management/ (personal) or .claude/skills/test-data-management/ (project).

Which AI agents can use test-data-management?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is test-data-management safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains test-data-management?

It is published by petrkindlmann in petrkindlmann/qa-skills. It has 1,356 recorded installs.

More from petrkindlmann/qa-skills

View all →

playwright-automation

petrkindlmann/qa-skills

Write production-grade Playwright tests in TypeScript: Page Object Model, fixtures, auto-waiting, user-facing locators, parallel execution, CI integration, sharding, and installed-version checks. Includes an explicit "do not" list for AI agents. Use when: "Playwright," "write E2E test," "page object," "new Playwright suite," "Playwright config." Not for: fixing one flaky test at runtime — use test-reliability. Not for: bulk regenerating selectors after a UI refactor — use selector-drift-recovery. Not for: visual baseline creation/management — use visual-testing. Not for: deep WCAG/axe audits — use accessibility-testing. Related: visual-testing, ci-cd-integration, api-testing, test-reliability, selector-drift-recovery, accessibility-testing.

Testing & QA1.9K installs

exploratory-testing

petrkindlmann/qa-skills

Design and execute structured exploratory testing sessions. Covers Session-Based Test Management (SBTM), charter writing, heuristic-based exploration (HICCUPS, FEW HICCUPS), bug discovery patterns, note-taking templates, and conversion of findings to automated tests. Use when: "exploratory testing," "SBTM," "manual testing," "bug hunting," "test charter," "heuristic testing." Not for: an AI browser agent autonomously exploring the app from a natural-language goal — use agentic-browser-testing. Not for: testing your product's own AI/LLM features — use ai-system-testing. Related: test-planning, ai-bug-triage, risk-based-testing, agentic-browser-testing.

Testing & QA1.5K installs

test-strategy

petrkindlmann/qa-skills

Produce a multi-quarter QA strategy document. Covers scope, risk-based prioritization, test levels (unit/integration/E2E), pyramid analysis, entry/exit criteria, quality KPIs, tool selection rationale, CI scaling levers, and timeline planning. Output is an actionable strategy document, not a shelf document. Use when: "test strategy," "QA strategy doc," "testing approach," "QA roadmap," "multi-quarter QA direction." Not for: a single-sprint or single-release plan — use test-planning. Not for: identifying which areas carry the most risk — use risk-based-testing first. Related: risk-based-testing, qa-metrics, release-readiness, test-planning, test-reliability.

Testing & QA1.5K installs

test-planning

petrkindlmann/qa-skills

Build a single sprint or release test plan. Covers feature decomposition into testable scenarios, requirements-to-test coverage mapping, effort estimation by test type, prioritization matrices (risk × effort), resource allocation, and scheduling with buffers. Use when: "sprint test plan," "release test plan," "what to test this sprint," "test estimation," "coverage mapping." Not for: multi-quarter strategy — use test-strategy. Not for: ranking areas by risk — use risk-based-testing. Not for: the go/no-go decision itself — use release-readiness. Related: test-strategy, risk-based-testing, release-readiness.

Testing & QA1.5K installs

qa-project-context

petrkindlmann/qa-skills

Create and fill .agents/qa-project-context.md with the project's tech stack, test frameworks, CI/CD pipeline, environments, quality goals, risk areas, team structure, and conventions. This is the one file every other QA skill reads first, so they skip redundant discovery and give context-aware advice. Use when: "set up QA context," "configure testing," "initialize project," first use of any QA skill. Not for: bootstrapping a brand-new project's QA end-to-end — use qa-start (which calls this skill as its first step). Related: qa-start, risk-based-testing, test-strategy, qa-metrics, playwright-automation.

Testing & QA1.4K installs

risk-based-testing

petrkindlmann/qa-skills

Produce a risk matrix or heatmap that quantifies what could break by business impact × probability, runs failure mode analysis on the top items, and maps test coverage to risk zones. Includes stakeholder interview frameworks and continuous reassessment. Run this BEFORE test-strategy or test-planning. Use when: "risk assessment," "risk matrix," "risk heatmap," "what could break," "critical paths," "failure modes," "where to focus testing." Not for: multi-quarter QA direction — use test-strategy. Not for: a single sprint/release test plan — use test-planning. Not for: hands-on session-based bug hunting — use exploratory-testing. Related: test-strategy, test-planning, release-readiness, qa-metrics.

Testing & QA1.4K installs

Popular testing & qa skills

View category →

tdd

mattpocock/skills

Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.

Testing & QA1.2M installs

grilling

mattpocock/skills

Grill the user relentlessly about a plan, decision, or idea. Use when the user wants to stress-test their thinking, or uses any 'grill' trigger phrases.

Testing & QA996.2K installs

migrate-to-shoehorn

mattpocock/skills

Migrate test files from as type assertions to @total-typescript/shoehorn. Use when user mentions shoehorn, wants to replace as in tests, or needs partial test data.

Testing & QA484.1K installs

run-train

lllllllama/rigorpilot-skills

Rigor Train skill for deep learning research repositories. Use when a documented or selected training command should be run conservatively for startup verification, short-run verification, full kickoff, or resume, with command, config, seed, log, checkpoint, status, and metric evidence written to standardized trainoutputs/. Do not use for environment setup, exploratory sweeps, speculative idea implementation, or end-to-end orchestration.

Testing & QA337.8K installs

test-driven-development

obra/superpowers

Use when implementing any feature or bugfix, before writing implementation code

Testing & QA261.8K installs

Use when implementation is complete, all tests pass, and you need to decide how to integrate the work

Testing & QA216.8K installs