Workflow

Tests bestanden? So prüfst du, ob sie liefen

Coding-Agenten melden grüne Tests, die nach der letzten Änderung nie liefen. Woran du das erkennst und wie du den Lauf belegst statt ihn zu glauben.

"Alle Tests laufen grün." Der Satz kommt vom Agenten im selben ruhigen Ton, egal ob er stimmt oder nicht. Genau das ist das Problem, das wir im Artikel Der Agent spielt, du bist jetzt Co-Trainer beschrieben haben: Das Warnsignal fehlt. Der Agent klingt nicht unsicherer, wenn er sich irrt.

Bei Tests ist der Irrtum meistens kein böser Wille. Es geht hier nicht darum, dass ein Agent Tests umschreibt, bis sie grün sind. Das ist Reward Hacking, dazu gibt es einen eigenen Artikel. Hier geht es um etwas Banaleres: Die Tests liefen, aber am falschen Stand, nur zum Teil oder gar nicht. Und die Meldung "bestanden" ging trotzdem raus.

Vier Arten, wie "bestanden" falsch sein kann

MusterWas passiert istTypisches Indiz
Veralteter LaufTests liefen grün, danach hat der Agent weiter editiert und den alten Erfolg gemeldetLetzter Testbefehl liegt vor dem letzten Edit
Falscher AusschnittNur eine Datei oder ein Filter (-k, --testNamePattern, --tests) lief, gemeldet wird die ganze SuiteFilter im Befehl, auffällig wenige Tests
Verschluckter Exit-Codenpm test 2>&1 | tail -20: Der Exit-Status ist der von tail, also 0Pipe im Befehl, kein set -o pipefail
Gar kein LaufDie Meldung stützt sich auf nichts im ProtokollKein Testbefehl im Verlauf

Dazu kommt ein fünfter, seltener Fall: Der Lauf war rot, der Agent hat die Ausgabe umgedeutet. Im Issue #46940 meldete Claude Code "4966/4966 ALL PASSED". Tatsächlich bestanden nur 4985 von 4992 Werten, und der Agent hatte die Gesamtzahl auf 4966 gesenkt. Das ist ein Nutzerbericht, Anthropic hat das Issue als "not planned" geschlossen.

Was die Zahlen hergeben

Eine repräsentative Quote gibt es nicht. Es gibt drei Stichproben, die in dieselbe Richtung zeigen.

150 Sessions, ein Team. Im Issue anthropics/claude-code #104504 vom 23.10.2026 hat ein Team 357 "Tests pass"-Aussagen aus 150 eigenen Claude-Code-Sessions gegen das Sitzungsprotokoll gelegt, also gegen Befehle, Exit-Codes, Dateiänderungen und Zeitstempel. 178 waren durch einen passenden Lauf gedeckt, 80 durch keinen, 5 widersprachen dem Protokoll, 92 ließen sich nicht entscheiden. Von den ungedeckten Fällen, die das Team genauer untersucht hat, waren 32 von 36 veraltete Läufe. Und 1.514 von 2.084 Testläufen (73 Prozent) liefen durch tail oder head. Die Autoren schreiben selbst, dass das die Sessions eines Teams sind und keine Schätzung für alle.

101 Aussagen, ein Entwickler. Vinzenz Eiberger hat zwei Wochen lang seine eigenen Sessions mit Claude Code und Codex ausgewertet (DEV, 24.09.2026). 35 von 101 Aussagen stimmten zum Zeitpunkt der Meldung nicht, 34 davon waren veraltete Läufe. Die Einstufung haben KI-Subagenten vorgenommen, die Aufteilung nach Agent will er ausdrücklich nicht als Modellvergleich verstanden wissen.

8.600 Sessions, breiter gefasst. Transluce hat im August 2026 reale Sessions nach "Overselling" durchsucht, also nach übertriebenen Erfolgs- und Testmeldungen. Im öffentlichen Datensatz traf das auf 34,7 Prozent der Sessions zu, schwere Fälle waren aber nur 1,8 Prozent. In internen Sessions lag der Wert bei 5,7 Prozent. Die Kategorie ist breiter als "Tests nicht gelaufen", die Zahl taugt also nicht als Quote für unser Problem.

Was sich daraus ableiten lässt: Der häufigste Fehler ist nicht der erfundene Testlauf, sondern der veraltete. Der Agent hat wirklich getestet, nur nicht den Stand, den du gerade bekommst.

Sechs Fragen an die Meldung

Für die Prüfung brauchst du kein Werkzeug, nur den Verlauf der Session oder die PR-Beschreibung.

  1. Steht der Befehl da? "Alle Tests bestanden" ohne Befehl ist eine Behauptung. pytest -k parser ist eine Auskunft, und zwar über einen Ausschnitt.
  2. Passen Zähler und Dauer? Eine Suite mit 3.000 Tests in zwei Sekunden ist verdächtig. Weniger Tests als beim letzten Lauf auch. Wie viele wurden übersprungen?
  3. Lief der Test nach dem letzten Edit? In beiden Auswertungen oben scheiterten die meisten falschen Meldungen genau hier. Im Verlauf siehst du die Reihenfolge.
  4. Hängt eine Pipe dran? Bei | tail oder | head ohne set -o pipefail sagt der Exit-Code nichts über die Tests.
  5. Ist ein Filter gesetzt? -k, --testNamePattern, -Dtest=, --tests, --findRelatedTests, --changed: alles legitim, aber dann ist es nicht die Gesamtsuite.
  6. Ist die CI am Head-Commit grün? Nicht irgendein grüner Haken, sondern der Check an genau dem Commit, der gemergt werden soll.

Die einfachste Vorbeugung ist eine Zeile in der Projektanweisung. Eiberger empfiehlt genau das, und es kostet nichts:

PromptAGENTS.md / CLAUDE.md · Regel für Testmeldungen

Wenn du meldest, dass Tests bestehen:

  • Führe die Tests nach deiner letzten Codeänderung erneut aus.
  • Nenne den exakten Befehl, den Exit-Code und die Zähler (bestanden, fehlgeschlagen, übersprungen).
  • Leite Testausgaben nicht durch tail oder head, oder setze vorher set -o pipefail.
  • Wenn du nur einen Teil der Tests ausgeführt hast, sag welchen.

Eine Garantie ist das nicht. Eine Anweisung kann der Agent übersehen. Sie macht Abweichungen aber sichtbar, weil eine Meldung ohne Befehl und Exit-Code dann selbst schon auffällt.

Fallen im Testrunner

Manche Lücken liegen gar nicht beim Agenten, sondern in den Standardeinstellungen der Werkzeuge. Ein Agent, der einen Filter setzt, der nichts trifft, bekommt je nach Runner trotzdem Grün.

RunnerFalleWas hilft
pytestExit-Code 5 heißt "keine Tests gesammelt", Skip-Gründe sieht man standardmäßig nichtExit-Code 5 in der CI als Fehler werten, -rs oder -ra für die Zusammenfassung (Exit codes)
Jest--passWithNoTests lässt einen Lauf ohne gefundene Tests bestehen, --onlyChanged und --findRelatedTests verengen die MengeFlag in der CI nicht setzen, Filter im Befehl prüfen (Jest CLI)
VitestOhne Tests schlägt der Lauf standardmäßig fehl, außer passWithNoTests ist an. --changed verengtEinstellung im Projekt prüfen (Vitest)
Maven-DskipTests kompiliert die Tests, führt sie aber nicht aus. Der Build ist trotzdem grünIm Befehl danach suchen, maven.test.failure.ignore nicht setzen (Surefire)
GradleTests laufen nur, wenn sich Code oder Tests geändert haben, sonst meldet der Task UP-TO-DATE oder FROM-CACHE--rerun erzwingt den Lauf, ignoreFailures nicht setzen (Gradle)

Gerade Gradle ist tückisch, weil es kein Fehler ist: Der Build ist schnell und grün, weil er zu Recht nichts zu tun hatte. Wer nur auf "BUILD SUCCESSFUL" schaut, sieht nicht, ob überhaupt ein Test lief.

Belegen statt glauben: Hooks im Agenten

Alle großen Coding-Agenten haben inzwischen Hooks, also Skripte, die bei bestimmten Ereignissen laufen. Zwei Arten sind hier nützlich: Hooks nach jedem Befehl, die mitschreiben, was lief und wie es ausging. Und Hooks beim Beenden, die den Agenten zurückschicken, wenn etwas fehlt.

AgentNach dem BefehlBeim Beenden blockieren
Claude CodePostToolUse, Fehler laufen über PostToolUseFailureStop mit "decision": "block" (Doku)
CodexPostToolUseStop mit "decision": "block" (Doku)
CursorafterShellExecution, postToolUsestop mit followup_message, Standardgrenze fünf Runden (Doku)
GitHub CopilotpostToolUseagentStop mit "decision": "block" (Doku)
Gemini CLIAfterToolAfterAgent mit "deny" erzwingt einen neuen Versuch (Doku)

Die Idee für einen Stop-Hook: Der Hook merkt sich den Zeitpunkt der letzten Dateiänderung und des letzten Testbefehls. Will der Agent fertig sein und der Test liegt vor der Änderung, schickt der Hook ihn mit einer Begründung zurück. Claude Code, Codex und Copilot haben einen Schleifenschutz eingebaut (stop_hook_active), damit der Agent nicht endlos zurückgeschickt wird.

Zwei Dinge musst du beim Bauen wissen. Bei Claude Code steht der Exit-Code eines Shell-Befehls nicht in der Eingabe von PostToolUse. Das Ereignis feuert nur bei Erfolg, Fehlschläge kommen über PostToolUseFailure. Wer nur das eine abonniert, sieht nur die Hälfte. Und Codex weist in seiner Doku darauf hin, dass das Format der Sitzungsprotokolle keine stabile Schnittstelle für Hooks ist. Ein Hook, der das Protokoll parst, kann mit dem nächsten Update brechen.

Die größere Einschränkung: Hooks laufen lokal. Wer sie ändern kann, kann sie auch abschalten. Für schnelle Rückmeldung an den Agenten sind sie ideal. Als Nachweis gegenüber einem Reviewer oder Auditor reichen sie allein nicht. Das gleiche Prinzip gilt für Git-Hooks, dazu mehr in Quality Gates gegen KI-Fehler.

Am Merge-Stand prüfen

Der eigentliche Beleg entsteht in der CI. Dort laufen die Tests unabhängig vom Agenten, an einem bekannten Commit, mit einem Ergebnis, das am Pull Request hängt.

Bei GitHub heißt das: Branch Protection oder Ruleset mit Pflicht-Check. Dabei gibt es zwei Stolperstellen:

  • Ein übersprungener Job zählt als Erfolg. Wenn dein Test-Job per if: übersprungen wird, meldet er laut GitHub-Doku "Success" und erfüllt den Pflicht-Check. Pflicht-Checks dürfen laut Doku erfolgreich, übersprungen oder neutral sein.
  • Ein übersprungener Workflow blockiert dagegen. Fällt der ganze Workflow wegen eines Pfad- oder Branch-Filters weg, bleibt der Check laut Workflow-Syntax-Doku auf "Pending". Das ist das Gegenteil, aber genauso verwirrend.

Mit "Require branches to be up to date before merging" testet die CI den Stand nach dem Rebase auf die Basis. Wer viele parallele Pull Requests hat, nimmt die Merge Queue: Sie testet die zusammengeführten Änderungen auf einem temporären Branch. Der Workflow muss dafür auf das Ereignis merge_group reagieren, sonst läuft der Check nie.

Bei GitLab heißen die Gegenstücke Merged results pipelines (Premium und Ultimate) und die Einstellung "Pipelines must succeed", die in allen Stufen verfügbar ist. Übersprungene Pipelines blockieren dort standardmäßig, das ist strenger als bei GitHub.

Lass die CI außerdem einen Testreport als Artefakt ablegen, zum Beispiel JUnit-XML. Dann stehen Zähler für bestandene, fehlgeschlagene und übersprungene Tests neben dem Commit, und niemand muss sich auf eine Zusammenfassung verlassen.

Ein fertiger Dienst als Beispiel

Es gibt erste Anbieter, die das Sitzungsprotokoll des Agenten auswerten und daraus ein Merge-Gate machen. Einer davon ist Code Telemetry. Offenlegung: Den Anstoß zu diesem Artikel gab uns Elliot Gardiner, der Gründer, per Mail. Er hat seine Rolle offen genannt, bezahlt wurde nichts, und das Produkt steht hier als ein Beispiel, nicht als Empfehlung.

Laut Hersteller prüft der "Grader" die aufgezeichnete Session gegen eine Policy, etwa "npm run test:unit wurde erfolgreich ausgeführt", und setzt am Pull Request einen Check, den GitHub als Pflicht verlangen kann. Eine Option verlangt, dass die Pflicht-Checks nach der letzten Änderung und vor dem Push bestanden wurden. Das ist genau unsere Lücke.

Die Grenzen nennt der Hersteller selbst: Ein Bestehen beweist keine Korrektheit, fehlende Telemetrie beweist nicht, dass etwas nicht passiert ist, und die CI wird nicht ersetzt. Pull Requests ohne Session lässt der Check standardmäßig durch. Die Doku warnt außerdem, dass jemand mit Push-Rechten den Check fälschen kann, wenn man den Workflow nicht per Ruleset absichert.

Für Teams im DACH-Raum zählt vor allem die Datenhaltung. Laut Datenschutzerklärung (Stand 02.11.2026) laufen die Daten bei AWS in den USA, als Unterauftragsverarbeiter sind unter anderem OpenAI und Anthropic genannt. Erfasst werden Befehle, Dateipfade und Exit-Codes, je nach Einstellung auch Prompts und Codeausschnitte. Inhalte sind standardmäßig geschwärzt, und der Anbieter sagt zu, die Daten weder zu verkaufen noch für Modelltraining zu nutzen. Die DSGVO, eine EU-Region oder ein Auftragsverarbeitungsvertrag kommen in der Erklärung nicht vor. Der Preis liegt laut Website bei 50 US-Dollar pro Person und Monat.

Wer die Daten im Haus halten will, kommt mit Bordmitteln weit: Hooks, die mitschreiben, plus Pflicht-Checks in der CI. Claude Code und Codex können zusätzlich OpenTelemetry-Daten an ein eigenes Backend schicken. Was ein Dienst wie Code Telemetry darüber hinaus bietet, ist die fertige Auswertung des Protokolls gegen eine Regel.

Wenn Nachweise Pflicht sind

Für Hersteller von Produkten mit digitalen Elementen wird das Thema ab Dezember 2027 formal. Der Cyber Resilience Act verlangt in Anhang VII Nr. 6, dass die technische Dokumentation Berichte über die durchgeführten Tests enthält. Diese Dokumentation muss laut Art. 13 Abs. 13 mindestens zehn Jahre aufbewahrt werden, oder für den Supportzeitraum, wenn der länger ist. Die meisten Pflichten gelten ab 11.12.2027, die Meldepflichten für aktiv ausgenutzte Schwachstellen schon seit 11.09.2026.

Der CRA sagt nichts über Coding-Agenten. Er verlangt Testberichte, nicht Sitzungsprotokolle. Aber ein Testbericht, der auf "der Agent hat gesagt, es ist grün" beruht, wird in einem Audit nicht weit tragen. Ein Report aus der CI, der an einem Commit hängt, schon. Ob ein Produkt unter den CRA fällt, ist eine Einzelfallfrage.

Womit du anfängst

Du musst nicht alles auf einmal umsetzen. Drei Schritte, nach Aufwand sortiert:

  1. Heute: Die Regel aus dem Prompt-Block oben in AGENTS.md oder CLAUDE.md. Ab dann ist jede Testmeldung ohne Befehl und Exit-Code ein Signal zum Nachfragen.
  2. Diese Woche: Pflicht-Check in der CI, der die Tests am Head-Commit erneut ausführt. Prüfen, ob ein Test-Job per if: übersprungen werden kann. Testreport als Artefakt.
  3. Wenn es passt: Ein Stop-Hook, der den Agenten zurückschickt, wenn der letzte Testlauf vor der letzten Änderung liegt.

Im Pull Request hilft das Ledger aus der 79-Prozent-Falle: Die Zeile "Verifiziert" bekommt dann einen konkreten Inhalt, nämlich Befehl, Exit-Code und Commit. Damit wird aus "der Agent sagt, es geht" etwas, das ein Kollege in einer Minute nachprüfen kann.

Quellen25