Flutterのアプリにゴールデンテストを導入
はじめに
アプリを作ろうと思ったんですが、いろいろ始める前に、なにかするとすぐ画面が崩れるので、知らないところでそうならないよう、画面の差分があったときにはちゃんと来づけるようにしたい…と思い、ゴールデンテストを導入することにしました。
…というわけで設定作業を始めたのですが…
ちゃんとアプリの画面が取れるようになるまでに苦労があったので、そこをシェアしようかな、と思った次第です。
結論
alchemistのサンプルには、ListTile
のテストが書かれていまして…そのままアプリのページのMyApp
(flutter create直後にできるヤツ)を置き換えても、ものすごい大量の例外で圧倒されてしまいました。
大量の警告をつぶさに読んでいくと、ウィジェットのサイズが指定されていないことが問題だったことがわかり、SizedBox
で包んであげればよいことがわかりました。
// 省略
goldenTest(
'Run my_app',
fileName: 'my_app',
builder:
() => GoldenTestGroup(
children: [
GoldenTestScenario(
name: 'my_app',
child: const SizedBox(width: 400, height: 800, child: MyApp()), // ココ!
),
],
),
);
// 省略
詳細
ここからは自分で設定したプルリクエストのまとめ的なものです。
できあがりの姿
- CI(Github Actions)でテスト、保存されているゴールデンファイルと差分が見つかったときにはエラー。
- 差分をダウンロードして確認
- 差分のできることがわかっているときにはゴールデンファイルをプルリクエストに追加
-
導入時のプルリクエストはこちら
- podcast playerって書いてあるけど、まだ全然進んでないのは御愛嬌w
ツール
ゴールデンテストを簡易に行えるようにするツールがいくつかあるようですが、その中からよく使われていそうなalchemistを選択しました。
alchemistでなるほどと思ったこと
READMEを見ていて、画像による比較で差分が出やすいのはフォントなので、全部■で表示することを進めていました。また、UIの影も、バージョンなどで変わりやすいのでナシが選べたりして、興味深かったです。
pubspec.yaml
alchemistを追加しただけです。
# 省略
dev_dependencies:
alchemist: ^0.11.0
flutter_lints: ^5.0.0
flutter_test:
sdk: flutter
# 省略
test/flutter_test_config.dart
CIで見るので、テスト時に実行したマシン向けの結果を作らないようにしています。
import 'dart:async';
import 'package:alchemist/alchemist.dart';
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
return AlchemistConfig.runWithConfig(
config: const AlchemistConfig(
platformGoldensConfig: PlatformGoldensConfig(enabled: false),
),
run: testMain,
);
}
テスト
(冒頭の結論のところと同じです。)
alchemistのサンプルには、ListTile
のテストが書かれていまして…そのままアプリのページのMyApp
(flutter create直後にできるヤツ)を置き換えても、ものすごい大量の例外で圧倒されてしまいました。
大量の警告をつぶさに読んでいくと、ウィジェットのサイズが指定されていないことが問題だったことがわかり、SizedBox
で包んであげればよいことがわかりました。
// 省略
goldenTest(
'Run my_app',
fileName: 'my_app',
builder:
() => GoldenTestGroup(
children: [
GoldenTestScenario(
name: 'my_app',
child: const SizedBox(width: 400, height: 800, child: MyApp()), // ココ!
),
],
),
);
// 省略
ゴールデンファイル
デザインを変えたり、新しいテストを追加したりしたときにはゴールデンファイルをflutter test --update-goldens
で更新する必要があります。
Github Actions
テストの失敗時に差分などの情報が格納されているディレクトリをアーティファクトとしてアップロードしています。
# 省略
- name: Run tests
run: flutter test
# 失敗時だけtest/golden/failuresディレクトリをアーティファクトにアップロードしてます。
- name: Upload golden failure images
if: failure()
uses: actions/upload-artifact@v4
with:
name: golden-failures
path: test/golden/failures
# 省略
アップロードされたアーティファクトはジョブ内のステップを開くとダウンロードパスが書かれています。
ちなみにこんな感じのものです。(フォントを■にする前に動かしたら…まんまと差分が検知されました💦)
おわりに
ひさしぶりにflutterを触りました。いろいろ忘れててもう…。もっと少しずつでもいいから触っていこ…。
あとは…「はじめに」にも書きましたが、おんなじところでひっかかったひとに届いてくれればいいな、という感じです。
Discussion