メインコンテンツへスキップ

適合性フィクスチャの作成

このディレクトリのコーパスは XTL の実行可能な定義となります。ここにエンコードされたフィクスチャは、いかなる単一の実装よりも長く生き残ります。フィクスチャは数多く作るよりも、上手く作ることのほうが重要です。

「JS 実装を真実とみなす」アンチパターン

魅力的な近道は次のとおりです:

  1. JS リファレンス実装を走らせる
  2. その出力を expected.xlsx として保存する
  3. コミットして「正規」と称する

これでは JS 実装が事実上の仕様になってしまいます。Python や Go の移植が異論を唱えたとき、誰が正しいのでしょうか? 先に動いた者が正しい、ということになります。仕様は「JS 実装の挙動」となり、標準化は死にます。

適合性は実装からではなく、仕様から作成されなければなりません。

作成手順

単純なフィクスチャの場合

  1. spec/ の該当セクションを読む。
  2. template.xlsxdata.xlsx を Excel(またはスプレッドシートエディタ)で手作業で作成する。
  3. 期待される出力を 手作業で 計算する — Excel を開き、電卓を開き、セルごとに作業する。expected.xlsx として保存する。
  4. リファレンス実装を実行する。手計算した期待値と食い違った場合、期待値を変更しては いけない — issue を立てる。仕様が間違っているか、実装が間違っているか、あなたの手計算が間違っているかのいずれかです。

複雑なフィクスチャの場合

手計算が非現実的な場合(例: 200 行の合計、複数シートのグルーピング):

  1. 仕様に従ってテンプレートとデータを作成する。
  2. 期待値を 2 つの独立した経路で計算する(例: Excel 数式 + 別のスクリプト)。両者は一致しなければなりません。
  3. リファレンス実装を実行する。両方の独立経路と一致するなら、実装の出力を期待値として保存する。
  4. 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 です。2 は、スタイル、マージ範囲、画像、パッケージ構造、その他ステージ 1 のセル値比較では観察できないワークブック機能を主張する必要のある静的出力フィクスチャに対してのみ使用してください。

expected_error はフィクスチャをエラーフィクスチャに変換します。expected.xlsxexpected/expected_dynamic と併用してはいけません(MUST NOT)。expected_dynamic はフィクスチャを動的アサーションフィクスチャに変換し、dynamic_cells を含まなければなりません。動的フィクスチャもまた静的な期待出力を省略します。comparison_stage は静的出力フィクスチャ専用としてください。

ステージ 2 フィクスチャ作成上の注意

現在のほとんどのステージ 2 フィクスチャ(024-026)の template.xlsxexpected.xlsx は、JS リファレンス実装が内部で使用しているのと同じ exceljs ライターによって構築されています。両側で 1 つのライブラリをラウンドトリップしているため、正規化器の 等価性 の主張(シートパートのリネーム、デフォルトページ設定の除去、属性順、引用スタイル、空要素の形式)は検証しますが、ライター横断 の主張は検証しません。ExcelJS のクセだけを扱う正規化器でも、これらのフィクスチャをパスしてしまいます。

フィクスチャ 027 は、作成された期待ワークブックの OOXML シリアライゼーションをワークブックのセマンティクスを保ったまま手作業で書き換えることで、パッケージレベルのライター差異カバレッジを追加します。これでも、Excel や LibreOffice、その他の独立した OOXML ライターで保存されたワークブックの代替にはなりません。そのような作成環境が利用可能になった際には、依然としてそうしたフィクスチャの追加が望ましいフォローアップです。

依然として大原則は適用されます: JS 実装を走らせて作成したステージ 2 の expected.xlsx は禁止です。ExcelJS による作成は、パッケージライターが汎用的である(XTL の実装ではない)からこそ、足場としてのみ許容されます。expected.xlsx が Excel 自身(または別の OOXML ライター)で保存されたステージ 2 フィクスチャを追加することは、依然としてより強力なフォローアップです。それまでの間、ライター横断挙動はフィクスチャ 027 のパッケージ書き換え、および src/__tests__/conformance-runner.test.ts の正規化器ユニットテストでカバーされます。

エラーフィクスチャでは expected.xlsxexpected/ を省略し、期待される診断の安定部分を宣言します:

expected_error: "Source sheet"

動的フィクスチャでは expected.xlsxexpected/ を省略し、動的アサーション種別を宣言し、ランナーが期待値を計算するセルをリストします:

expected_dynamic: utc_today
dynamic_cells:
- sheet: Report
cell: A2
format: YYYY-MM-DD

厳格なルール

  • 期待出力は作成されるものであって、生成されるものではない。 手作業で検証できないなら、独立した方法で検証しなければなりません。expected.xlsx をテスト出力ではなく、仕様の一部として扱ってください。
  • 各フィクスチャは 1 つの概念を検証する。 1 つのフィクスチャに repeat + filter + 集計を混ぜると、失敗の診断が難しくなります。最小のフィクスチャを組み合わせてください。
  • フィクスチャのファイルサイズは小さく。 1000 行のデータが必要なフィクスチャは、テスト概念が間違っています — 同じ性質を行使する小さなデータを生成してください。
  • PII(個人情報)や独自データを含めない。 フィクスチャは MIT ライセンスで公開されます。合成データのみを使用してください。
  • テンプレートは人間が読めるものでなければならない。 明示的にテストする場合を除き、バイナリ専用の Excel 機能(カスタム XML、マクロ)はフィクスチャで避けてください。
  • エラーフィクスチャは安定した診断のみを主張する。 絶対パスのような揮発性のある詳細ではなく、契約を記述する短い部分文字列にマッチさせてください。
  • 動的フィクスチャは仕様で定義された動的値のみを主張する。 静的挙動のために期待ワークブックを作成する手間を避ける目的で使用してはいけません。

仕様とフィクスチャが食い違う場合

仕様が勝ちます。フィクスチャを更新してください。

フィクスチャと実装が食い違う場合

フィクスチャが勝ちます。実装を更新してください。

作成中に仕様化されていないケースを発見した場合

止めてください。issue を立てて、先に仕様を更新してください。仕様化されていない挙動に依存するフィクスチャをコミットしてはいけません — そうすると「コーパスの挙動」として未仕様化が凍結され、仕様が後追いでそれに合わせざるを得なくなります。