Deterministic Test Data: Faker Seeds and Reproducible Fixtures
Reproduce Faker test data with a seed, pinned version, locale and clock. Includes a runnable example, verified output and fixes for changing fixtures.
By Vincent RuanPublished June 25, 2026Last updated September 6, 20264 min read

Deterministic test data seeding lets you replay generated inputs by recording how they were made. The useful contract is seed + generator version + locale + call order + reference date. A seed by itself is incomplete: Faker explicitly documents that upgrades can change outputs and that relative date methods need a fixed reference date [faker-usage].
Use this page when a fixture changes between runs or you need a reproducible bug report. For choosing fields and building related tables, start with the test data generation guide.
A runnable Faker example with measured output
Download faker-seed-v1.mjs. In an empty working directory, run npm install --save-exact @faker-js/faker@9.9.0, then node faker-seed-v1.mjs. It creates a separate English-locale Faker instance for each run, seeds it with 42, compares the results and prints the values below. No service or account is needed.
| Operation | Run A | Run B |
|---|---|---|
| First person.firstName() | Garnet | Garnet |
| Second person.firstName() | Valentine | Valentine |
| Third person.firstName() | Moses | Moses |
| Re-seed 42; date.soon({ days: 7, refDate: "2026-01-01T00:00:00.000Z" }) | 2026-01-03T14:55:22.489Z | 2026-01-03T14:55:22.489Z |
The date row starts from a freshly reset seed. It is not the fourth draw after the names. Moving that reset or inserting another random call changes the sequence. The script asserts both the repeated output and these recorded values, so a dependency upgrade that changes them is visible.
What to pin when the same seed stops working
| Input to record | Typical cause of drift | Fix |
|---|---|---|
| Exact package version and lockfile | A name pool changes in an update | Commit the lockfile; review fixture changes on upgrade |
| Locale and fallback order | A missing field falls back to another language | Construct the instance with an explicit locale |
| Generation code and call order | A new phone field consumes random draws before the name | Version the recipe; use separate instances for independent fixtures |
| Clock and reference date | date.soon() moves with today | Pass refDate or set a fixed default reference date |
| Timezone and output format | Local date formatting differs between machines | Use explicit timezone rules and a stable serializer |
| Per-test instance | Concurrent tests share a random stream | Create and seed an instance inside each test |
Pinning a major version alone is insufficient. Python Faker also limits its reproducibility promise to the same version and method sequence, and notes that provider data can change in patch releases [python-faker]. Keep a copy of an important failing input even when you also record its seed.
Seed calls for JavaScript, Python and .NET
| Library | Per-instance initialization | Scope |
|---|---|---|
| Faker.js | const fake = new Faker({ locale: en }); fake.seed(42); | The new instance |
| Python Faker | fake = Faker("en_US"); fake.seed_instance(42) | The new instance |
| Bogus (.NET) | new Faker<User>().UseSeed(42) | The configured User generator |
Faker.js exposes seed and reference-date configuration on its Faker instance [faker-api]. Python offers both shared and per-instance seeding [python-faker]. Bogus documents local seeds and explains how rule order affects generated values [bogus]. These libraries have different randomizers and datasets: seed 42 does not mean the same name across languages.
Repeat failures without freezing discovery
Use a fixed configuration for snapshots and ordinary integration tests. In an exploratory run, vary the seed and save it together with the generated input when a test fails. Then reduce that input to a small regression fixture. A long name found through random generation becomes a reliable regression only when the test keeps that input or a pinned recipe.
Seeding does not guarantee a leap day, a decomposed Unicode name or an overlong email appears. Keep those as explicit cases alongside your generated data. The name validation cases and date-of-birth cases provide fixed inputs and expected behavior.
Reproducing a Fakenamely dataset
The API accepts a seed and the bulk exporter exposes one for downloads. Record the full request or export configuration, including country, selected fields and row count. The current identity engine uses an isolated Faker instance and a fixed default reference date of 2026-01-01; callers can supply a different date. A site update can change the underlying data or recipe, so save exported JSON when you need the exact records long term.
- Record the package version, seed, locale and generation recipe.
- Fix relative dates and choose an explicit serialization format.
- Generate each independent fixture with its own instance.
- Compare two runs; save the exact failing input if the case matters across upgrades.
References & sources
- Faker usage: reproducible results and relative dates — Faker
- Faker class: seed and setDefaultRefDate — Faker
- Seeding the Generator — Python Faker
- Bogus determinism and local seeds — Bogus
Frequently asked questions
What is deterministic test data?
Test inputs that can be recreated from a recorded configuration. For generated fixtures, record the seed, exact library version, locale, generation code and clock inputs. Explicitly saved fixtures can also be deterministic without any generator.
Why does Faker return different values with the same seed?
Check for a changed library or locale, an extra generator call, shared random state, or a date method that uses the current time. The same seed does not promise identical results across package upgrades, including changes within one major version.
How do I seed Faker.js, Python Faker and Bogus?
Faker.js: create a Faker instance and call its seed(42). Python Faker: create fake = Faker() and call fake.seed_instance(42). Bogus: use UseSeed(42) on your Faker<T>. Also pin dependencies and any reference dates.
Should I store the seed or the generated JSON?
Keep the seed and generation recipe for routine datasets. Save the exact failing record for a regression that must survive generator upgrades. A seed identifies a sequence; a saved fixture preserves the actual input.
Does seeding eliminate flaky tests?
It controls one source of variation. Clock reads, network responses, thread scheduling, shared state and nondeterministic serialization can still change a test. Fixed seeds also repeat the same coverage, so add explicit boundary cases and log seeds from exploratory runs.
More on test data practice
- Mock Data vs. Real Data: Why Teams Test With Fake Profiles
- Test Data Management: 9 Best Practices
- Synthetic Data for ML: Evaluation and Common Mistakes
- Email Validation Test Cases — CSV, JSON & 8 Validators
- What Is Synthetic Test Data? A Developer's Guide
- Test Data Generation Guide: Schemas, Rows & Edge Cases