Zwölf grüne Module und ein zusammengesetztes Produkt

Veröffentlicht

Der Schwarm wurde von zwölf parallelen Owners gebaut, einer pro Modul, jeder mit einer exklusiven Dateiliste und einem eigenen Gate. Jede Spur wurde nach ihren eigenen Maßstäben grün. Dann lief der zusammengesetzte Koordinator, und das Erste, was er zeigte, war, dass ein grünes Modul kein verdrahtetes Modul ist.

Der Koordinator, der die Policy umging

Der erste zusammengesetzte Koordinator lief auf einem internen Queue-Scheduler und befragte die Policy-Engine nie. Die Residenzregel, der harte Filter, mit dem das ganze Produkt begründet wird, wurde von einem Modul durchgesetzt, das der Versandpfad nicht aufrief. Derselbe Koordinator zahlte nach der selbst gemeldeten Dauer des Workers aus. Jedes Modul bestand seine eigenen Tests, und das Produkt setzte fast nichts durch.

Die Korrektur war strukturell und nicht ein weiterer Test: Die Standardkomposition des Koordinators verwendet die echten Module für Registry, Policy, Scheduler, Ledger, Chain und Verifikation, und die Test-Doubles, die im Quellbaum gelebt hatten, wurden gelöscht. Doubles gehören in Testdateien. Die daraus entstandene Regel steht im Vertrag: Abnahme für jede künftige Spur ist das laufende Produkt, nicht die eigene Suite.

Eine erfundene Route und eine Nahtstelle, die niemand nutzte

Eine Komponente schrieb den Pfad eines Endpunkts als Zeichenkette, statt die Routenkonstante aus der eingefrorenen Schnittstelle zu lesen. Der Literalpfad wich von dem ab, den die Nahtstelle nannte, also rief das Dashboard etwas auf, das sonst niemand bediente. Die Routenkonstante existiert wegen dieses Defekts, und die Regel ist deutlich: Ein Pfad als Literal in einer anderen Komponente als der Schnittstellendatei ist ein Defekt.

Der zweite Defekt an der Nahtstelle wurde vom End-to-End-Skript gefunden und nicht von einem Unit-Test, und anders wäre er nicht zu finden gewesen. Ein Job muss auf einen Geräteschlüssel verschlüsselt werden, bevor er eingereicht wird, und die Geräteliste liefert bewusst keine Schlüssel. Damit war eine Einreichung von außen unmöglich: Nur eine Demo im selben Prozess konnte einreichen, weil sie beide Seiten des Austauschs selbst erzeugte. Die Route für die Geräteidentität wurde genau dafür ergänzt, damit ein echter, getrennter Contributor-Prozess einen öffentlichen Schlüssel holen kann. Der Abnahmetest mit zwei Contributoren fand es, weil er nicht schummeln konnte.

Dinge, die nur das zusammengesetzte Produkt zeigte

  • Ein Platzhalter-Backend-Label war in zwei Komponenten in ein Jurisdiktionsfeld gelangt, sodass sich keine von beiden registrieren konnte. Der Validator verlangt jetzt einen echten zweibuchstabigen Ländercode.
  • Die Auszahlung wurde an der Wanduhr gemessen, und ein schneller Job rundete auf null Millisekunden und zahlte nichts. Die Auszahlung wird jetzt mit einer monotonen Sub-Millisekunden-Uhr gemessen und im signierten Ergebnis mitgeführt.
  • Die Guthabenanzeige bevorzugte einen reinen Anzeigewert gegenüber dem maßgeblichen ganzzahligen Guthaben, sodass ein Betreiberpanel die falsche Zahl in der falschen Einheit zeigte.
  • Eine Abnahmeprüfung verglich ein kurzes Guthaben mit einer ganzen Textseite und traf eine unabhängige Kennung; sie meldete zweimal Erfolg, ohne etwas zu messen. Jetzt prüft sie die exakt formatierte Zeichenkette, die eine zufällige Kennung nicht fälschen kann.

Auch das Gate musste gehärtet werden

Eine Testdatei beendete ihre Prüfungen und verließ dann nie ihre Event-Loop, wodurch die ganze Suite hing. Ein Timeout pro Test begrenzt keine laufende Loop, also begrenzt das Gate jetzt den Suite-Subprozess über die Wanduhrzeit, beendet die Prozessgruppe und meldet das Hängen als Fehler. Es lässt außerdem einen Lauf scheitern, der zu früh mit zu wenigen gesammelten Tests endet, und entfernt Test-Runner-Umgebungsvariablen aus dem Kindprozess, damit ein verschachtelter Runner keinen Modus erben kann, der das Problem verdeckt. Ein Gate, das ewig hängen kann, ist kein Gate.

Die Prüfung, die das Falsche verlangte

Ein Test verlangte, dass die Browser-Worker-Seite jede Route der Schnittstelle trägt. Das stimmte, als er geschrieben wurde, und war keine Anforderung mehr, sobald eine reine Betreiberroute hinzukam; also wurde er gegenüber einem korrekten Produkt rot. Die an der Grenze festgehaltene Lehre ist präzise: Eine Prüfung darf nicht mehr verlangen, als die Komponente schuldet, und die richtige Menge zum Prüfen sind die Routen, die diese Komponente tatsächlich nutzt. Ein Test, der sich über das Produkt irrt, ist schlimmer als kein Test, weil jemand das Produkt ändern wird, um ihn zu erfüllen.

Was zwölf grüne Suiten nie gefunden hätten

Keiner dieser Defekte lag innerhalb eines Moduls. Sie lagen auf den Pfaden zwischen den Modulen: ein Scheduler, der nicht aufgerufen wurde, eine Route, die anders geschrieben war, ein Schlüssel, der nicht abrufbar war, eine Einheit, die erst zählte, als zwei echte Prozesse aufeinandertrafen. Wenn diese Welle einen übertragbaren Befund hat, dann den, dass die Integrationsgrenze eine echte, zusammengesetzte End-to-End-Prüfung verdient und jeder Owner wissen muss, welche anderen Module das eigene tatsächlich erfüllen muss. Die vollständige Liste dieser Entscheidungen steht in der Spezifikation, weil die Alternative eine grüne Suite und ein Produkt war, das nichts durchsetzte.

Quellen

Jeder Link führt zu der Quelle, die der Beitrag nennt. Wo eine Quelle eine Angabe nicht hergibt, zeigt der Beitrag sie als unverified, statt sie zu füllen.

Alle Beiträge