Generating Synthetic Test Data
When to use
- Creating fixtures for pipeline/dbt unit and integration tests.
- Seeding dev/staging with realistic, privacy-safe data instead of copying prod.
- Load-testing with high volume, or crafting edge cases on purpose.
- Do NOT use for production data generation or ML training data augmentation.
Workflow
- [ ] Seed the generator for deterministic, reproducible output
- [ ] Preserve referential integrity (child keys reference generated parents)
- [ ] Include edge cases: nulls, duplicates, boundaries, late/out-of-order events
- [ ] Match production distributions where behavior depends on them
- [ ] Scale volume for load tests; keep small fixtures for unit tests
- Deterministic + seeded. Fix the random seed so tests are reproducible;
flaky data makes flaky tests. Small, fixed fixtures for unit tests.
- Referential integrity. Generate parents first, then children referencing
real parent keys — otherwise join/relationship tests are meaningless.
- Edge cases on purpose. Include nulls, duplicate keys, boundary values,
empty batches, and late/out-of-order timestamps so pipelines are tested against
what actually breaks them.
- Realistic distributions where logic depends on them (skew, seasonality) —
uniform random data hides skew bugs.
- Privacy-safe. Synthetic stand-ins let you test without copying PII
(pairs with
masking-pii-data).
Patterns
Deterministic, referentially-consistent generation (Python + Faker):
from faker import Faker
fake = Faker(); Faker.seed(42) # reproducible
customers = [{"customer_id": i, "email": fake.email()} for i in range(1000)]
orders = [{
"order_id": n,
"customer_id": fake.random_int(0, 999), # references a real customer
"amount": round(fake.random.uniform(0, 500), 2),
"ordered_at": fake.date_time_this_year(),
} for n in range(10000)]
Inject edge cases explicitly — append rows with a null email, a duplicate
order_id, a zero/negative amount, and a far-future timestamp so quality checks
and dedup logic are exercised.
dbt seeds / unit-test fixtures — commit small CSV seeds or inline unit_tests
rows for deterministic model tests (testing-dbt-projects).
Common pitfalls
- Unseeded randomness — non-reproducible, flaky tests; always seed.
- Broken referential integrity — orphan foreign keys make relationship tests
pass or fail meaninglessly.
- Only happy-path data — the pipeline breaks on nulls/dupes/late events you
never generated; add them deliberately.
- Uniform distributions — hide skew and performance issues that real,
skewed data would surface in load tests.
- Copying production "just this once" — leaks PII; generate synthetic instead.
- Giant fixtures for unit tests — slow and hard to reason about; keep unit
fixtures tiny, reserve volume for load tests.
1---2name: generating-synthetic-test-data3description: Generate realistic synthetic data for testing data pipelines — deterministic seeded fixtures, referential integrity across tables, edge cases (nulls, duplicates, late/out-of-order events), volume for load tests, and privacy-safe stand-ins for production. Use when creating test data for pipeline/dbt tests, seeding dev environments, load testing, or replacing PII with safe synthetic data.4---56# Generating Synthetic Test Data78## When to use910- Creating fixtures for pipeline/dbt unit and integration tests.11- Seeding dev/staging with realistic, privacy-safe data instead of copying prod.12- Load-testing with high volume, or crafting edge cases on purpose.13- Do NOT use for production data generation or ML training data augmentation.1415## Workflow1617```18- [ ] Seed the generator for deterministic, reproducible output19- [ ] Preserve referential integrity (child keys reference generated parents)20- [ ] Include edge cases: nulls, duplicates, boundaries, late/out-of-order events21- [ ] Match production distributions where behavior depends on them22- [ ] Scale volume for load tests; keep small fixtures for unit tests23```24251. **Deterministic + seeded.** Fix the random seed so tests are reproducible;26 flaky data makes flaky tests. Small, fixed fixtures for unit tests.272. **Referential integrity.** Generate parents first, then children referencing28 real parent keys — otherwise join/relationship tests are meaningless.293. **Edge cases on purpose.** Include nulls, duplicate keys, boundary values,30 empty batches, and late/out-of-order timestamps so pipelines are tested against31 what actually breaks them.324. **Realistic distributions** where logic depends on them (skew, seasonality) —33 uniform random data hides skew bugs.345. **Privacy-safe.** Synthetic stand-ins let you test without copying PII35 (pairs with `masking-pii-data`).3637## Patterns3839**Deterministic, referentially-consistent generation (Python + Faker):**4041```python42from faker import Faker43fake = Faker(); Faker.seed(42) # reproducible4445customers = [{"customer_id": i, "email": fake.email()} for i in range(1000)]46orders = [{47 "order_id": n,48 "customer_id": fake.random_int(0, 999), # references a real customer49 "amount": round(fake.random.uniform(0, 500), 2),50 "ordered_at": fake.date_time_this_year(),51} for n in range(10000)]52```5354**Inject edge cases explicitly** — append rows with a null email, a duplicate55`order_id`, a zero/negative amount, and a far-future timestamp so quality checks56and dedup logic are exercised.5758**dbt seeds / unit-test fixtures** — commit small CSV seeds or inline `unit_tests`59rows for deterministic model tests (`testing-dbt-projects`).6061## Common pitfalls6263- **Unseeded randomness** — non-reproducible, flaky tests; always seed.64- **Broken referential integrity** — orphan foreign keys make relationship tests65 pass or fail meaninglessly.66- **Only happy-path data** — the pipeline breaks on nulls/dupes/late events you67 never generated; add them deliberately.68- **Uniform distributions** — hide skew and performance issues that real,69 skewed data would surface in load tests.70- **Copying production "just this once"** — leaks PII; generate synthetic instead.71- **Giant fixtures for unit tests** — slow and hard to reason about; keep unit72 fixtures tiny, reserve volume for load tests.