黃金檔測試
Spec: ISO/IEC/IEEE 29119-4 ISO/IEC/IEEE 29119-4 Spec: ISO/IEC 25010 ISO/IEC 25010 Evidence: Test-backed
黃金檔是一份記錄下來的「正確輸出應該長這樣」,測試每次執行時都會拿它來比對。NextPDF 用黃金檔捕捉非預期變更:壓縮方式不同的串流、位置移動的段落、偏移的座標。本頁說明這套機制如何運作,以及黃金檔如何保持值得信賴,而不是淪為一份沒有人讀的過時參考。
為什麼這很重要
標題為「為什麼這很重要」的區段PDF 產生是一條很長的管線,有許多地方可能悄悄偏移。一次「什麼都沒改」的重構,可能不知不覺重排了運算子、改動了一個變換矩陣,或讓某個表格儲存格產生極小的偏移。單元測試很少能捕捉這種情況:它們斷言的是你想到要檢查的某個值,而不是那些你沒有檢查的數千個位元組。以結構為基礎與以規格為基礎的技術會偵測到不同錯誤,兩者都無法完整涵蓋對方(ISO/IEC/IEEE 29119-4,附錄 A)。黃金檔正是一份以範例呈現的規格,它釘選的是整份輸出,而非單一個斷言。
風險是雙向的。太嚴格的黃金檔會碰到每個無害變更都失敗,然後被盲目重新核可,直到它什麼也證明不了。太寬鬆的黃金檔則會讓真正的回歸通過。拿捏好這個平衡,正是這門手藝的全部。
精簡版說明
標題為「精簡版說明」的區段- 黃金檔是一份釘選的參考輸出,由已知良好的引擎行為產生,並提交到版本庫中。
- 黃金測試會重新產生輸出,並將它與釘選的參考相比對;任何差異都會讓測試失敗,並要求由人判斷。
- NextPDF 在有意義且穩定的層級上比對:擷取出的文字與正規化後的結構運算子,而非原始位元組,因為原始位元組帶有雜訊(時間戳、子集排序、壓縮),那些並不是回歸。
- 更新黃金檔是一個刻意且經過審查的動作,受明確的
GOLDEN_UPDATE開關控管——絕不是自動「接受任何變更」。 - 黃金測試與快照測試、特性化測試有一個決定性的差別:黃金檔永不自動更新。
NextPDF 的做法
標題為「NextPDF 的做法」的區段引擎的黃金檔基礎設施採用明確的雙層比對,而非位元組比對:
- Generate Render the fixture input through the current engine.
- Layer 1 — text Extract human-readable text from the content stream; diff against the text golden. Catches dropped or reordered content and encoding regressions.
- Layer 2 — structure Extract ordered PDF operators, normalise coordinates to a fixed precision, diff against the operator golden. Catches layout shifts and broken structure.
- Decide Any diff fails the test; a human judges whether it is a regression or an intended change.
它刻意不比對的內容,和它實際比對的內容一樣重要。原始位元組輸出被排除在外,因為時間戳、字型子集排序與串流壓縮會讓它變得脆弱,卻不會讓它更正確。像素層級的影像比對在這一層被排除在外,因為它需要外部算繪器,並會引入環境差異。浮點座標會被正規化到固定精度,避免無意義的捨入雜訊偽裝成回歸。這就是測試行為的黃金檔,與測試短暫環境雜訊的黃金檔之間的差別。
這項選擇也決定了本頁標示的可重現性設定:結構性。NextPDF 記載了三種設定——逐位元(精確的位元組可重現)、結構性(物件圖與運算子序列可重現,允許良性的位元組層級差異)以及語意(意義可重現)。這一層的黃金測試在設計上斷言的就是結構性設定。這就是為什麼它們的參考能在一次壓縮函式庫升級後存活,卻仍會在一個移動過的表格上失敗。
證據怎麼說
標題為「證據怎麼說」的區段Evidence: Test-backed 這套雙層比對(先擷取文字, 再比對正規化後的結構運算子)是引擎自身記載的黃金檔方法論,並基於上述理由,明確將原始位元組、影像比對與精確浮點比對排除在範圍之外。黃金套件是一個經宣告、可獨立執行的測試套件,有別於快照與特性化套件。
Evidence: Test-backed 誠實機制很具體:
黃金參考是產生出來的成品,而非手寫而成。覆寫它們的動作,受一個明確的 GOLDEN_UPDATE 環境開關把關,該開關記載為一個罕見、永遠經過審查的操作。相較之下,引擎中的快照測試會在首次執行時重新產生,並透過更新旗標來確認偏移。而特性化測試則鎖定既有行為,卻不主張它是正確的。這三者是刻意設計成不同的工具。
Evidence: Standard-backed 黃金檔是一份以範例呈現的規格。 Spec: ISO/IEC/IEEE 29119-4, Annex A ISO/IEC/IEEE 29119-4 Annex A 指出以規格為基礎與以結構為基礎的技術會捕捉不同類別的錯誤,而一套策略應該將它們結合起來。這就是為什麼在 測試金字塔中,黃金檔是與單元測試和結構測試並列,而非取而代之。
實際範例
標題為「實際範例」的區段黃金測試在機制上很簡單;紀律在於圍繞它的工作流程:
<?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.範例本身展示的就是流程。測試程式碼只負責比對。讓黃金檔值得信賴的,是在同一個改動引擎的變更中,把更新後的參考當作輸出一併審查。
常見誤解
標題為「常見誤解」的區段最常見的錯誤,是把黃金測試當成逐位元組測試。NextPDF 的黃金檔並不是檔案位元組本身——而是它擷取出的文字與正規化後的結構運算子。斷言原始位元組會在新版 zlib、不同的子集標籤或重新產生的時間戳上失敗,而這些都不是回歸。接著這個測試會在一週之內被重新核可到毫無用處。(當精確的位元組確實必須可重現時,那屬於另一個獨立、更嚴格的逐位元可重現性設定,而非黃金檔。)
第二個錯誤,是假設一套全綠的黃金套件就證明了正確性。它證明的是未變更。從有缺陷的輸出產生的黃金檔,會忠實地保護那個缺陷。黃金檔防範的是從已知良好基準線發生的回歸;它們並不確立那條基準線當初是好的。那是單元、結構與符合性各層的職責。
限制與邊界
標題為「限制與邊界」的區段黃金測試只回答一個問題:輸出相對於釘選的參考是否發生了變化。它不說明那份參考當初是否正確。它也不衡量效能、符合性或安全性。那些是其他層的事。夾具語料庫的大小、套件的通過率,以及任何覆蓋率數字,都是從持續整合成品產生、並隨建置一同發布的活躍品質訊號。本文刻意不在這裡列出它們,以免在此處變得過時。
確切的目錄佈局、比對器內部運作與更新開關,由引擎的測試基礎設施所擁有,並可能演進。若測試組態與本說明有任何牴觸,以測試組態為準。本頁不對任何其他函式庫的快照或黃金工具做任何主張。
相關文件
標題為「相關文件」的區段- NextPDF 測試金字塔——黃金層在這五層中的位置,以及它獨有的證明範圍。
- 變異測試解析——NextPDF 如何檢查它的測試(含黃金檔)是否真的能偵測到缺陷。
- 處處嚴格型別——在任何黃金測試執行之前,就先移除一整類缺陷的靜態分析。
詞彙表
標題為「詞彙表」的區段- 黃金檔——一份釘選的參考輸出,由已知良好的引擎行為產生並提交,測試每次執行時都會拿它來比對。永不自動更新。
- 雙層比對——NextPDF 的黃金比對:擷取出的文字(第 1 層)加上正規化後的結構運算子(第 2 層),而非原始位元組。
- 快照測試——一種相關但不同的技術,其參考會在首次執行時重新產生,並透過更新旗標來確認偏移。
- 特性化測試——一種鎖定既有行為、卻不斷言其正確性的測試,通常用來讓重構變得安全。
- 可重現性設定——輸出必須重現的層級:逐位元(精確的位元組)、結構性(物件圖與運算子序列,允許良性的位元組差異),或語意(意義)。此處的黃金測試斷言的是結構性設定。
GOLDEN_UPDATE——用來授權覆寫黃金參考的明確環境開關;一個罕見、經過審查的操作。