Was macht crucible?
Wann diese Fertigkeit verwenden
Wenn Sie aufgefordert werden, Unit-Tests in TypeScript-Projekten zu schreiben, zu reparieren oder zu überprüfen.
Wann diese Fertigkeit NICHT verwenden
Beim Schreiben von End-to-End-, Integrations-, UI- oder Simulationstests.
Projektweite Opt-Out-Möglichkeit
Vor der Aktivierung prüfen, ob das Projekt diese Fertigkeit abgelehnt hat. Suchen Sie nach Folgendem:
- Eine .no-crucible-Datei im Projektstammverzeichnis
- "crucible: false" irgendwo in AGENTS.md oder .claude/settings.json
Wenn ein Opt-Out-Signal gefunden wird, nicht automatisch aktivieren; wenden Sie diese Fertigkeit nur an, wenn der Benutzer sie in dieser Konversation explizit anfordert.
Regeln
- Beispielbefehle verwenden
pnpm, aber immer den Paketmanager des Projekts verwenden. - Keinen Anwendungscode ändern, es sei denn, dies wird ausdrücklich verlangt.
- Wenn Tests hinzugefügt werden sollen, keine bestehenden Tests ändern.
- Wenn Tests repariert werden sollen, keine neuen Tests hinzufügen.
- Wenn Tests überprüft werden sollen, bestehende Tests reparieren und dann nach Bedarf Tests hinzufügen, um die Testkriterien zu erfüllen.
Testkriterien
Unit-Tests sollten:
- Die maximal mögliche Branch Coverage gemäß Vitest aufweisen.
- Alle tötbaren Mutanten töten und die maximal mögliche Mutationspunktzahl für den gesamten Code im Geltungsbereich der Aufforderung erreichen (nicht nur für den von Tests abgedeckten Code). Nicht tötbare Mutanten verhindern eine Punktzahl von 100.
- Möglichst eigenschaftsbasiert sein, es sei denn, es gibt nur eine Handvoll von Eingabefällen. Z. B. hat eine Funktion mit einem einzelnen booleschen Parameter und keinen impliziten Eingaben nur zwei mögliche Eingabefälle, daher lohnt sich keine eigenschaftsbasierte Umsetzung.
- (falls eigenschaftsbasiert) Arbitrarien haben, die alle möglichen Parameter und impliziten Eingaben abdecken. Es ist entscheidend, dass keine Fälle ausgeschlossen werden, die in der Produktion auftreten könnten. Im Zweifelsfall lieber zu breite Arbitrarien wählen.
- Fehlschlagen, wenn sie fehlerhaften Code testen oder wenn Arbitrarien absichtlich zu breit gewählt wurden. Betrachten Sie Tests als Anforderungen: Sie sollten entsprechend benannt sein und automatisch bestehen, sobald der Benutzer den Fehler in der Zukunft behoben hat, nachdem der Benutzer die Funktion und/oder Arbitrarien repariert hat. Verwenden Sie nicht
test.fails/.skip; dadurch wird dem Benutzer weniger deutlich, dass Aufmerksamkeit erforderlich ist, daher sind Tests, die bestehen, obwohl sie nicht sollten, der höchste zu vermeidende Fehler.
Branch Coverage prüfen und Tests ausführen: pnpm exec vitest run src/foo.test.ts --coverage
Nach überlebenden Mutanten im getesteten Code suchen: pnpm exec stryker run --mutate "src/foo.ts"
Testsetup überprüfen
- Überprüfen, ob alle folgenden Pakete im Projekt installiert sind:
vitest fast-check @stryker-mutator/core @stryker-mutator/vitest-runner @stryker-mutator/typescript-checker - Überprüfen, ob die Vitest- und Stryker-Konfigurationen Dateien korrekt ein- und ausschließen. Stryker sollte keine Dateien prüfen, die nur Testdaten enthalten.
- Stryker-Konfiguration überprüfen:
- Verwendet den
clear-text-Reporter (andere Reporter optional). - Verwendet den TypeScript-Checker und zeigt korrekt auf die TS-Konfigurationsdatei.
- Verwendet den
- Nach anderen Konfigurationsproblemen suchen, die Probleme im Testschreib-Workflow verursachen könnten.
- Ergebnisse dem Benutzer melden.
Tests schreiben
Wenn Sie aufgefordert werden, neue Tests zu schreiben, ändern Sie KEINEN ANWENDUNGSCODE ODER BESTEHENDE TESTS.
Zunächst bestehende Tests bewerten, indem Sie Ein Modul bewerten befolgen. Erstellen Sie eine neue Debrief-Datei mit der Vorlage und notieren Sie dort die anfänglichen Coverage- und Mutationswerte.
Zweitens Tests genau nach diesem Prozess schreiben:
Führen Sie Folgendes für jede Funktion/Methode im Modul-Interface durch, wobei Sie eine Funktion beenden, bevor Sie mit der nächsten beginnen:
- Bestimmen Sie den Zweck der Funktion, indem Sie Kommentare, ihren Namen, ihre Typsignatur und ihre Verwendung untersuchen. Bei Unsicherheit dies im Debrief vermerken, Tests überspringen und mit der nächsten Funktion fortfahren.
- Notieren Sie mögliche Fehler in der Implementierung der Funktion.
- Identifizieren Sie auf der Grundlage ihres Zwecks fehlerhafte Annahmen, die die Funktion über ihre Parameter und impliziten Eingaben macht, und notieren Sie Eingabefälle, die wahrscheinlich zu fehlerhaftem Verhalten führen. Z. B. eine Funktion, die eine positive ganze Zahl akzeptiert, aber ihre Eingabe nicht validiert, macht eine fehlerhafte Annahme über ihre Eingabe.
- ÄNDERN SIE NIEMALS VORHANDENE TESTS. Wenn Sie Probleme in bestehenden Tests finden, informieren Sie den Benutzer über die gefundenen Probleme.
- Schreiben Sie neue Tests wie folgt:
a. Erstellen Sie mit
fast-checkeigenschaftsbasierte Test-Stubs mit Arbitrarien, die alle möglichen Parameter und impliziten Eingaben der Funktion abdecken. Verwenden Siefc.asyncProperty+await fc.assert(...), wenn die zu testende Funktion asynchron ist. Im Zweifelsfall lieber zu breite Arbitrarien wählen und dies im Debrief erwähnen, damit der Benutzer sie korrigieren kann. Benennen Sie Tests als Beschreibungen des gewünschten Verhaltens. b. Schreiben Sie mitvitestAssertions innerhalb der Stubs, die alle Rückgabewerte und Seiteneffekte wie das Werfen von Ausnahmen, das Mutieren von Eingaben, das Mutieren/Neuzuweisen von Variablen aus äußeren Gültigkeitsbereichen usw. abdecken. Stellen Sie sicher, dass Tests das gewünschte Verhalten bestätigen und die zuvor identifizierten fehlerhaften Annahmen/Fehler abfangen und entsprechend fehlschlagen. - Coverage erneut prüfen:
pnpm exec vitest run src/foo.test.ts --coverage - Mutationstest nur für die aktuelle Funktion:
pnpm exec stryker run --mutate "src/foo.ts:<startLine>-<endLine>" - Die neu geschriebenen Tests überarbeiten und Schritte 5a und 5b wiederholen, bis die Testkriterien (oben aufgeführt) für die Funktion erfüllt sind.
- Den Debrief mit einem Abschnitt zu dieser Funktion aktualisieren.
Nachdem Sie Tests für alle Funktionen geschrieben haben, überprüfen Sie, ob Sie Abschnitte zum Debrief für jede Funktion hinzugefügt haben, und schreiben Sie den Zusammenfassungsabschnitt fertig.
Tests überprüfen
Wenn Sie aufgefordert werden, das gesamte Projekt zu überprüfen, prüfen Sie die projektweite Codeabdeckung und Mutationswerte und empfehlen Sie Bereiche für detailliertere Überprüfungen oder zum Hinzufügen/Aktualisieren von Tests. Bevorzugen Sie Empfehlungen für die wichtigsten und fehleranfälligsten Bereiche der Codebasis – Kern-Geschäftslogik, ereignisgesteuerter Code und komplexe Funktionen.
Wenn Sie aufgefordert werden, einen Teil des Projekts zu überprüfen, suchen Sie nach Modulen oder Funktionen (im Geltungsbereich der Aufforderung), die keine Tests haben, und melden Sie diese dem Benutzer im Post-Audit-Debrief.
Für jedes Modul im Geltungsbereich der Aufforderung, das Tests hat, folgen Sie Ein Modul bewerten. Wenn nach den Bewertungskorrekturen noch Testkriterien nicht erfüllt sind, folgen Sie Tests schreiben, um die verbleibenden Lücken zu füllen.
Ein Modul bewerten
Verwenden Sie diesen Prozess, wenn Sie eine vorhandene Testdatei anhand der Testkriterien bewerten müssen – sowohl vor dem Schreiben neuer Tests als auch bei der Überprüfung.
- Codeabdeckung mit Vitest prüfen:
pnpm exec vitest run src/foo.test.ts --coverage. - Nach überlebenden Mutanten mit Stryker Mutator suchen:
pnpm exec stryker run --mutate "src/foo.ts". - Für jede Funktion im Modul, die Tests hat:
- Für eigenschaftsbasierte Tests:
- Nach Eingaben suchen, die die Funktion ohne Ausnahme oder Fehlerwert akzeptieren würde, aber nicht von den Arbitrarien generiert werden können. Arbitrarien nach Bedarf erweitern, um solche Eingaben einzuschließen.
- Nach Eingaben suchen, die nicht von Arbitrarien abgedeckt werden, insbesondere implizite Eingaben wie Klassenfelder, globale Variablen, Datum/Uhrzeit und zufallsgenerierte Zahlen. Arbitrarien dafür hinzufügen.
- Fehler in Mock-Implementierungen beheben.
- Nach Leistungsengpässen suchen.
- Für eigenschaftsbasierte Tests:
- Die Coverage- und Mutationswerte sowie alle Erkenntnisse im Debrief festhalten.
Test-Debriefs
Formatieren Sie Debriefs gemäß der folgenden Vorlage. Wenn es in einem Funktionsabschnitt nichts zu berichten gibt, schreiben Sie einfach „n/a“. Geben Sie den Debrief in eine Markdown-Datei im Verzeichnis debriefs/ aus.
Debrief: {moduleName/dateiName} {jjjj-mm-tt}
Zusammenfassung
Coverage (Branch) Vorher: X% → Nachher: Y% Zeilen, die nicht abgedeckt werden konnten: {Zeilenbereiche}
Mutationswert (gesamt) Vorher: X% → Nachher: Y%
Probleme
{Aufzählungsliste mit fehlerhaften Annahmen, gefundenen Bugs, Problemen in Tests und fehlschlagenden Tests. Jeder Listeneintrag sollte mit dem projektspezifischen relativen Pfad zur Datei und den Zeilennummern beginnen, an denen das Problem gefunden wurde}
{funktionsname}
Funktionszweck {ein Satz, der beschreibt, was die Funktion tun soll} (Vertrauen: hoch | unsicher) {falls unsicher: was unklar ist und warum}
Gefundene fehlerhafte Annahmen
- (Zeile {Zeilennummer/-bereich}): {Annahme über Eingabetyp/-bereich/-form, die die Funktion nicht validiert}
In der Implementierung gefundene Fehler
- (Zeile {Zeilennummer/-bereich}): {Beschreibung + Zeilennummer}
In vorhandenen Tests gefundene Probleme
- (Zeile {Zeilennummer/-bereich}): {Problembeschreibung + Testname}
Geschriebene Testfälle
- {kurze Beschreibung jeder getesteten Eigenschaft/Invariante}
Fehlschlagende Tests
- (Zeile {Zeilennummer/-bereich}): {Testname + Grund}
Nicht tötbare Mutanten
- (Zeile {Zeilennummer/-bereich}): {kurze Beschreibung}