Make the edge case
repeatable.

Describe the data your importer should survive.
Seed it. Break it on purpose. Get the same fixture again.

A small language for test data.
Real parsing. Explicit seeds.
Deliberately imperfect records.

01 Source

.fixture

Ctrl / ⌘ + Enter to run

02 Result

waiting for source

Your fixture takes shape here.

Run the source to inspect generated records.

JSON distinguishes missing, null, and empty strings. CSV maps all three to empty cells.

Ready to run.

Local · no accounts · no API

Small enough to learn.
Precise enough to trust.

Five types. Seven generators. Three ways to make a record imperfect.

Read the full reference ↗Demo outline ↗

Give chance a seed.

fixture imports seed 42 { … }

One required seed, one defined draw order. The same source produces the same data.

Describe a field.

age: int = int(18, 85);

Use id, int, string, bool, or date. Values are typed, never inferred.

Connect the records.

person_id: id = ref(people.id);

Reference a generated ID in an earlier table. Relations use values that actually exist after mutations.

Make trouble explicit.

id: id = seq(1) duplicate every 4;

missing every 3 omits a key. null every 3 keeps it with null. duplicate every 4 copies the previous final ID.

Bounded by design.

20,000 total rows · 200,000 cells · 8 tables · 32 fields per table. No loops, functions, file access, or source execution. Work runs in a cancellable worker.