Seed your fake data generator and log the seed, so any failing run can be replayed exactly. With Python's Faker, call Faker.seed() for the shared generator or seed_instance() for one instance. Pin the library version too, because the docs say results are not guaranteed to match across patch versions.
Why this matters for security testing
Fake data keeps real customer data out of test environments, which is the safe default. But random fake data brings a new problem: a test that fails once and never again. A security defect found that way cannot be reproduced, reported or fixed.
Seeding fixes it. The same seed and the same library version produce the same data, so a failure becomes a recipe, not a rumor.
The two seeding options
From the Faker documentation:
Faker.seed(4321)seeds the shared random number generator used by all generators.fake.seed_instance(4321)seeds only that generator's own random instance, separate from the shared one.
Both give identical output for identical calls, provided the Faker version is the same. In pytest, the faker fixture can be seeded by defining a faker_seed fixture.
Use the shared seed for simple suites. Use instance seeds when parallel test workers must not interfere with each other.
A practical pattern
- Pick a seed per run. A fixed seed gives stable CI. A random seed finds more variety.
- Do both: a fixed seed on pull requests, a random seed nightly.
- When using a random seed, print it at the start of the run and attach it to any failure output.
- To replay, set the same seed through an environment variable.
- Once the failure is understood, copy the minimal data that triggers it into an explicit test, so you no longer depend on the generator.
Step five is the important one. Generators change. Data tables are updated, formats evolve. The docs warn that seeded output can shift between versions, and say to pin to an exact patch version if your tests hardcode seeded output. An explicit fixture does not have that weakness.
What fake data cannot do
| Concern | Fake data helps | Fake data does not help |
|---|---|---|
| Privacy of real people | Yes, nothing real is used | Not if you copy real values in |
| Realistic edge cases | Partly | Real systems have odd values generators never produce |
| Reproducibility | Yes, with seeds | Not across version changes unless pinned |
| Security payloads | No | Add hostile strings by hand or via fuzzers |
Fake names and emails are polite. They do not contain a quote character, a very long string or a path traversal attempt unless you add one. Keep a small hand written list of hostile values beside the generated ones.
Also keep fake credentials obviously fake and clearly marked, so they never get mistaken for real ones in a review.
Quick rules
- Never hardcode the seed in a way that hides it from failure output.
- Never commit generated files you cannot regenerate.
- Never mix real and fake records in one fixture file.
Try it yourself
Click through it at your own pace, or open it full screen. Find the version column, since pinning exact versions is what keeps seeded output stable.
Safeguard's SBOM and dependency scanning gives you that inventory, and the free scan is a quick way to see it for your own project.
Quick check
Is a seeded fake value still safe to publish in a bug report?
Yes if it was generated, but check that it does not accidentally match a real person or a real secret format.
Why pin the library version?
Faker documents that seeded results are not guaranteed to be the same across patch versions, so an upgrade can change your data.
Sources
Last reviewed: 19 October 2026.