編寫符合性 Fixture
本目錄下的語料庫,會成為 XTL 的可執行定義。在此編寫的 fixture 會比任何單一實作都長壽。把它們寫好,比寫得多重要許多。
「以 JS 實作為真」的反模式
最誘人的捷徑是:
- 跑一遍 JS 參考實作
- 把它的輸出存成
expected.xlsx - 提交並宣稱它就是正規的
這等於把 JS 實作當成了事實上的規格。當 Python 或 Go 移植版本不同意時,誰才對?先跑的人對。規格淪為「JS 實作做了什麼」,標準化就此死亡。
符合性 fixture 必須依規格撰寫,不能依實作撰寫。
撰寫流程
簡單 fixture
- 閱讀
spec/中相關章節。 - 在 Excel(或試算表編輯器)中親手撰寫
template.xlsx與data.xlsx。 - 親手計算預期輸出——打開 Excel、打開計算機,一格一格地算。存成
expected.xlsx。 - 執行參考實作。若它與你手算的預期不一致,不要修改預期值——開一個 issue :可能是規格錯了、實作錯了,或你手算錯了。
複雜 fixture
當無法手算(例如 200 列的總和、多工作表分組)時:
- 依規格撰寫範本與資料。
- 透過兩條獨立路徑計算預期值(例如 Excel 公式 + 另一個獨立腳本)。兩者必須一致。
- 執行參考實作;若它與兩條獨立路徑都一致,再把實作的輸出存成預期值。
- 在
meta.yaml中記錄:verified_by: [excel-formulas, manual-script]。
meta.yaml 應包含什麼
description: "Basic per-row substitution with [field] syntax"
spec_section: "Cell-level variables"
spec_version: 0.1
tags: [substitution, basic]
comparison_stage: 1
verified_by: [hand] # 或 [excel-formulas, manual-script] 等
comparison_stage 為選填,預設為 1。只有當靜態輸出 fixture 需要正規 OOXML 比對來斷言樣式、合併範圍、影像、套件結構或其他階段 1 儲存格值比對看不到的活頁簿特性時,才使用 2。
expected_error 會把 fixture 轉成錯誤 fixture,MUST NOT 與 expected.xlsx、expected/ 或 expected_dynamic 一起使用。expected_dynamic 會把 fixture 轉成動態斷言 fixture,MUST 一併包含 dynamic_cells;動態 fixture 同樣省略靜態預期輸出。comparison_stage 僅用於靜態輸出 fixture。
階段 2 fixture 撰寫注意事項
目前大多數階段 2 fixture(024-026)的 template.xlsx 與 expected.xlsx,都是用 JS 參考實作內部使用的同一個 exceljs 書寫器產出的。兩邊都繞同一個程式庫往返一次,所以它們驗證的是正規化器的 等價性 主張(工作表 part 改名、預設頁面設定剝除、屬性順序、引號樣式、空元素表示法),而非 跨書寫器 主張。一個只處理 ExcelJS 怪癖的正規化器仍可通過這些 fixture。
Fixture 027 透過親手改寫已撰寫好的 expected 活頁簿的 OOXML 序列化,同時保留相同的活頁簿語意,補上套件層級的書寫器差異覆蓋。但這仍不是「由 Excel、LibreOffice 或其他獨立 OOXML 書寫器存檔的活頁簿」的替代品;當該撰寫環境可用時,這類 fixture 仍是首選的後續強化方向。
最高守則仍然成立:透過執行 JS 實作來產生階段 2 expected.xlsx