Kompletter Leitfaden

Testdaten aus deinem Datenbankschema generieren

Dein Schema beschreibt bereits alles, was die Daten erfüllen müssen: die Tabellen, die Typen, die Fremdschlüssel. Dieser Leitfaden führt durch die Generierung eines vollständigen, ladbaren Datensatzes daraus, egal ob dein Schema in SQL, Django oder Prisma lebt, und was eine Datenbank, die lädt, von einem Haufen loser Zeilen trennt.

SeedBase · ~9 Min. Lesezeit

Es gibt zwei Wege, eine Datenbank für Entwicklung oder Tests zu füllen. Du kannst Werte Spalte für Spalte erfinden, oder du leitest den ganzen Datensatz aus dem Schema ab, das du ohnehin schon geschrieben hast. Der erste ist schnell bei drei Zeilen und fällt in dem Moment auseinander, in dem deine Daten Beziehungen haben. Dieser Leitfaden handelt vom zweiten.

Was "aus einem Schema generieren" wirklich bedeutet

Ein Schema ist ein Vertrag. Es sagt, dass orders.customer_id auf eine echte customers.id zeigen muss, dass email eindeutig und nicht null ist, dass eine Bestellung viele Positionen hat. Aus dem Schema zu generieren bedeutet, dass ein Werkzeug diesen Vertrag liest und Daten erzeugt, die ihn einhalten: Kinder verweisen auf existierende Eltern, Inserts kommen eltern-zuerst heraus, und das Ergebnis lädt mit aktivierten Constraints in Postgres oder MySQL.

Der Gegensatz ist ein Generator, der jede Zelle für sich befüllt. Er erzeugt plausibel aussehende Werte und eine Datenbank, die nicht lädt, denn eine referenzielle Datenbank ist das Gegenteil eines Sacks unabhängiger Zellen.

Die vier Dinge, die schema-getriebene Daten richtig machen müssen

1. Fremdschlüssel gehen auf

Jede order.customer_id ist die id eines Kunden, der tatsächlich erzeugt wurde, auch wenn die Schlüssel UUIDs sind oder Lücken haben. Mach das falsch, und der Ladevorgang scheitert beim ersten Kind-Insert:

ERROR:  insert or update on "order_items" violates foreign key
        constraint "order_items_product_id_fkey"
DETAIL:  Key (product_id)=(173) is not present in table "products".

Warum Ad-hoc-Faker genau hier auflaufen, haben wir in warum Faker bei Testdaten mit Fremdschlüsseln bricht auseinandergenommen.

2. Inserts kommen in Abhängigkeitsreihenfolge heraus

Ein echter Ladevorgang fügt customers vor orders und orders vor order_items ein. Diese Reihenfolge ist eine topologische Sortierung des Fremdschlüssel-Graphen, und Zyklen oder Selbstreferenzen brauchen Sonderbehandlung. Ein schema-bewusster Generator erledigt das für dich, sonst deaktivierst du beim Laden die Constraints und lieferst Daten aus, die in Produktion nie existieren könnten.

3. Produktionsnahe Verteilungen

Gleichförmiger Zufall gibt jedem Kunden ungefähr gleich viele Bestellungen. Produktion hat einen langen Schwanz: die meisten Kunden haben eine oder zwei, eine Handvoll hat hunderte. Genau dieser Schwanz ist die Stelle, an der Pagination, N+1-Queries und langsame Joins umkippen, ein Datensatz, der ihn versteckt, testet also das Falsche.

4. Werte sind kohärent und abgeleitete Werte rekonzilieren

Die E-Mail sollte zum Namen passen, die Stadt zur PLZ und zum Land, und order.total sollte der Summe seiner Positionen entsprechen. Unabhängige Generierung pro Zelle bricht alle drei, was jeden Test, der ein abgeleitetes Feld prüft, klammheimlich ungültig macht.

Starte von deinem Schema, in welcher Form es auch vorliegt

Du solltest ein Schema, das du ohnehin pflegst, nicht neu beschreiben müssen. Zeig den Generator auf die Source of Truth, die du hast:

SQL-Dump oder DDL

CREATE TABLE customers (
  id    integer PRIMARY KEY,
  email varchar(160) UNIQUE NOT NULL,
  name  varchar(120) NOT NULL
);
CREATE TABLE orders (
  id          integer PRIMARY KEY,
  customer_id integer NOT NULL REFERENCES customers(id),
  total       decimal(10,2),
  ordered_at  timestamp NOT NULL
);

Komplette Anleitung: Testdaten aus einem SQL-Schema generieren.

Django models.py

Importiere deine models.py, und die Beziehungen (ForeignKey, ManyToMany) kommen mit, die generierten Zeilen respektieren sie also. Siehe Django-Testdaten und die Schritt-für-Schritt-Anleitung eine Django-Datenbank befüllen.

Prisma schema.prisma

Füge dein schema.prisma ein, und die @relation-Direktiven steuern die Fremdschlüssel. Mehr in Prisma-Testdaten und Prisma-Seed-Daten ohne Seed-Skript.

Womit du auch startest, es wird in ein internes Modell geparst, die vier Eigenschaften oben gelten also auf dieselbe Weise. Das ist der Sinn, vom Schema aus zu arbeiten: eine Quelle, konsistentes Ergebnis.

Drei Wege, die Datenbank zu füllen

  1. Synthetisch von Grund auf. Generiere einen frischen Datensatz aus dem Schema. Keine echte Zeile ist beteiligt, das ist die sauberste Haltung für Staging, Demos und CI.
  2. Eine Produktionskopie maskieren. Wenn du die exakte Form und das Volumen echter Daten brauchst, ersetze die PII an Ort und Stelle und halte die Schlüssel intakt. Anleitung: Produktionsdaten fürs Staging maskieren und DSGVO-konforme Anonymisierung.
  3. Eine Teilmenge herausschneiden. Nimm eine fremdschlüssel-konsistente Scheibe einer großen Datenbank, sodass jedes referenzierte Eltern-Objekt mitsamt seinen Kindern mitkommt, und maskiere sie dann.

Bring es in deine Datenbank

Exportiere das Ergebnis als SQL, CSV oder JSON und lade es, oder pushe es direkt in eine verbundene Datenbank. Aus dem VS Code- oder JetBrains-Plugin wird die Verbindung automatisch aus deiner .env oder schema.prisma erkannt, es ist also ein Schritt:

psql "$DATABASE_URL" -f seed.sql
# oder im Editor: Load into Database / Reset & Reseed

Brauchst du eine API statt einer Datenbank? Jede Generierung lässt sich auch als read-only Mock-REST-API mit denselben fremdschlüssel-konsistenten Daten ausliefern.

Für CI ist die Generierung geseedet: derselbe Seed reproduziert bei jedem Lauf denselben Datensatz, ein fehlschlagender Test ist also reproduzierbar statt jedes Mal ein frischer Würfelwurf.

Wo das hineinpasst

Eine ehrliche Einschränkung. Wenn dein Test wirklich nur drei feste Zeilen braucht, ist eine winzige handgeschriebene Fixture völlig in Ordnung. Aus dem Schema zu generieren zahlt sich aus, wenn die Datenbank relational ist und du willst, dass sie sich wie Produktion verhält. SeedBase wurde gegen ein echtes Projekt mit 20 Apps und 226 Tabellen getestet, daher kommen die Fremdschlüssel-Reihenfolge und die Verteilungsbehandlung. EU-gehostet, keine Drittanbieter-Tracker, alles exportierbar.

FAQ

Was bedeutet es, Testdaten aus einem Schema zu generieren?

Du leitest die Daten aus deinen Tabellen, Spalten und Beziehungen ab, statt Werte einzeln zu erfinden. Der Generator liest die Fremdschlüssel, Typen und Constraints und erzeugt einen Datensatz, in dem Kinder auf existierende Eltern verweisen, die Inserts in Abhängigkeitsreihenfolge herauskommen und das Ergebnis mit aktivierten Constraints lädt.

Aus welchen Schema-Formaten kann ich generieren?

Aus einem SQL-Dump oder DDL, einer Django-models.py oder einem Prisma-schema.prisma. Alle drei werden in dasselbe interne Modell geparst, das Ergebnis ist also fremdschlüssel-konsistent, egal aus welcher Quelle.

Warum nicht einfach Faker oder Zufallswerte nutzen?

Faker ist großartig für einen einzelnen Wert, erzeugt aber jeden unabhängig, ohne jeden Begriff von Fremdschlüsseln, Insert-Reihenfolge oder zeilenübergreifender Konsistenz. In großem Maßstab heißt das verwaiste Referenzen und gleichförmige Verteilungen, die echte Bugs verstecken. Mehr dazu hier.

Sind die generierten Daten für CI reproduzierbar?

Ja. Die Generierung ist geseedet, derselbe Seed reproduziert also bei jedem Lauf denselben Datensatz.

Kann ich auf echte Produktionsdaten verzichten?

Ja. Generiere synthetische Daten aus dem Schema, damit keine echte Zeile die Produktion verlässt, oder maskiere eine Kopie, wenn du die exakte Form echter Daten brauchst. Mehr zum Maskieren.

Erzeuge eine echte Datenbank aus deinem Schema

Zeig SeedBase auf dein SQL-, Django- oder Prisma-Schema und bekomm eine befüllte, fremdschlüssel-konsistente Datenbank mit realistischen Verteilungen. Free-Tier, keine Kreditkarte.

  • Jeder FK geht auf
  • Long-Tail-Verteilungen
  • SQL / CSV / JSON
  • EU-gehostet
Testdaten generieren, kostenlos

Oder live ausprobieren: Editor öffnen, ohne Anmeldung