【flutter】多言語対応したアプリのwidget testを実装しよう【Golden Test】


flutterで多言語化したファイルのテスト方法については日本語文献がないため、
困っている方は多いのではないでしょうか。

今回は、カウンターアプリを基に多言語対応したアプリのwidget test(Golden Test)の実装法について解説します。

今回紹介するコードは下記のGitHubリポジトリにまとまっています。
ぜひ参考にしてください。
（良ければスターをお願いします。）

https://github.com/Umigishi-Aoi/localization

##カウンターアプリの多言語対応##
カウンターアプリの多言語対応についてはこちらの記事にまとまっています。

https://qiita.com/Umigishi-Aoi/items/5a62fc3b5d26938d4282

この記事では、カウンターアプリを日本語、英語に対応しています。
この記事が完了した前提で進めるので、多言語化がまだの方は、こちらの記事を先に読んでください。

##テスト目的と方法##

テストを実装するにあたって、今回のテストの目的を明確にしておきます。
テストの目的は「機種の言語設定に対して、日本語、英語が正しく表示されること」とします。

この目的に対するテスト手法として、「Golden Test」を選択します。
「Golden Test」はwidget testの一種で、
ユーザーが使用する画面を、画像で比較するテストとなります。

ちゃんと日本語になっているか、正しく表示されているかを確認するにはもってこいのテストです。
「Golden Test」の実装法については、こちらの記事を参考にしました。

https://zenn.dev/matsumaru/articles/c2bf8ec468cff8

https://zenn.dev/matsumaru/articles/0971ee5af5fdc9


##課題と解決方法##

多言語対応したアプリのテスト実装の課題は、「どうやって言語を指定するか」です。

解決方法は簡単で、　``MaterialApp``に``locale : Locale('言語')``を設定すれば、
設定された言語でテストできます。

今回のカウンターアプリでいえば、``MyApp``の代わりに、
以下の``myAppTest``というWidgetを返すメソッドを用意し、
こちらをテストすれば``MyApp``を言語設定してテスト可能です。

```dart:widget_test.dart
//テスト用Widgetを定義　言語を引数に取るように設定
Widget myAppTest(String language) {
  return MaterialApp(
    title: 'Flutter Demo',
    localizationsDelegates: AppLocalizations.localizationsDelegates,
    supportedLocales: AppLocalizations.supportedLocales,
    theme: ThemeData(
      primarySwatch: Colors.blue,
    ),
    //機種の言語設定の代わりになる部分
    locale: Locale(language),
    home: Builder(builder: (context) {
      return MyHomePage(title: AppLocalizations.of(context)!.title);
    }),
  );
}
```

多言語化で自動生成されたファイルを使うため、アプリ作成時と同様に、
以下を``import``しましょう。

```dart:widget_test.dart
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
```
##サンプルコードとテスト結果##
最後にサンプルコードの全体とテスト結果を紹介します。

```dart:widget_test.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:golden_toolkit/golden_toolkit.dart';

import 'package:localization/main.dart';

import 'package:flutter_gen/gen_l10n/app_localizations.dart';

//テスト用Widgetを定義　言語を引数に取るように設定
Widget myAppTest(String language) {
  return MaterialApp(
    title: 'Flutter Demo',
    localizationsDelegates: AppLocalizations.localizationsDelegates,
    supportedLocales: AppLocalizations.supportedLocales,
    theme: ThemeData(
      primarySwatch: Colors.blue,
    ),
    //機種の言語設定の代わりになる部分
    locale: Locale(language),
    home: Builder(builder: (context) {
      return MyHomePage(title: AppLocalizations.of(context)!.title);
    }),
  );
}

//日本語フォントの読み込み用メソッド
Future<void> loadJapaneseFont() async {
  TestWidgetsFlutterBinding.ensureInitialized();
  final binary = rootBundle.load('font/Mplus1-Regular.ttf');
  final loader = FontLoader('Roboto')..addFont(binary);
  await loader.load();
}

void main() {
  //多言語対応できているかのGolden Test
  testGoldens('golden test', (WidgetTester tester) async {
    //日本語フォントの読み込み
    await loadJapaneseFont();
    //デバイスの画面サイズ
    final size = Size(415, 896);

    //日本語のテスト
    await tester.pumpWidgetBuilder(myAppTest('ja'), surfaceSize: size);

    await screenMatchesGolden(tester, 'myApp_ja');

    //英語のテスト
    await tester.pumpWidgetBuilder(myAppTest('en'), surfaceSize: size);

    await screenMatchesGolden(tester, 'myApp_en');

    //英語以外のテスト
    await tester.pumpWidgetBuilder(myAppTest('es'), surfaceSize: size);

    await screenMatchesGolden(tester, 'myApp_es');
  });

  //カウンターのテストは変更なし、省略
}

```
``AppLocalizations``の部分でエラーが発生しますが、無視して実行可能です。


``flutter test --update-goldens``で出力されたスクリーンショットは以下の通りです。

日本語の結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1694109/5a1bbb9e-ddfd-d401-9354-3d23a2c0f6c3.png" width="300">

英語の結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1694109/3a69ec7c-bace-54e1-f532-2926018de53e.png" width="300">

両者以外(例としてスペイン語(es))の結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1694109/3a69ec7c-bace-54e1-f532-2926018de53e.png" width="300">

日本語設定、英語設定それぞれで言語が切り替わっていること、表示されていることが確認できました。
(FABのアイコンが表示されていませんが、今回は不問とします。)

##まとめ##

今回は、カウンターアプリを基に多言語対応したアプリのwidget test(Golden Test)の実装法について解説しました。

設定自体はかなり簡単ですよね。

ぜひこちらを参考にして、多言語対応したアプリのWidget testをやってみてください！