見出し画像

FlutterにGolden Testを導入しました

はじめに

みなさんお元気ですか。SHIFT DAAE 開発グループ所属のsakuraiです。

前回のブログでは 開発中のFlutterプロジェクトにWidgetbookを導入した経緯を書きました。
リンク先の記事の通り、実機へのデプロイ前に手軽にいろんな解像度でレイアウト確認ができるようになり便利になったのですが、手作業の確認になるため、開発作業中にもっと手軽に確認できたら良いなと思いました。

そこでさらに効率的に確認できるようにgolden_toolkitを利用したgolden testを導入しました。導入するといろんな解像度の確認だけではなく修正内容の確認も分かりやすくなり、開発効率もぐんと上がりました。
こちらも非常によかったので、私のPJで導入した手順を紹介します。

執筆者プロフィール:sakurai
SHIFT DAAE部所属の開発エンジニアです。

golden testとは

VRT(Visual Regression Test)を行うためのFlutterのパッケージです。  
golden_toolkitを利用して修正前後のスクリーンショットを作成し、
画像を比較することで見た目の変更を検知することが可能です。

また、スクリーンショット作成時に出力する解像度やフォントサイズを複数設定することが可能ですので、VRTと同時に複数解像度でレイアウト確認もできます。便利ですね!
それでは以下導入した手順を記載いたします。

導入実施手順

導入する環境についてはこちらのブログの環境を引き続き利用いたします。
(よろしければ前のブログも見てください!)

それでは新しくgolden testを導入します。

パッケージの追加

dev_dependenciesgolden_toolkitを追加します。

# ./pubspec.yaml
dev_dependencies:
  golden_toolkit: ^0.15.0

次にgolden testを実行するテストケースを書きます。

# ./test/my_home_page_golden_test.dart
import 'package:blog/main.dart';
import 'package:flutter/material.dart';
import 'package:golden_toolkit/golden_toolkit.dart';

void main() {
  testGoldens('MyHomePage', (tester) async {
    final builder = DeviceBuilder()
      ..addScenario(
          widget: MaterialApp(
            theme: ThemeData(
              primarySwatch: Colors.blue,
              fontFamily: 'Noto Sans JP',
            ),
            home: const MyHomePage(
              title: 'GoldenTestサンプル',
            ),
          ),
          name: 'MyHomePage');

    await tester.pumpDeviceBuilder(builder);
    await screenMatchesGolden(tester, 'my_home_page');
  });
}

テストケース作成後、下記のコマンドを実行します。

flutter test --update-goldens --tags=golden

コマンドを実行することでテストファイルを同じ階層にgoldensというディレクトリが作成され 、スクリーンショットが生成されます。基本的にはこれでgolden testが利用可能になります!

が、このままでは少し問題がありますのでもう少し設定を追加していきましょう。

まずは生成したスクリーンショットを確認します。

文字の部分が四角で潰れています。
FlutterのテストではAhemというテスト用のフォントを利用しており、
このフォントでは文字が黒い四角で表示されます。

パッケージで利用しているフォントを別途利用するためには

await loadAppFonts();

というメソッドをテスト時に実行する必要があります。
(参考:https://pub.dev/packages/golden_toolkit#loading-fonts)

毎回テストコードに追記することも可能ですが、面倒なので一括で設定しましょう。
testディレクトリに以下のファイルを作成することでテスト実行時にloadAppFontsを実行してくれます。

# ./test/flutter_test_config.dart
import 'dart:async';
import 'package:golden_toolkit/golden_toolkit.dart';

Future testExecutable(FutureOr Function() testMain) async {
  await loadAppFonts();
  await testMain();
}

再度flutter test --update-goldens --tags=goldenを実行して、正しく文字が表示できました!

次に複数の解像度での確認ができるよう対応します。
先ほどと同じflutter_test_config.dartにテスト実行時のデバイス設定を追加することで指定した解像度での確認が可能です。
例として以下のように設定しました。

# ./test/flutter_test_config.dart
import 'dart:async';
import 'dart:io';

import 'package:flutter/widgets.dart';
import 'package:golden_toolkit/golden_toolkit.dart';

Future testExecutable(FutureOr Function() testMain) async {
  return GoldenToolkit.runWithConfiguration(
    () async {
      await loadAppFonts();
      await testMain();
    },
    config: GoldenToolkitConfiguration(
      defaultDevices: const [
        Device( 
          name: 'mobileS', // 最小の端末
          size: Size(360, 720),
          devicePixelRatio: 3,
          safeArea: EdgeInsets.only(top: 44, bottom: 34),
        ),
        Device(
          name: 'mobileM',
          size: Size(390, 844),
          devicePixelRatio: 3,
          safeArea: EdgeInsets.only(top: 44, bottom: 34),
        ),
        Device(
          name: 'mobileL', // 最大の端末
          size: Size(428, 926),
          devicePixelRatio: 3,
          safeArea: EdgeInsets.only(top: 44, bottom: 34),
        ),
      ],

      // Currently, goldens are not generated/validated in CI for this repo. We have settled on the goldens for this package
      // being captured/validated by developers running on MacOSX. We may revisit this in the future if there is a reason to invest
      // in more sophistication
      skipGoldenAssertion: () => !Platform.isMacOS,
    ),
  );
}

再度flutter test --update-goldens --tags=goldenを実行すると以下のようにスクリーンショットが作成できました!
要件で決まった最小と最大サイズを指定しておくと便利そうです。

ということで無事に導入できました。 あとは開発を進める中で適宜スクリーンショットの更新を行います。

PJでの使い方

上記で設定したテストについて、私のPJでは以下のように利用しています。

  1. featureブランチで開発作業を行う。

  2. 開発作業完了後にGolden Testを更新し、新しい画像を含めてコミット。プルリクエストを作成する。

  3. プルリクエストを作成するレビュー時に変更差分を確認する。想定していない画面の変更があった場合は対応を検討する。

と言った感じで利用しています。

Golden Testの導入で気づいたのですがGitHubでは画像の変更がある場合、
プルリクエストで以下のように
比較できるようです
。こちらも便利ですね!!

reg suitを利用して、画像差分の確認も自動化できるようですが
今の所はプルリクエストでの確認で十分と判断して導入していません。
作業量が増えてきて改善が必要なれば対応を検討しようと思います。

終わりに

Golden Testを導入することで

  • Widgetbookよりさらに手軽に各解像度でのレイアウト確認ができるようになった。

  • 画面の比較でPRの修正内容が視覚的にわかりやすくなった

  • Flutterのバージョンアップ影響で想定していない部分の色の変更があったが、検知できた

  • 変更に強くなったので、リファクタリングしやすくなった

など良いことがたくさんありました。
しっかり各画面のテストケースを作成していくことで、本番稼働後も安心して、変更対応ができそうです。

より効率的にGolden Testを利用できないか引き続き色々考えたいと思います。お読みいただき、ありがとうございました。

\もっと身近にもっとリアルに!DAAE公式Twitter/

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/