Zum Inhalt springen

Golden-File-Testing

Spec: ISO/IEC/IEEE 29119-4 Spec: ISO/IEC 25010 Evidence: Test-backed

Eine Golden-File ist ein aufgezeichnetes „So sieht korrekte Ausgabe aus“, mit dem ein Test bei jedem Lauf abgleicht. NextPDF nutzt Golden-Files, um Änderungen aufzuspüren, die niemand vornehmen wollte: einen anders komprimierten Stream, einen verschobenen Absatz, eine abweichende Koordinate. Diese Seite erläutert, wie das funktioniert und wie eine Golden-File vertrauenswürdig bleibt, statt zu einer veralteten Referenz zu werden, die niemand mehr liest.

Die PDF-Generierung ist eine lange Pipeline mit vielen Stellen, an denen es unbemerkt zu Abweichungen kommen kann. Ein Refactoring, das „nichts ändert“, kann trotzdem Operatoren umordnen, eine Transformationsmatrix verändern oder eine Tabellenzelle um einen winzigen Betrag verschieben. Unit-Tests fangen das selten ab: Sie prüfen einen Wert, dessen Prüfung Sie vorgesehen haben, nicht aber die Tausenden von Bytes, an die Sie nicht gedacht haben. Struktur- und spezifikationsbasierte Verfahren erkennen unterschiedliche Fehler, und keines schließt das andere ein (ISO/IEC/IEEE 29119-4, Annex A). Eine Golden-File ist eine Spezifikation durch Beispiel, die die gesamte Ausgabe fixiert, nicht nur eine einzelne Zusicherung.

Das Risiko besteht in beiden Richtungen. Eine Golden-File, die zu streng ist, schlägt bei jeder harmlosen Änderung fehl und wird blind erneut abgesegnet, bis sie nichts mehr beweist. Eine Golden-File, die zu lasch ist, lässt echte Regressionen durch. Diese Balance richtig zu treffen, ist die ganze Kunst.

  • Eine Golden-File ist eine fixierte Referenzausgabe, die aus bekannt korrektem Engine-Verhalten generiert und in das Repository eingecheckt wird.
  • Ein Golden-Test generiert die Ausgabe neu und vergleicht sie mit der fixierten Referenz; jede Abweichung führt dazu, dass der Test fehlschlägt, und verlangt eine menschliche Entscheidung.
  • NextPDF vergleicht auf der Ebene, die aussagekräftig, aber stabil ist: extrahierter Text und normalisierte strukturelle Operatoren, nicht rohe Bytes, weil rohe Bytes Rauschen enthalten (Zeitstempel, Subset-Reihenfolge, Komprimierung), das keine Regression darstellt.
  • Das Aktualisieren einer Golden-File ist eine bewusste, geprüfte Handlung hinter einem expliziten GOLDEN_UPDATE-Schalter — niemals ein automatisches „Akzeptiere, was auch immer sich geändert hat“.
  • Golden-Testing unterscheidet sich vom Snapshot- und Charakterisierungs-Testing in einem entscheidenden Punkt: Eine Golden-File wird niemals automatisch aktualisiert.

Die Golden-Infrastruktur der Engine nutzt einen expliziten zweischichtigen Diff statt eines Byte-Vergleichs:

  1. Generate Render the fixture input through the current engine.
  2. Layer 1 — text Extract human-readable text from the content stream; diff against the text golden. Catches dropped or reordered content and encoding regressions.
  3. Layer 2 — structure Extract ordered PDF operators, normalise coordinates to a fixed precision, diff against the operator golden. Catches layout shifts and broken structure.
  4. Decide Any diff fails the test; a human judges whether it is a regression or an intended change.
Wie ein NextPDF-Golden-Vergleich abläuft: das PDF generieren, die aussagekräftigen Schichten extrahieren (Text, dann normalisierte strukturelle Operatoren), jede gegen die fixierte Referenz vergleichen und bei jeder Abweichung mit einem menschenlesbaren Bericht fehlschlagen.

Was bewusst nicht verglichen wird, ist genauso wichtig wie das, was verglichen wird. Die Rohbyte-Ausgabe wird ausgeschlossen, weil Zeitstempel, die Reihenfolge von Font-Subsets und die Stream-Komprimierung sie fragil machen, ohne sie korrekter zu machen. Pixelgenaues Bild-Diffing ist von dieser Ebene ausgeschlossen, weil es einen externen Renderer benötigt und Umgebungsvarianz einbringt. Gleitkomma-Koordinaten werden auf eine feste Genauigkeit normalisiert, damit sich bedeutungsloses Rundungsrauschen nicht als Regression ausgibt. Das ist der Unterschied zwischen einer Golden-File, die Verhalten prüft, und einer, die vorübergehendes Umgebungsrauschen prüft.

Diese Wahl benennt zugleich das Reproduzierbarkeitsprofil der Seite: strukturell. NextPDF dokumentiert drei Profile — bitweise (die exakten Bytes reproduzieren sich), strukturell (der Objektgraph und die Operatorsequenz reproduzieren sich, wobei gutartige Varianz auf Byte-Ebene zulässig ist) und semantisch (die Bedeutung reproduziert sich). Golden-Tests auf dieser Ebene sichern das strukturelle Profil konstruktionsbedingt ab. Deshalb überstehen ihre Referenzen ein Versionsupdate der Komprimierungsbibliothek, schlagen aber bei einer verschobenen Tabelle dennoch fehl.

Evidence: Test-backed Der zweischichtige Vergleich (Textextraktion, dann normalisierter struktureller Operatorvergleich) ist die dokumentierte Golden-Methodik der Engine; Rohbyte-, Bild-Diff- und Exakt-Gleitkommavergleiche liegen aus den oben genannten Gründen ausdrücklich außerhalb des Geltungsbereichs. Die Golden-Suite ist eine deklarierte, separat ausführbare Testsuite, getrennt von den Snapshot- und Charakterisierungssuiten.

Evidence: Test-backed Der Mechanismus, der die Referenzen ehrlich hält, ist konkret: Golden-Referenzen sind generierte Artefakte, nicht von Hand geschrieben. Das Überschreiben ist durch einen expliziten GOLDEN_UPDATE-Umgebungsschalter abgesichert; dokumentiert ist er als seltener, stets geprüfter Vorgang. Im Gegensatz dazu regenerieren Snapshot-Tests in der Engine beim ersten Lauf und bestätigen Abweichungen über ein Update-Flag. Charakterisierungstests fixieren dagegen das Alt-Verhalten, ohne zu behaupten, es sei korrekt. Alle drei sind bewusst unterschiedliche Werkzeuge.

Evidence: Standard-backed Eine Golden-File ist eine Spezifikation durch Beispiel. Spec: ISO/IEC/IEEE 29119-4, Annex A macht deutlich, dass spezifikationsbasierte und strukturbasierte Verfahren unterschiedliche Fehlerklassen erkennen und dass eine Strategie sie kombinieren sollte. Deshalb stehen Golden-Files neben Unit- und strukturellen Tests, nicht an ihrer Stelle, in der Testpyramide.

Ein Golden-Test ist mechanisch simpel; die Disziplin liegt im Workflow darum herum:

<?php
declare(strict_types=1);
// 1. The fixture: a fixed HTML input committed next to the test.
// tests/Golden/fixtures/html-inputs/002-basic-table.html
// 2. The pinned references, generated once from known-good behaviour:
// 002-basic-table.text.golden (Layer 1 — extracted text)
// 002-basic-table.operators.golden (Layer 2 — normalised operators)
// 3. The run compares; ANY difference fails:
// vendor/bin/phpunit --testsuite Golden
// 4. An intended behaviour change is the ONLY time references move,
// and it is explicit and reviewed — never automatic:
// GOLDEN_UPDATE=1 vendor/bin/phpunit --testsuite Golden
//
// The regenerated *.golden files land in the diff of the same change
// that altered behaviour, so a reviewer sees the output delta next to
// the code delta and signs off on both together.

Das Beispiel zeigt den Prozess. Der Testcode vergleicht nur. Was die Golden-File vertrauenswürdig macht, ist, dass eine geänderte Referenz als Ausgabe in derselben Änderung geprüft wird, die die Engine verändert hat.

Der häufigste Fehler besteht darin, Golden-Testing als Byte-für-Byte-Testing zu behandeln. Die Golden-Files von NextPDF sind nicht die Bytes der Datei — sie sind ihr extrahierter Text und ihre normalisierten strukturellen Operatoren. Eine Zusicherung auf rohe Bytes würde bei einer neuen zlib-Version, einem anderen Subset-Tag oder einem neu generierten Zeitstempel fehlschlagen, von denen keines eine Regression ist. Und der Test würde innerhalb einer Woche durch wiederholtes Absegnen unbrauchbar. (Wo sich exakte Bytes tatsächlich reproduzieren müssen, ist dies das separate, strengere bitweise Reproduzierbarkeitsprofil, keine Golden-File.)

Der zweite Fehler besteht in der Annahme, eine grüne Golden-Suite beweise Korrektheit. Sie beweist Nicht-Änderung. Eine Golden-File, die aus fehlerhafter Ausgabe generiert wurde, schützt zuverlässig den Fehler. Golden-Files schützen vor Regression gegenüber einer bekanntermaßen guten Baseline; sie belegen nicht, dass die Baseline gut war. Dafür sind die Unit-, Struktur- und Konformitätsebenen da.

Ein Golden-Test beantwortet genau eine Frage: Hat sich die Ausgabe gegenüber der fixierten Referenz geändert? Er sagt nichts darüber aus, ob die Referenz jemals korrekt war. Er misst auch nicht Performance, Konformität oder Sicherheit. Das sind andere Ebenen. Die Größe des Fixture-Korpus, die Erfolgsrate der Suite und jede Coverage-Kennzahl sind aktuelle Qualitätssignale, die aus Continuous-Integration-Artefakten generiert und mit dem Build veröffentlicht werden. Sie werden hier bewusst nicht genannt, weil sie an dieser Stelle veralten könnten.

Das genaue Verzeichnislayout, die internen Abläufe des Komparators und der Update-Schalter liegen in der Verantwortung der Testinfrastruktur der Engine und können sich weiterentwickeln. Die Testkonfiguration ist die maßgebliche Instanz, falls sie jemals von dieser Erläuterung abweicht. Diese Seite trifft keine Aussage über das Snapshot- oder Golden-Tooling irgendeiner anderen Bibliothek.

  • Golden-File — eine fixierte Referenzausgabe, die aus bekannt korrektem Engine-Verhalten generiert und eingecheckt wird und mit der ein Test bei jedem Lauf abgleicht. Wird niemals automatisch aktualisiert.
  • Zweischichtiger Diff — der Golden-Vergleich von NextPDF: extrahierter Text (Schicht 1) plus normalisierte strukturelle Operatoren (Schicht 2), statt roher Bytes.
  • Snapshot-Test — ein verwandtes, aber eigenständiges Verfahren, bei dem die Referenz beim ersten Lauf neu generiert und eine Abweichung über ein Update-Flag bestätigt wird.
  • Charakterisierungstest — ein Test, der bestehendes Verhalten fixiert, ohne zuzusichern, dass es korrekt ist, typischerweise um ein Refactoring abzusichern.
  • Reproduzierbarkeitsprofil — die Ebene, auf der sich die Ausgabe reproduzieren muss: bitweise (exakte Bytes), strukturell (Objektgraph und Operatorsequenz, gutartige Byte-Varianz zulässig) oder semantisch (Bedeutung). Golden-Tests sichern hier das strukturelle Profil ab.
  • GOLDEN_UPDATE — der explizite Umgebungsschalter, der das Überschreiben von Golden-Referenzen autorisiert; ein seltener, geprüfter Vorgang.