14 min read

    Testing with AI: Why AI Code Needs Tests

    A single undefined value showed us: testing beats trust. With a Vitest setup for React projects.

    Thomas KnorrGeschäftsführer, datadice GmbHVeröffentlicht im Februar 2026

    KI-generierter Code braucht Tests

    *Ein einziger undefined-Wert hat uns gezeigt: Vertrauen ist gut, Testen ist besser.*

    Werkzeuge wie Claude Code, GitHub Copilot oder Cursor verändern die Softwareentwicklung grundlegend. Teams bauen Funktionen deutlich schneller als früher. CRUD-Systeme, Datenbank-Hooks und UI-Komponenten entstehen in kurzer Zeit. Diese Geschwindigkeit hat eine Schattenseite: Wir vertrauen dem generierten Code zu sehr. Wir deployen ihn ohne ausreichende Prüfung.

    Wir zeigen ein reales Beispiel aus einem unserer Kundenprojekte. Es belegt: Automatisierte Tests sind bei KI-gestützter Entwicklung Pflicht.

    Ein vermeidbarer Bug

    Wir haben in einem Tool für Sponsoring-Management (React, TypeScript, Firebase) mit Claude Code ein Aufgabensystem gebaut. Nutzer erstellen Aufgaben, weisen sie Mitarbeitenden zu, setzen Fälligkeitsdaten und verfolgen den Status. Der Code sah sauber aus. Der TypeScript-Compiler meldete keine Fehler. Der Build war grün.

    Dann erstellte der Kunde die erste Aufgabe. Es kam ein Fehler.

    Die Ursache war banal:

    // So sah der Code aus
    await addDoc(tasksRef, {
      title: values.title,
      assignedTo: values.assignedTo,
      dueDate: values.dueDate ? Timestamp.fromDate(values.dueDate) : undefined,
      relatedEntityType: values.relatedEntityType,  // undefined wenn nicht gesetzt
      relatedEntityId: values.relatedEntityId,      // undefined wenn nicht gesetzt
      createdAt: Timestamp.now(),
    });

    Firestore akzeptiert keine undefined-Werte. Füllt der Nutzer ein optionales Feld nicht aus, steht dort undefined. Firestore meldet dann: "undefined is not a valid Firestore value".

    TypeScript erkennt das Problem nicht. Der Typ Timestamp | undefined ist technisch korrekt. Der Build läuft fehlerfrei durch. Der Fehler tritt erst zur Laufzeit auf: Ein echter Nutzer schickt das Formular ab und die Anwendung bricht ab.

    Warum KI-Assistenten diesen Fehler machen

    Das Muster ist typisch für KI-generierten Code:

    1. KI kennt die API-Dokumentation, aber nicht die Eigenheiten zur Laufzeit.
    Claude weiß, dass Firestore eine NoSQL-Datenbank ist. Eine Eigenheit steht aber in keiner Typdefinition: undefined in JavaScript-Objekten führt bei Firestore zu einem Fehler. null oder ein weggelassenes Feld funktionieren dagegen.

    2. TypeScript erzeugt falsche Sicherheit.
    Der Code ist typkorrekt. dueDate?: Timestamp erlaubt undefined. TypeScript meldet keinen Fehler. Firestore lehnt den Wert zur Laufzeit trotzdem ab.

    3. Der Happy Path funktioniert immer.
    Beim Testen füllt man meist alle Felder aus. Dann funktioniert alles. Der Bug tritt nur bei leeren optionalen Feldern auf. Genau das passiert, sobald echte Nutzer die App verwenden.

    4. KI liefert schnell, aber nicht robust.
    Ein KI-Assistent liefert schnell funktionierenden Code. "Funktionierend" heißt dabei meist: Der Code kompiliert und sieht richtig aus. Ohne ausdrückliche Anweisung schreibt kein KI-Assistent von sich aus Tests.

    Ein einfacher Fix

    Eine Hilfsfunktion entfernt undefined-Werte aus Objekten:

    function stripUndefined<T extends Record<string, unknown>>(obj: T): Partial<T> {
      return Object.fromEntries(
        Object.entries(obj).filter(([, v]) => v !== undefined)
      ) as Partial<T>;
    }
    
    // Anwendung
    const cleanData = stripUndefined(data);
    await addDoc(tasksRef, { ...cleanData, createdAt: Timestamp.now() });

    Der Fix umfasst drei Zeilen Code. Wir haben den Bug in fünf Minuten behoben. Der Kunde hatte den Fehler aber bereits gesehen. Wir mussten erklären, warum eine Grundfunktion nicht lief. Dieses Vertrauen war beschädigt. Ein einziger Test verhindert solche Fehler.

    Testing-Setup mit Vitest

    Für React-Projekte mit Vite ist Vitest die naheliegende Wahl. Vitest nutzt dieselbe Konfiguration wie Vite. Es läuft sehr schnell und bietet eine Jest-kompatible API.

    Installation:

    npm install --save-dev vitest @testing-library/react @testing-library/jest-dom jsdom

    Konfiguration in vite.config.ts:

    export default defineConfig({
      test: {
        globals: true,
        environment: 'jsdom',
        setupFiles: ['./src/test/setup.ts'],
        include: ['src/**/*.{test,spec}.{ts,tsx}'],
      },
    });

    Das Setup dauert bei uns keine zehn Minuten. Danach stehen alle Werkzeuge bereit, um den Code abzusichern.

    Vier Kategorien für Tests

    Nicht jede Zeile Code braucht einen Test. Vier Kategorien gehören aber zu jeder Funktion:

    1. Schema-Validierung (Zod, Yup)
    Jedes Formular hat ein Validierungsschema. Tests prüfen drei Dinge: Pflichtfelder sind erzwungen. Grenzwerte gelten. Ungültige Werte werden abgelehnt.

    2. Hilfsfunktionen und Berechnungslogik
    Reine Funktionen ohne Seiteneffekte lassen sich leicht testen. Beispiele sind Rabattberechnungen, Datumslogik und Formatierungen.

    3. Datenaufbereitung für die Datenbank (der blinde Fleck)
    Diese Kategorie testet fast niemand. Gerade hier entstehen viele Bugs. Es geht um den Code zwischen Formular und Datenbank.

    describe('Firestore-Datenaufbereitung', () => {
      it('enthält keine undefined-Werte', () => {
        const taskData = {
          title: 'Test',
          dueDate: undefined,  // User hat kein Datum gewählt
        };
        const cleanData = stripUndefined(taskData);
        expect(Object.values(cleanData)).not.toContain(undefined);
      });
    });

    4. Zusammenspiel von Formular und Mutation
    Löst der Code den Nutzernamen korrekt auf? Konvertiert er das Datum richtig?

    CLAUDE.md als Leitplanke

    KI-Assistenten schreiben den Code. Deshalb müssen die Regeln dort stehen, wo die KI sie liest. Bei Claude Code ist das die Datei CLAUDE.md im Hauptverzeichnis des Projekts.

    Das gehört hinein:

    ## Testing Strategy
    
    ### PFLICHT: Tests bei jedem neuen Feature
    
    Bevor ein Feature als fertig gilt, MÜSSEN folgende Tests existieren:
    
    1. **Zod-Schema-Validierung**: Jedes neue Schema testen
    2. **Utility-Funktionen**: Jede reine Logik-Funktion
    3. **Firestore-Datenaufbereitung**: NIEMALS undefined an Firestore
    4. **Formular-Logik**: Transformation von Form-Werten zu DB-Daten
    
    ### Bekannte Firestore-Fallstricke
    Firestore akzeptiert KEIN undefined. Immer stripUndefined() verwenden.

    Die Wirkung: Claude Code liest diese Regeln bei jeder neuen Funktion. Es schreibt die Tests automatisch dazu. Die KI wird so zu ihrem eigenen Quality Gate.

    Unser Workflow für KI-Code

    Nach einigen Iterationen arbeiten wir mit diesem Workflow:

    Feature-Anforderung
        ↓
    Implementierung (KI schreibt Code)
        ↓
    Tests schreiben (KI schreibt Tests, weil CLAUDE.md es vorschreibt)
        ↓
    npm run test → Grün?
        ↓ Ja                    ↓ Nein
    npm run build            Bug fixen → zurück zu Tests
        ↓ Erfolgreich?
    Deploy

    Der Kern: Tests sind kein eigener Schritt, den jemand vergessen kann. Sie gehören zur Definition of Done.

    Zahlen aus unserem Projekt:

    • 39 Tests in drei Dateien, geschrieben in unter 15 Minuten
    • Laufzeit: unter 2 Sekunden, denn Vitest ist schnell
    • Abgedeckt: der undefined-Bug, der uns beim Kunden Vertrauen gekostet hat

    Fünf Erkenntnisse

    1. TypeScript reicht nicht.
    TypeScript prüft Typen zur Compile-Zeit. Das Verhalten zur Laufzeit erkennt es nicht. Ein Beispiel ist die Ablehnung von undefined durch Firestore. Tests schließen diese Lücke.

    2. Der Happy Path reicht nicht.
    Sind alle Felder ausgefüllt, funktioniert alles. Die Bugs stecken in optionalen Feldern, leeren Eingaben und Sonderfällen.

    3. KI braucht klare Regeln.
    Ohne ausdrückliche Anweisung schreibt kein KI-Assistent Tests. Die CLAUDE.md legt deshalb fest: keine Funktion ohne Tests.

    4. Tests müssen schnell laufen.
    Dauern Tests 30 Sekunden, überspringt man sie. Vitest läuft bei uns in unter 2 Sekunden. Damit entfällt jede Ausrede.

    5. Testen Sie, was schiefgehen kann.
    Der entscheidende Test prüft nicht, ob sich eine Aufgabe anlegen lässt. Er prüft, ob der Code undefined-Werte korrekt entfernt.

    Fazit: Testen ist besser

    KI-Assistenten machen uns produktiver. Produktivität ohne Qualitätssicherung gleicht aber dem Autofahren ohne Bremsen: Es geht schnell, bis es knallt.

    Der Aufwand ist klein:

    • Testing-Setup: bei uns 10 Minuten
    • Anpassung der CLAUDE.md: 5 Minuten
    • Danach schreibt die KI die Tests automatisch mit

    Der Nutzen:
    Sie haben weniger Bugs in Produktion. Sie führen weniger unangenehme Kundengespräche. Sie vertrauen Ihrem Code mehr.

    Ein einziger undefined-Wert in einem Firestore-Dokument hat diesen Artikel ausgelöst. Der Fix bestand aus drei Zeilen. Die Lektion bleibt: Vertrauen Sie keinem Code ohne Tests. Das gilt für eigenen Code und für KI-generierten Code.

    Was this helpful?

    Let us clarify in an initial consultation where AI makes a concrete difference in your company.