オフラインスナップショット
オフラインスナップショットは、利用者が渡した HTML に対して抽出を実行する。 取得は一切行わない。 URL 展開も、URL ポリシーも、セッションも、HTTP リクエストも、ブラウザのリースも、JavaScript もない。
スナップショットは、CI でのテスト、セレクタの開発、ページ変更後のリグレッションテストに使う。
三つの実行境界
Section titled “三つの実行境界”コンパイル済みのプログラムには三つのエントリポイントがある。 その違いは重要である。
| エントリポイント | 取得 | 受け付けるモード |
|---|---|---|
Program.Extract、program.extract |
ソースのモードに従う。HTTP またはブラウザアダプタ。 | すべてのモード。 |
Program.ExtractHTML |
なし。 | HTTP モードのみ。Go のみ。 |
Program.ExtractSnapshot、program.extractSnapshot |
なし。 | プログラムが適格なら、すべてのモード。 |
Program.ExtractHTML は、保存済み HTML 向けに Go が最初から持っていたエントリポイントである。
受け付けるのは HTTP モードのプログラムだけである。
ExtractSnapshot は一般形である。
ブラウザモードのプログラムも受け付けるが、そのプログラムが適格である場合に限る。
ランタイムはスナップショットの適格性を、不変プログラムを準備する時点で、プログラム全体から算出する。
workflow ノード、または evaluate-js の値ソースを持つプログラムは適格でない。
E_SNAPSHOT_UNSUPPORTED で失敗する。
ランタイムがこれらの操作を黙って無視することはない。 静的な HTML では、ブラウザ上の変更や JavaScript の結果を再現できないからである。 そのため、偽の成功は起こり得ない。 ブラウザモードのプログラムをスナップショットでテストしたい場合は、JavaScript を少数のフィールドに閉じ込め、それ以外のフィールドをオフラインで検証する。
スナップショットが保つもの
Section titled “スナップショットが保つもの”適格なスナップショットは、抽出の挙動を完全に保つ。
- セレクタとその個数制約
- トランスフォーム。外部トランスフォームも含む
on-errorとon-row-errorによるエラーからの回復- 警告と
partialフラグ - キャンセル
したがってスナップショットテストは、近似ではなく実際の挙動を検査する。
HTML は --html オプションで渡す。
scrape-kdl extract ./extractor.kdl --html ./page.html標準入力も受け付ける。
cat page.html | scrape-kdl extract ./extractor.kdl --html -ランタイムが URL 展開を行わないため、宣言済みの input は不要である。
オフライン実行はネットワーク活動を発生させない。
--allow-private-hosts オプションも影響しない。
安定したテスト
Section titled “安定したテスト”HTML は抽出器と一緒にリポジトリへ保存する。 そうすればテストは、ネットワークの変化ではなく自分のコードの変化を知らせてくれる。
- ページを 1 回だけ保存する。任意値の欠落、複数行のコレクション、壊れた行など、扱いを確認したい状態を含むページを選ぶ。
- そのファイルを抽出器と一緒にバージョン管理へ入れる。
- CI ジョブで
--html付きのextractを実行する。 - JSON の結果をゴールデンファイルと比較する。
結果は決定的である。
同じ HTML と同じプログラムからは、常に同じ値、同じ警告、同じ partial フラグが得られる。
ページが変わったら、新しいスナップショットを取得し、ゴールデンファイルの差分を確認する。 差分は、何が変わったかを正確に示す。
ランタイムは、HTML をメモリ上で解析する前と、出力メンバごと、コレクションの行ごとにコンテキストを検査する。
キャンセルされると E_EXECUTION_CANCELED になり、原因も保持される。
フィールドポリシーでも行ポリシーでも回復できない。
TypeScript ランタイムは同じ境界で AbortSignal を使う。
次に読むもの
Section titled “次に読むもの”- 診断:失敗した結果の読み方。
- Go または TypeScript と Bun:プログラムからスナップショットを呼ぶ方法。