Test data that
can't contradict itself.

Most fake-data tools fill each field on its own, so a record can be valid field by field and impossible as a whole. TDC builds the record instead of the fields — and gives you the very same rows in TypeScript, Python, Java, C# and Rust.

Open SourceMIT License

A record that makes sense

Fill every field independently and each value is fine on its own — while the record they add up to is impossible. A patient who is female and carries a diagnosis only men get. A Fiat with a model that belongs to a Nissan. A city from one state wearing the postcode of another.

Nothing is technically wrong, so nothing complains. You find out later: a test fails and looks like an application bug until someone opens the fixture, or a load test spends its whole run in the validator instead of in the feature it was supposed to measure.

TDC works the other way round. A field can be tied to a field chosen before it, and it then draws only from what that choice leaves reachable. The wrong list is not filtered out afterwards — it was never in reach.

Each field drawn on its own PATIENT RECORD Gender Female Name Robert Diagnosis Prostatitis Each field follows the choice above it PATIENT RECORD Gender Female Name Elizabeth Diagnosis Migraine
The same three fields, filled two ways. On the left each one was drawn on its own. On the right each one follows from the choice above it.

The proportions you asked for

Ask a seeded generator for a 60/40 split and you get roughly 60/40 — usually. Over ten rows "roughly" can mean seven and three, and the edge case you were trying to cover is simply not in the data.

TDC allocates whole rows to groups before it fills any of them, so a 60/40 split over ten rows is six and four. Every run. The same holds several levels down: shares inside a group are applied inside that group, so a rule like "half of the men, a quarter of the women" comes out exact on both sides.

A seeded draw · asked for 60 / 40 7 / 3 5 / 5 6 / 4 TDC · asked for 60 / 40 6 / 4 6 / 4 6 / 4
Three runs of each, asking for the same 60/40 split. One drifts with the seed; the other lands on the number every time.

A signal you can draw

Ready-made distributions come in fixed shapes — a bell, a decaying tail. Real data often has a shape that is not on that list: demand that climbs toward noon and falls at night, two seasonal peaks where the second one is higher, the silhouette of a chart somebody screenshotted for you.

So draw it. Hand TDC a drawing or a picture of a curve, and its outline becomes the shape of your data, stretched across however many rows you asked for — ten thousand or ten million. Nothing is pre-rendered; each row works out its own point on the line.

the picture you hand over the rows it produces row 1 last row
The line is the picture that was handed over. The dots are generated rows, each one landing on it.

The same data in five languages

A Java service, a Python pipeline and a TypeScript test suite usually agree on what the test data should look like, and then each of them builds its own. The three sets drift, and the bug that only reproduces in one of them costs a day to find.

TDC is one engine written five times over — TypeScript, Python, Java, C# and Rust — and held to a single shared suite of cases. One description and one seed produce the same rows in all five, down to the byte. That is checked on every change rather than promised.

TypeScript Python Java C# Rust SAME DESCRIPTION · SAME SEED 1,Female,Elizabeth,342,Male,Robert,513,Female,Patricia,284,Male,James,45 sha-256 3bca9c07…
One description, one seed, five implementations — and one output they all have to match.

And a few more problems it takes off your hands

All of it described in a short file, and none of it written in code.


The documentation is where all of this is actually explained.