tim witter
Alle Beiträge

Blog

Verifikation ist eine Vereinbarung des Projekts

Ich setze nicht voraus, dass ein vertrauter Testbefehl in jedem Projekt dasselbe bedeutet. Die festgelegten Prüfungen gehören zur Arbeitsvereinbarung eines Repositories. Ich lese sie, bevor ich eine Änderung als geprüft bezeichne.

Mit dem vorgesehenen Weg beginnen

Ich suche den Projekteinstieg, die betroffenen Dateien und die dokumentierten schnellen Prüfungen für diesen Bereich. Eine gezielte Prüfung liefert rasch Rückmeldung während der Arbeit; sie ersetzt keine vorgeschriebene Formatierung oder Typprüfung. Überschreitet die Änderung Grenzen, kann ein umfassenderer Lauf sinnvoll sein. Meine Faustregel: Der Umfang der Prüfung muss zur späteren Aussage passen.

Der festgelegte Weg ist eine Vereinbarung in beide Richtungen. Eine nicht vorgesehene Prüfung kann aufschlussreich sein, ersetzt aber nicht die vereinbarte. Kann eine vorgesehene Prüfung in meiner Umgebung nicht laufen, berichte ich das, statt die Lücke mit einem ähnlichen Befehl zu überdecken. Ich sage, auf welche Vereinbarung ich antworte.

Ich prüfe auch, was ein schneller Befehl tatsächlich abdeckt. Eine Typprüfung kann schnell sein, weil sie Deklarationen liest statt Code auszuführen; ein gezielter Test wählt eine Datei aus. Beides macht das Ergebnis nicht schwach, begrenzt aber die Aussage. Wer die Grenze kennt, erkennt, wann ein umfassenderer Lauf fällig ist.

.project-checks.jsonJSON
{
  "version": 1,
  "checks": [
    {
      "name": "typecheck",
      "argv": ["bun", "run", "typecheck"],
      "profiles": ["fast"]
    },
    {
      "name": "build",
      "argv": ["bun", "run", "build"],
      "profiles": ["full"]
    }
  ]
}

Drei Ergebnisse auseinanderhalten

Bestanden heißt, dass ein benannter Befehl mit dem aktuellen Stand erfolgreich lief. Fehlgeschlagen heißt, dass ich den Befund untersuchen und beheben muss, statt ihn zu verschweigen. Nicht ausgeführt heißt, dass mir Belege fehlen, auch wenn ich Erfolg erwarte. Eine schnelle Prüfung spart Zeit; einen nicht gestarteten Build als erfolgreich auszugeben, wäre irreführend.

Die drei Ergebnisse verlangen unterschiedliche Antworten. Ein Fehlschlag braucht eine Korrektur und einen erneuten Lauf; ein nicht ausgeführtes Ergebnis braucht eine Umgebung, eine Berechtigung oder die bewusste Entscheidung, die Lücke zu akzeptieren; ein Erfolg braucht Ehrlichkeit über seinen Umfang. Fasst man sie zusammen, verschwindet die offene Frage.

Auch Veraltung gehört hierher. Ein Ergebnis beschreibt den Stand, in dem der Befehl lief; ein Erfolg von vor meiner letzten Änderung belegt nichts über die aktuelle Datei. Ändere ich Code nach einer Prüfung, fällt sie auf nicht ausgeführt zurück, bis ich sie wiederhole. Diese einfache Regel verhindert, dass ein grüner Bericht stillschweigend falsch wird.

summary.tsTypeScript
type Outcome = "passed" | "failed" | "not-run";

interface CheckResult {
  name: string;
  outcome: Outcome;
  detail?: string;
}

// Not run is its own outcome; it never folds into passed.
export function summarize(results: readonly CheckResult[]): string {
  const failed = results.filter((result) => result.outcome === "failed");
  if (failed.length > 0) {
    return "failed: " + failed.map((result) => result.name).join(", ");
  }
  const unrun = results.filter((result) => result.outcome === "not-run");
  if (unrun.length > 0) {
    return "not run: " + unrun.map((result) => result.name).join(", ");
  }
  return "all declared checks passed";
}

Die tatsächlichen Belege nennen

Zum Abschluss notiere ich Befehl, Ergebnis und Einschränkung: Vielleicht lief ein gezielter Test, aber keine Integrationsumgebung war verfügbar. Nach einer Korrektur prüfe ich erneut, denn ein früherer Erfolg beschreibt früheren Code. Mein Bericht ist überprüfbar, wenn andere dieselben Befehle ausführen und erkennen können, welche Aussage jedes Ergebnis trägt.

Ein guter Bericht trennt, was der Befehl belegt hat, von dem, was ich daraus schließe. Der Befehl liefert einen Rückgabewert und Ausgabe; die Deutung, dass die Änderung solide ist, ist meine. Ich nenne beides und benenne die Annahme, die sie verbindet, etwa dass der Test denselben Pfad ausführt wie das beschriebene Verhalten.

Außerdem soll mein Bericht nachvollziehbar sein und nicht nur behaupten. Wer denselben Stand auscheckt, sollte dieselben Befehle ausführen und dieselben Ergebnisse sehen. Ist das unmöglich, weil Umgebung oder Eingabe fehlen, sage ich, welcher Teil nicht reproduzierbar ist und was dadurch unbestätigt bleibt.

checks.shShell
# Fast feedback while editing.
bun run typecheck
# passed: no type errors

# The broader check is declared but not available here.
bun run build
# not run: build toolchain missing in this environment