🙆

Flutter Golden Test / VRT の環境を合わせ、完全一致で比較する

に公開

はじめに

Flutter の Golden Test / VRT を行うことで、Widget の崩れや UI の変更を検知できます。
ただし、Flutter の Golden Test / VRT は、実行する環境によって差分が発生してしまうことがあります。
そのため、ローカルと CI で環境を合わせることで、完全一致で比較できると考えました。

環境

  • ローカル
    • macOS
  • CI
    • GitHub Actions
    • Ubuntu

なぜ環境によって差分が発生するのか

ローカルでは macOS、CI では Ubuntu という異なる OS を使用しているため、フォントなどの違いにより生成される画像に微妙なズレが発生します。

関連 Issue: https://github.com/flutter/flutter/issues/56383

環境を合わせ、完全一致で比較する

環境によって差分が発生する場合、どのように対処すればよいでしょうか。
その方法として、ローカルでは Docker を利用し、CI と同じ Ubuntu 環境を再現する方法を試してみました。

Dockerfile

docker/flutter_golden_test/Dockerfile

FROM ubuntu:24.04

ARG FLUTTER_VERSION=3.29.2

ENV FLUTTER_VERSION=$FLUTTER_VERSION

RUN apt-get update && apt-get install -y \
    curl \
    git \
    unzip \
    xz-utils \
    zip \
    libglu1-mesa \
    && rm -rf /var/lib/apt/lists/*

RUN curl -o flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_$FLUTTER_VERSION-stable.tar.xz \
    && mkdir -p /usr/local/flutter \
    && tar -xf flutter.tar.xz -C /usr/local/flutter --strip-components=1 \
    && git config --global --add safe.directory /usr/local/flutter \
    && rm flutter.tar.xz

ENV PATH="/usr/local/flutter/bin:$PATH"

RUN flutter doctor --android-licenses || true && flutter doctor || true

CMD ["flutter", "--version"]

実行コマンド

FLUTTER_VERSION=$(< .fvmrc jq -r .flutter) \
  PREFIX=$(basename $(pwd))_ && \
  docker buildx build \
    --platform linux/x86_64 \
    --build-arg FLUTTER_VERSION=${FLUTTER_VERSION} \
    -t ${PREFIX}flutter_golden_test \
    docker/flutter_golden_test && \
  docker volume create \
    ${PREFIX}flutter_golden_test_dart_tool && \
  docker run \
    --rm -v $(pwd):/app \
    -v ${PREFIX}flutter_golden_test_dart_tool:/app/.dart_tool \
    --platform linux/x86_64 \
    -it \
    ${PREFIX}flutter_golden_test flutter test --tags golden

※ ゴールデンファイルを更新する場合は --update-goldens を付けて実行します。

  • FLUTTER_VERSION=〜 で FVM で管理している Flutter のバージョンを取得
  • PREFIX=〜 で Docker イメージやコンテナなどのプレフィックスを設定
  • docker buildx build で Docker イメージをビルド
    • プラットフォームは linux/x86_64 を指定
    • FLUTTER_VERSION をビルド引数として渡す
  • docker volume create.dart_tool を保存するボリュームを作成
  • docker run でコンテナを起動
    • -v $(pwd):/app でカレントディレクトリをマウント
    • -v ${PREFIX}flutter_golden_test_dart_tool:/app/.dart_tool.dart_tool をマウント
    • --platform linux/x86_64 でプラットフォームを指定

VSCode 向け tasks.json

.vscode/tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "flutter test --tags golden",
      "detail": "golden タグのテストを実行",
      "type": "shell",
      "command": "sh",
      "args": [
        "-c",
        "FLUTTER_VERSION=$(< .fvmrc jq -r .flutter) PREFIX=$(basename $(pwd))_ && docker buildx build --platform linux/x86_64 --build-arg FLUTTER_VERSION=${FLUTTER_VERSION} -t ${PREFIX}flutter_golden_test docker/flutter_golden_test && docker volume create ${PREFIX}flutter_golden_test_dart_tool && docker run --rm -v $(pwd):/app -v ${PREFIX}flutter_golden_test_dart_tool:/app/.dart_tool --platform linux/x86_64 -it ${PREFIX}flutter_golden_test flutter test --tags golden"
      ]
    },
    {
      "label": "flutter test --update-goldens --tags golden",
      "detail": "golden タグのテストを実行してゴールデンファイルを更新",
      "type": "shell",
      "command": "sh",
      "args": [
        "-c",
        "FLUTTER_VERSION=$(< .fvmrc jq -r .flutter) PREFIX=$(basename $(pwd))_ && docker buildx build --platform linux/x86_64 --build-arg FLUTTER_VERSION=${FLUTTER_VERSION} -t ${PREFIX}flutter_golden_test docker/flutter_golden_test && docker volume create ${PREFIX}flutter_golden_test_dart_tool && docker run --rm -v $(pwd):/app -v ${PREFIX}flutter_golden_test_dart_tool:/app/.dart_tool --platform linux/x86_64 -it ${PREFIX}flutter_golden_test flutter test --update-goldens --tags golden"
      ]
    }
  ]
}

まとめ

ローカルと CI で Docker を利用し環境を合わせることで、Golden Test / VRT を完全一致で比較できるようになりました。
これにより、Widget の崩れや UI の変更をわずかな差分でも検知できるようになります。

最後まで読んでいただきありがとうございます。この記事が少しでも役に立ったと思ったら、Like♥ を押していただけると励みになります。

Discussion