run-goldens-rebaseline について
Flutter開発者向けに、ビジュアルテストのベースラインを更新する手動手順を示すスキルです。有効なアサーションと画像ごとの確認を優先し、環境確認、不要ファイルの整理、個別コミットまで定めます。
主な機能
- 01画像以外のアサーションを先に通過
- 02固定された更新環境を使用
- 03変更画像を一枚ずつ確認
- 04孤立画像と失敗生成物を削除
- 05ベースラインを別コミットして再実行
活用シーン
- 01意図した UI 変更後のベースライン更新
- 02環境差による画像差分の調査
- 03ビジュアル変更一式のレビュー
- 04CIによるベースライン書き換えの防止
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ zakariaf/ flutter-skills --skill run-goldens-rebaselineインストール後、Claude Code で/run-goldens-rebaselineを入力して読み込まれたか確認します。
詳細
ゴールデンの再ベースライン
ゴールデンを承認すると、UI が以前どのように見えていたかを記録した唯一のものが上書きされます。これは、テストスイートの中でアサーションを実行するのではなく、破壊する唯一の操作です。そのため、手動で、自由度を抑え、人間が実行するワークフローです。手順を順番どおりに実行し、独自の判断で変更を加えず、失敗を解消するために実行してはいけません。
2 レーンのゴールデン戦略、ハーネス、そしてゴールデンが視覚的アサーションの中で最も弱い理由については、widget-golden-and-a11y-testing を参照してください。このスキルは、ベースラインを変更するための手順だけを扱います。
絶対に守るルール
- ゴールデンの失敗は、対処すべき雑務ではなく、問いかけです。 再生成する前に、「このピクセルの変更を意図したか?」に答えてください。変更された画像のすべてについて、答えが明確な「はい」でない場合、その変更はリグレッションであり、修正すべきなのはコードです。
- まず実際のアサーションをすべてパスさせてください。 計算されたジオメトリ、タップターゲットのサイズ、オーバーフロー、テキストスケール、純粋な Dart のコントラストテストは、再ベースラインの前にパスする必要があります。理由:ゴールデンでは何もアサートできません。クリップされて読めないテキストのスクリーンショットを承認すると、永遠にパスしてしまいます。ゲートとなるのはアサーションであり、画像は差分を確認するためだけのものです。
- 再ベースラインは、固定された承認環境でのみ行ってください。 コミット済みの画像を生成したときと同じ OS、同じ Flutter バージョンを使用してください。理由:フォントのラスタライズ結果はホストによって異なるため、別の環境で承認すると、ホスト由来のノイズで画像がすべて書き換えられ、ほかの全員の比較が恒久的に壊れます。
loadAppFonts()を必ず実行してください。 実行しないと、実フォントレーンではすべてのグリフが Ahem のボックスとして描画され、その長方形だらけの画像を承認して、永遠に「パス」させてしまいます。- CI では
--update-goldensを絶対に使わず、赤いパイプラインを直すためにも使わないでください。 確認対象を書き換えるゲートでは何もアサートできません(ci-pipeline-and-gates)。承認は、ローカルで人間がレビューして行う作業です。 - 不安定なゴールデンは絶対に承認しないでください。 コードを変更していないのに変化するゴールデンは、環境またはアニメーションの収束に関する不具合です。安定したフレームまでポンプする、時間依存性を取り除く、またはゴールデンを削除してください。再承認すると、次回の実行まで問題が隠れてしまいます。
- 変更された画像を一枚ずつ、必ず目視で確認してください。 数や差分の統計ではなく、画像そのものを確認します。理由:これがレビューのすべてです。無関係な画面が変わっていたとしても見つけるために、この手順が存在します。
- 影響を受ける画像をすべて一度に承認し、サブセットだけを承認することは絶対に避けてください。 変更を予想した画像だけを承認すると、残りの画像が失敗したままになり、レビューされない二度目の作業を招きます。
- 孤立したファイルは削除してください。 名前を変更または削除したゴールデンテストの PNG は、エラーにならないまま残り続けます。古いファイルの削除も同じ変更の一部です。
- 画像は独立したコミットにし、画像を変更した変更と同じ PR に含めてください。 コミットメッセージには、変更した内容と理由を記載します。理由:バイナリをコードのコミットに混在させるとコードの差分が読みにくくなり、レビュアーは意図した再ベースラインと、紛れ込ませた再ベースラインを見分けられません。
順序に沿ったワークフロー
- 変更が意図したものか確認し、ゴールデン以外のテストスイート(geometry、 overflow、text-scale、contrast、a11y)がすべて成功していることを確認します。
- 失敗するゴールデンテストをフラグなしで一度実行し、失敗出力を読みます。
Flutter はゴールデンの隣に
failures/*_testImage.png、*_masterImage.png、*_isolatedDiff.pngを書き込みます。何かを判断する前に差分を開いてください。 - ブレッシング環境にいることを確認します(OS が固定されており、
flutter --versionが コミット済みのベースラインを生成したものと一致していること)。 - ゴールデンタグに対象を限定して、ベースラインを再生成します。
flutter test --update-goldens --tags golden # or a single file while iterating: flutter test --update-goldens test/golden/notes_screen_golden_test.dart - 実際に変更されたものを一覧表示し、すべて開きます。
予想外の画像はリグレッションです。中止し、画像をgit status --porcelain -- '*.png'git checkout -- <paths>で元に戻して、コードを修正します。 - 孤立ファイルを削除します — どのテストからも参照されなくなったゴールデンファイルです。
# Every committed golden whose filename appears in no test source. for f in $(git ls-files 'test/**/goldens/*.png'); do grep -rq "$(basename "$f")" test --include='*.dart' || echo "orphan: $f" done failures/の生成物を削除し、決してコミットされないようにします。- 検証します。フラグなしでスイートを再実行します。
それでも失敗するものがあれば、書き込んだベースラインで再現できていません。アニメーションが 安定していない、値が時間に依存している、またはフォントが読み込まれていない可能性があります。flutter test --tags golden - 画像だけをコミットします。 例:
test(goldens): rebaseline notes screen — row height 40→48 (design review FIX-12)。
検証(必須 — PR の前に合格する必要があります)
flutter test --tags goldenが--update-goldensなしで成功すること。実行ごとに 結果が異なるゴールデンを検出するため、連続で 2 回実行します。- 変更された PNG をすべて開き、意図した変更と一致していることを確認します。無関係なものは何も変わっていません。
failures/ディレクトリも孤立した PNG もなく、.github/workflows/内に--update-goldensが存在しないこと。- 実際に意味のある失敗を検出できる geometry/contrast/a11y のアサーションが 引き続きすべて成功すること。
アンチパターン
- テストが失敗したとき、反射的に
--update-goldensを使うこと — 失敗内容を読む代わりに アサーションを削除してしまいます。 - ベースラインを生成したマシンや Flutter のバージョンと異なる環境でブレッシングすること — ホスト固有のラスタライズですべての画像を書き換え、他の人のスイートがすべて失敗します。
loadAppFonts()を使わずにブレッシングすること — Ahem のボックスだらけの画像を正しいものとして 承認してしまいます。- CI ワークフローで
--update-goldensを使うこと — ゲートが何も検証しなくなり、その状態が永続します。 - コード変更と画像を一緒にコミットすること — レビュー担当者が意図したベースラインの再生成と 偶発的な変更を切り分けられません。
- 失敗したものの一部だけをブレッシングすること — 残りが次の実行で失敗し、レビューされないまま ブレッシングされます。
- テストの名前を変更した後、孤立した PNG を残すこと — 今後どのテストでも失敗しない無用なファイルです。
- 差分が出続けるゴールデンを再ブレッシングすること — それは修正すべきフレークであり、更新すべきベースラインではありません。
failures/*_testImage.pngをコミットすること — ノイズになるうえ、誰も信頼しない「参照」画像の第 2 セットとして 気付かれないまま機能してしまいます。
完了の定義
- 視覚的な変更が意図したものであり、変更された画像をすべて目視で確認しました。
- ゴールデン以外の geometry、overflow、text-scale、contrast、a11y テストは、ベースラインの再生成 前にすべて成功しており、現在も成功しています。
-
loadAppFonts()を有効にして、固定されたブレッシング環境でベースラインを再生成しました。 - 影響する対象一式を一度の実行ですべてブレッシングし、予想外の変更はありませんでした。
- 孤立したゴールデンを削除し、
failures/の生成物を削除しました。 -
flutter test --tags goldenがフラグ なしで成功し、連続 2 回成功しました。 - 画像を単独で同じ PR にコミットし、原因がわかるメッセージを付けました。
- CI 設定内に
--update-goldensが存在しません。
関連するスキル
widget-golden-and-a11y-testing— 2 つのゴールデンテストのレーン、pumpAppハーネス、loadAppFonts()、およびゴールデンテストがスイート内で最も弱いアサーションである理由。ci-pipeline-and-gates— ゲートは検証を行い、承認はしません。ランナーを固定するルール。design-review-workflow— 意図的な視覚的変更を正当に生み出すレビューの工程。design-system-structure— すべてのゴールデンテストを変化させたトークン変更の発生元。testing-strategy— 代わりに重視すべきアサーション。
参考資料
- Flutter —
matchesGoldenFile:https://api.flutter.dev/flutter/flutter_test/matchesGoldenFile.html - Flutter —
flutter testのオプション(--update-goldens、--tags):https://docs.flutter.dev/reference/flutter-cli - Flutter —
GoldenFileComparator/LocalFileComparator:https://api.flutter.dev/flutter/flutter_test/GoldenFileComparator-class.html golden_toolkit/alchemist—loadAppFonts():https://pub.dev/packages/alchemist
コメント
Markdown 対応