SheepDev

SQL and test data

Generate repeatable test data without real records

Tools to use

A bug disappearing after refresh may mean the data changed, not that the bug was fixed. Fresh random fixtures are useful but can erase reproduction conditions. Seeded generation recreates data from the same settings. Build a small fictional dataset you can share without copying real users' information.

Start with three rows and four columns

Choose three rows, seed 42 and JSON. Define id as integer, name as name, active as boolean and email as email in that order. The current implementation produces the following. Names come from a fixed sample list and addresses use example.test; no real people or contacts are retrieved.

Fictional data with seed 42
[{"id":1,"name":"Haru","active":false,"email":"user1@example.test"},{"id":2,"name":"Ren","active":false,"email":"user2@example.test"},{"id":3,"name":"Mina","active":false,"email":"user3@example.test"}]

Generate again with identical settings and check equality. These names do not model specific users. Keep fixtures clearly marked and out of production notification flows. Using fictional addresses does not replace disabling delivery in a test environment.

The schema order is part of reproducibility

With seed 43, row two is Haru and row three Aoi with active true; row one remains unchanged. Changing a seed need not change every cell. Integer and email values derive from row numbers, so they stay fixed. Distinguish random-valued types from deterministic row-based types.

Adding or reordering random-consuming columns can change later values even with the same seed. Record column names, types, order, count and format alongside the seed. Future generator changes may alter output, so long-lived regression tests can preserve the necessary generated fixture itself.

JSON, CSV and SQL represent the data differently

Switching to CSV gives headers and rows; SQL gives INSERT for the configured table. A JSON boolean printed as true or false in CSV is not guaranteed to be read back as boolean. Check the receiving tool's type interpretation, not just how the output looks.

SQL output only creates text. It does not inspect constraints, defaults or foreign keys, so matching column names is not permission to insert into production. Prepare a minimal test schema and keep the fixture isolated from external notifications or billing flows.

Random rows alone do not cover boundaries

Seed 42 produces false for all three active values, so it does not test the true state. Long names, empty strings, NULL, quotes, emoji and maxima will not all appear by chance. Add deliberate constants or explicit fixtures for those conditions. Random examples and designed boundary cases serve different roles.

Count boundaries need deliberate tests too. The generator supports 1–1,000 rows; represent an empty list in your test fixture rather than requesting zero. For pagination, choose exactly one page and one item beyond it. More rows are not automatically better coverage.

Reproducible randomness is not for secrets

Reproducing values from a seed is useful for testing but unsuitable for secrets. Do not treat generated strings or emails as authentication tokens or real accounts. Use a cryptographic token generator for secret randomness, and keep those secrets out of reproducible fixtures.

A useful bug report includes schema, seed, count, format, expected behavior and observed behavior. Reduce to the smallest reproducible set. Replacing 'I tried lots of random data' with 'these three rows trigger this problem' also makes regression checks precise.

Turn a randomly discovered failure into a stable fixture

If a large random dataset breaks the screen once, success with another seed does not mean the defect is fixed. Reproduce the failure by retaining seed, schema, column order, count and format. Generator versions can change the sequence, so a long-term regression test can preserve the actual fictional failing rows as a fixed fixture.

Then remove unrelated rows or columns while preserving the failure. A thousand-row problem may reduce to two equal display names, or it may require a count just over a threshold. Fix the neighboring counts in that case. Random generation explores combinations; a focused fixture explains the discovered condition. Minimization must preserve the failure, not accidentally remove its cause.

Fictional names and emails do not represent real user behavior or data distributions. Performance or capacity tests may need specific lengths, cardinalities and duplication patterns. Define those characteristics separately. If the generator's simple types do not cover them, record that limitation rather than treating row count as proof of adequate testing.

Sources

Tools to use

Guides →