Test Data & API Mocking

Test Data Management: Best Practices, Tools & Examples

Parveen KumariUpdated Oct 19, 202618 min read

Quick answer

Test data management (TDM) is the practice of planning, creating, provisioning, versioning and retiring the data your tests use, so every run gets realistic, isolated and compliant data on demand. Default to synthetic data generated from the schema, mask anything copied from production, isolate data per run, keep data definitions in version control and automate provisioning and cleanup in CI.

Reviewed by Sushant Joshi

Share:
Test data management best practices across environments and pipelines

Test data management (TDM) is the practice of planning, creating, provisioning, versioning and retiring the data your tests use, so that every run gets realistic, isolated and compliant data on demand. It is the pillar of our test data and API mocking hub: this guide explains what TDM is, the best practices that hold up at scale, how it works in microservices and CI/CD, and links to a deeper guide for every technique — from generating test data for API testing to data masking.

Most teams have invested in automation frameworks and CI/CD and still manage test data by hand: tickets to a DBA for a refresh, a shared staging database where teams overwrite each other's records, and a production copy nobody is quite sure was masked. The symptoms are familiar — tests that pass at 9 a.m. and fail at 2 p.m., multi-day waits for environments, and an audit finding about customer data in QA.

TDM fixes this by treating test data the way CI/CD treats deployments: as an automated, repeatable, governed process rather than a manual chore.


In this guide

  1. What is test data management?
  2. Why test data management is needed
  3. Test data management best practices
  4. Test data management in microservices
  5. TDM architecture and the CI/CD life cycle
  6. Test data management tools
  7. Test data management in practice: two examples
  8. Test data management challenges and how to solve them
  9. Test data management FAQ

What is test data management?

Test data management is the discipline that answers five questions for every test: what data does it need, where does that data come from, how is it kept realistic and current, how is it kept compliant, and how is it delivered fast enough not to block the pipeline?

It covers the full life cycle of test data:

  1. Plan — decide what data each test or scenario needs.
  2. Create — generate it, mask it from production, or subset it.
  3. Provision — deliver it to the right environment at the right time.
  4. Maintain — keep it valid as schemas and business rules change.
  5. Retire — clean up after the run and purge old copies on a schedule.

Four techniques do the creating:

  • Synthetic data generation — realistic but entirely artificial data from tools like Faker, Mockaroo or GenRocket, or derived directly from an OpenAPI or JSON Schema. Private by design and unlimited in volume. See synthetic test data vs production data.
  • Production data masking — transforming sensitive fields in a production copy so the data keeps its shape and relationships but identifies nobody. Good masking is deterministic (same input, same output), referentially consistent (a masked customer ID matches across tables) and format-preserving (a masked email still looks like one).
  • Data subsetting — extracting a small, representative slice of production that preserves referential integrity: take an order and you also take its customer, line items, payments and shipments.
  • Provisioning and orchestration — APIs, containerized databases and self-service requests that deliver a named scenario to an environment in minutes.

The difference between TDM and ad hoc data creation is governance: managed test data has an owner, a version history, quality checks and compliance rules, instead of being a throwaway artifact each developer recreates.


Why test data management is needed

  • Data is the bottleneck. Provisioning is often the slowest step in delivery; multi-day waits for a refresh cancel out the speed of automated testing.
  • Most flaky tests are data problems. A test expects customer 42, but another test deleted it; it expects ten catalogue items, but a parallel run added three. Shared mutable data makes results depend on timing.
  • Compliance is not optional. GDPR, CCPA, HIPAA and PCI DSS all restrict how personal and cardholder data may be used outside production. Unmasked copies in staging are an audit finding waiting to happen.
  • Microservices multiply the problem. Each service owns its store, and a cross-service scenario needs coordinated data in several of them.
  • Data failures waste debugging time. "Expected 5 items, got 3" could be a bug or stale data, and the log does not say which. Separating the two needs tooling: in Shift-Left API, a failed API run is grouped into causes with a verdict on each — test defect, data issue, environment problem or suspected product bug — so a missing seed record is reported as a data issue instead of being muted as flakiness.

Test data management best practices

These are the practices that separate managed test data from a shared staging database.

  1. Default to synthetic data. Make generated data the standard and require a written justification for any production copy in a non-production environment.
  2. Generate from the schema, not from fixtures. Data derived from the OpenAPI or JSON Schema is valid by construction and fails loudly when the contract changes. The mechanics are in how to generate test data for API testing, and the generators compared in test data generation tools.
  3. Use factories with overrides. A factory builds a valid object with sensible defaults; a test overrides only the fields it cares about, which keeps tests readable and resilient to schema changes.
  4. Isolate data per execution. Each pipeline run gets its own data: containerized databases, thin clones or per-run generation. No shared mutable data between teams, suites or stages.
  5. Mask every production flow. Every copy of production data that leaves production passes through an automated, deterministic masking pipeline. No manual workarounds, no "temporary" unmasked copies.
  6. Classify every field. Tag fields as PII, PHI, PCI, confidential or non-sensitive, and drive masking rules from the tags so new fields are handled automatically.
  7. Version data with code. Keep generators, scenario definitions, masking rules and seed scripts in the same repository as the application, reviewed in the same pull requests.
  8. Automate provisioning and cleanup. Pipelines request data through an API and receive it in minutes; every provisioning step has a matching teardown that runs whether the tests pass or fail. Patterns for this are in test data automation in CI/CD pipelines.
  9. Build named scenario libraries. "Customer with an expired card and two open orders" is requested by name, not assembled record by record.
  10. Assign ownership. Every data domain — customers, orders, payments — has an owner responsible for its model, generators and masking rules.
  11. Monitor data quality. Validate test data stores for schema drift, broken relationships and stale references before they cause failures.
  12. Measure it. Track provisioning time, the share of tests with isolated data, the data-related failure rate and compliance findings, alongside your delivery metrics.

Test data management checklist

  • ✔ Audit every test environment for unmasked production data and remediate
  • ✔ Classify all fields by sensitivity
  • ✔ Automated, deterministic masking on every production-to-test flow
  • ✔ Synthetic generators for unit, API and integration tests
  • ✔ Factories with overrides instead of static fixtures
  • ✔ Isolated data per pipeline run; no shared mutable data
  • ✔ Data definitions versioned with application code
  • ✔ Self-service provisioning APIs used by CI/CD
  • ✔ Automated cleanup and scheduled purges
  • ✔ Named scenario libraries for the main business workflows
  • ✔ Owners assigned for every data domain
  • ✔ KPIs tracked: provisioning time, data-related failure rate, compliance findings

Generate test data variants from your spec (free)

Free, runs in your browser, no sign-up needed.


Test data management in microservices

In a monolith, one migration and one seed script cover everything. In microservices, every service is an independent deployable with its own data life cycle, so test data has to be owned per service and composed across services.

Service-level data factories

Each service maintains a factory for its own domain objects:

// order-service test data factory
class OrderTestDataFactory {
  static createValidOrder(overrides = {}) {
    return {
      customerId: faker.string.uuid(),
      items: [{ productId: faker.string.uuid(), quantity: 1, price: 29.99 }],
      shippingAddress: AddressFactory.createValid(),
      ...overrides,
    };
  }
}

Ephemeral databases per run

The cleanest isolation is a database per test run: start a container, migrate, seed, test, destroy.

# docker-compose.test.yml
services:
  order-db-test:
    image: postgres:16
    environment:
      POSTGRES_DB: orders_test
    tmpfs: /var/lib/postgresql/data   # RAM-backed for speed

Testcontainers does the same from inside the test code, and LocalStack covers DynamoDB, S3 and SQS. The seconds of startup are trivial next to hours lost to shared-state failures.

Contract-driven stubs for other services' data

The order service does not own customers or products, so its tests should not need them to exist. Stub those services with mocks generated from their specs and verified by contract tests (Pact, Spring Cloud Contract), so the stubbed data stays the shape the provider really returns. Choosing a mocking tool is covered in API mocking tools, and the technique itself in what is API mocking.

Cross-service scenarios through the APIs

For the few tests that span services, an orchestration layer creates data by calling each service's public API — never by writing into another team's database — so the data passes the same validation as production data. A POST /test-data/scenarios/customer-places-order endpoint, or a chained API workflow, keeps that logic in one place. The consistency problems this raises are covered in test data challenges in distributed systems, and database-level isolation and migrations in database testing strategies for DevOps.

Event-sourced services and performance data

Services built on event sourcing or CQRS cannot be seeded by inserting final-state rows; build state by replaying the event sequence that produces it, so the data goes through the same business logic. Performance tests need volume — thousands or millions of records — so keep pre-generated, versioned data sets in object storage and load them at the start of the run, regenerating when schemas change. The request side needs variety too, or every virtual user hits the same cached record; bind load tests to a data set so each user sends different values.


TDM architecture and the CI/CD life cycle

A mature TDM setup works as a service layer between test execution and data storage. A governance layer in the middle applies classification, masking, access control and audit logging to every request. Upstream sit three sources: a synthetic data engine, a masked data repository of anonymized production snapshots refreshed on a schedule, and a subset library of representative slices. Downstream, CI/CD pipelines, developer machines, QA and performance infrastructure all request data through the same layer.

A request names a scenario ("checkout with three items, a coupon and international shipping"); the platform assembles the data from the right source, loads it into the target (a containerized database, a mock or a shared instance), returns connection details and cleans up afterwards.

Test data management architecture across environments and pipelines

The life cycle in a pipeline

For most pipelines the life cycle is four operations — provision, migrate, seed, use — and the container's death is the cleanup:

# .github/workflows/api-tests.yml
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:                                   # 1. provision: disposable, per run
        image: postgres:16-alpine
        env: { POSTGRES_PASSWORD: test }
        options: --health-cmd pg_isready --health-interval 5s
    env:
      DATABASE_URL: postgresql://postgres:test@localhost/postgres
    steps:
      - uses: actions/checkout@v4
      - run: alembic upgrade head                                  # 2. schema
      - run: python scripts/seed.py --profile ci --seed 20260819   # 3. deterministic data
      - run: pytest tests/api                                      # 4. use

Shared environments that cannot be disposable need an explicit, scheduled reset that is verified afterwards — including a test that proves no real personal data landed:

#!/usr/bin/env bash
# refresh-staging.sh: runs nightly
set -euo pipefail
psql "$STAGING_DSN" -c 'DROP SCHEMA public CASCADE; CREATE SCHEMA public;'
alembic -x url="$STAGING_DSN" upgrade head
psql "$STAGING_DSN" -f seeds/reference-data.sql
python scripts/seed.py --dsn "$STAGING_DSN" --profile staging --seed "$(date +%Y%m%d)"
pytest tests/test_masking.py --dsn "$STAGING_DSN"

Generate payloads from the schema

Hand-maintained fixtures break on every schema change. Generating from the spec keeps data valid by construction:

# conftest.py: deterministic, schema-valid data with no fixture files
import pytest, yaml
from faker import Faker
from jsonschema import validate

fake = Faker()
Faker.seed(20260819)          # deterministic across runs and machines

SPEC = yaml.safe_load(open("openapi.yaml"))
CUSTOMER = SPEC["components"]["schemas"]["Customer"]

@pytest.fixture
def customer_payload():
    payload = {
        "name":  fake.name(),
        "email": fake.unique.email(domain="example.test"),   # never a real domain
        "phone": fake.numerify("+1-###-###-####"),
        "tier":  fake.random_element(["free", "pro", "enterprise"]),
    }
    validate(payload, CUSTOMER)   # fails loudly when the schema moves
    return payload

Test data management tools

ToolTypeBest forOpen source
Faker (Python/JS/Java), Bogus (.NET)Generation libraryDeveloper-driven synthetic data in test codeYes
json-schema-fakerSchema-based generationPayloads straight from a JSON SchemaYes
MockarooSaaS generationVisual data design with API accessFreemium
GenRocketModel-based generationComplex multi-entity synthetic data with business rulesNo
Tonic.aiSynthetic + maskingPrivacy-safe data derived from production schemasNo
DelphixVirtualization + maskingThin clones with integrated maskingNo
Informatica TDMFull suiteEnterprise masking, subsetting and compliance workflowsNo
Broadcom Test Data ManagerFull suiteMainframe-to-cloud data with lineageNo
K2ViewData fabricEntity-centric data delivery across systemsNo
Testcontainers / LocalStackEphemeral infrastructureA real database or cloud service per runYes
Flyway / LiquibaseSchema migrationVersioned schemas that test data followsYes

Most organizations combine them: a library such as Faker inside the test code, an enterprise platform for governed production-derived data and masking, and containers for isolation.

Free 1-page checklist

API Testing Checklist for CI/CD Pipelines

A printable 25-point checklist covering authentication, error scenarios, contract validation, performance thresholds, and more.

Download Free

Where Shift-Left API fits

At the API test layer, Shift-Left API keeps test data as project data sets — imported from CSV, Excel, JSON, YAML or XML, or read at run time from data sources including PostgreSQL, MySQL, SQL Server, Oracle, SQLite and MongoDB (read-only) or another API. Any test bound to a data set runs once per row with its own result; EXPECTED_STATUS columns set per-row expectations and INVALID_ columns become negative variants. A test-data owner can also fill a project's existing tests from a data set: a preview shows every value that will change, deliberate boundary values and credentials are left alone, and Undo restores the tests. Every data set edit is versioned. When an API dependency is not available, the built-in mock server generates stand-ins from the imported spec.


Test data management in practice: two examples

Both are illustrative composites of typical rollouts, not named customers' measured results.

An enterprise bank. Twelve application teams ran 200+ daily builds and got test data by filing tickets to a DBA team, waiting days for each refresh; an audit found unmasked customer data in staging, and data-related failures ate a large share of QA time. The bank moved in three phases: database virtualization with integrated masking, so masked thin clones provisioned in minutes; a self-service provisioning API consumed by CI, which retired the ticket queue; and synthetic generators per team for unit and API tests. Provisioning went from days to minutes, unmasked data disappeared from lower environments, and data-related failures dropped sharply.

A 12-service e-commerce platform. All services shared one test database seeded nightly, so tests ran serially and roughly one run in eight failed on data state. Over eight weeks each team built a factory for its domain, moved integration tests onto per-run Postgres containers, refactored cross-service tests onto a scenario endpoint that created data through the services' APIs, and finally decommissioned the shared database. Suites could run in parallel, each service's suite ran on its own in minutes, and new services no longer had to touch a shared seed script.


Test data management challenges and how to solve them

Schema drift

Data that was valid last week fails this week because a required field was added. Solution: tie generators to the schema (OpenAPI, JSON Schema, migrations) and regenerate or validate test data as part of every migration.

Referential integrity in masked data

Masking one table is easy; keeping a masked customer ID consistent across every table and database that references it is not. Solution: deterministic masking that always maps the same input to the same output.

Cross-team and cross-service dependencies

One team's tests need data another team owns. Solution: shared data contracts for cross-service scenarios, contract-verified stubs for isolated tests and an orchestrator that creates coordinated data through APIs for the few end-to-end ones.

Scaling provisioning for CI/CD

Fifty builds a day need fifty isolated data sets. Solution: thin clones (Delphix, Windocks) or containerized databases pre-loaded with scenario data that start in seconds.

Freshness versus stability

Tests want data that reflects production but does not change mid-run. Solution: a dual track — a masked base set refreshed on a schedule, plus synthetic scenario data generated per run.

Compliance across jurisdictions

EU, US healthcare and payment data each carry different rules. Solution: policy-based handling where classification and regional tags drive masking and residency automatically, so a team cannot forget to apply them.

Organizational resistance

Teams used to owning their data resist a central platform. Solution: sell it as self-service — no tickets, no waiting — with governance applied automatically in the background, and start with the team in the most pain.


More from the Test Data & API Mocking hub

Every guide in this hub, grouped by format. The Test Data & API Mocking hub page has the full list.

Tools and comparisons

Test data management FAQ

What is test data management?

Test data management is the practice of planning, creating, maintaining and governing the data that software tests use. It covers synthetic data generation, masking of production data, subsetting, versioning and automated provisioning, so that every test run gets realistic, isolated and compliant data without waiting on a ticket.

Why is test data management needed?

Without it, tests share mutable data and fail for reasons unrelated to the code, teams wait days for refreshed environments, and copies of production data leak personal information into lower environments. Test data management removes those three costs: flakiness, delay and compliance risk.

What are the most important test data management best practices?

Default to synthetic data generated from the schema, mask every field copied from production, isolate data per test run, keep data definitions and generators in version control next to the code, automate provisioning and cleanup in CI/CD, assign an owner to each data domain, and measure provisioning time and data-related failures.

How do you manage test data in an automation framework?

Use factories that build valid objects with sensible defaults and per-test overrides instead of static fixture files, generate values from the API or database schema, seed unique data in setup and remove it in teardown, run against a disposable database where you can, and drive data-driven tests from versioned CSV, JSON or database sources.

How do you manage test data in microservices?

Give each service its own test data factory and a disposable database per run, stub other services' data with contract-driven mocks, and create cross-service scenarios through the services' public APIs rather than writing into their databases. For event-sourced services, build state by replaying event sequences.

What is the test data management life cycle?

The life cycle has five stages: plan what data each test needs; create it by generation, masking or subsetting; provision it to the right environment at the right time; maintain it as schemas change; and retire it by cleaning up after the run and purging old copies on a schedule.


Sources and further reading

Key takeaways

  • Test data management is the life cycle of test data — plan, create, provision, maintain, retire — run as an automated, governed process.
  • Synthetic data generated from the schema should be the default; production data appears only masked, deterministically and through a pipeline.
  • Isolation per run is what ends data-related flakiness; containers and thin clones make it cheap.
  • In microservices, data is owned per service and composed through APIs, never by writing into another team's database.
  • Start where the pain is: masking first if compliance is the risk, automated provisioning if speed is, isolation if flakiness is.

Want test data that drives your API tests without fixture files? Start a free trial: import a CSV, Excel or JSON data set or connect a database, bind it to your generated API tests, and get one result per row — with negative rows from INVALID_ columns.


Explore the test data and mocking hub: How to Generate Test Data for API Testing | Test Data Generation Tools | Synthetic vs Production Test Data | Data Masking for Test Environments | Test Data Automation in CI/CD | Test Data Challenges in Distributed Systems | Database Testing Strategies for DevOps | What is API Mocking? | API Mocking Tools

For regulated teams: see the standardizing API testing across enterprise teams, API testing for HIPAA compliance, API testing data residency under GDPR and the regulated industries overview.

Continue learning

Go deeper in the Learning Center

Hands-on lessons with runnable code against our live sandbox.

Ready to shift left with your API testing?

Import your OpenAPI spec and get a runnable test suite, in our cloud or on your own infrastructure.