FlutterでのUIテストフレームワークについて
運用が始まってクレームが来た場合、QAもしくは開発チームでその不具合を再現することが解決の第一歩となる。Flutterの場合、対象機種が多いこともあり再現実験を手動で行うのは大変だ。UIテストは運用中の物件に対して実行すれば機種を取り替えて次々と実験できるなど、開発時だけでなく運用中にも力を発揮する。
FlutterはUIテスト用の堅牢なフレームワークを提供している。Flutterアプリケーションのテストに使用できるツールやフレームワークはいくつか存在する。
- Flutter Test:
- Flutterには、単体テスト、ウィジェットテスト、統合テストをサポートするテストパッケージが含まれている。Flutterテストフレームワークのコアには以下が含まれている。
- 単体テスト: 個々の関数、メソッド、またはクラスをテストするためのものである。
- ウィジェットテスト: 個々のウィジェットをテストするためのものである。これらのテストは統合テストよりもはるかに速く実行され、ウィジェットの動作に対して高い信頼性を提供する。
- 統合テスト: 完全なアプリケーションまたはその大部分をテストするためのものである。
- Flutter Driver:
- Flutter Driverは、Flutterアプリの自動化されたUIテストのためのツールである。ユーザー入力をシミュレートし、期待される動作を検証するテストを記述できる。
- ただし、Flutter Driverは新しい
integration_test
パッケージに取って代わられる予定である。
- Integration Test Package:
integration_test
パッケージはFlutter Driverの後継である。エンドツーエンドテストを実行するためのより統合された方法を提供し、flutter_test
パッケージと連携して動作する。このパッケージは、実デバイスやエミュレータでテストを実行することをサポートする。- ユーザーインタラクションをシミュレートし、アプリの動作を検証するテストを記述できる。
- サードパーティツール:
- Appium: モバイルおよびWebアプリケーションの自動化のための広く使用されるオープンソースツールであり、Flutterでも使用可能であるが、設定が必要である。
- Detox: モバイルアプリのグレーボックスエンドツーエンドテストおよび自動化ライブラリであり、コミュニティプラグインを通じてFlutterもサポートしている。
- Espresso (Android向け)およびXCTest (iOS向け): これらはプラットフォーム固有のテストに使用できるが、Flutter固有ではない。
Flutterにおけるウィジェットテストの例
以下に、Flutterでの簡単なウィジェットテストの例を示す。
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// アプリを構築し、フレームをトリガーする。
await tester.pumpWidget(MyApp());
// カウンターが0から始まることを確認する。
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
// '+'アイコンをタップし、フレームをトリガーする。
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
// カウンターが増加したことを確認する。
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}
テストの実行
テストを実行するには、単体テストおよびウィジェットテストにはflutter test
コマンドを使用し、統合テストにはFlutter Driver用のflutter drive
または新しい統合テストパッケージ用のflutter test integration_test
コマンドを使用する。
これらのツールおよびフレームワークは、Flutterアプリケーションの開発と保守中にアプリを堅牢で信頼性の高いものに保つための包括的なテストスイートを提供する。
FlutterでのEspressoおよびXCUITestの使用について
Espresso(Android用)およびXCUITest(iOS用)はFlutterアプリケーションでも使用可能であるが、これらのフレームワークはFlutter専用ではない。以下に、Flutterアプリでこれらを統合する方法を示す。
FlutterでEspressoを使用する
Espressoは、リッチなAPIを提供するAndroidのテストフレームワークである。FlutterでEspressoを使用するには、以下の手順に従う。
- Espressoの依存関係を追加する: Androidアプリモジュールの
build.gradle
ファイルに必要なEspressoの依存関係を追加する。androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test:runner:1.4.0' androidTestImplementation 'androidx.test:rules:1.4.0'
- Espressoテストを書く:
androidTest
ディレクトリにEspressoテストクラスを作成する。例えば:@RunWith(AndroidJUnit4.class) public class MainActivityTest { @Rule public ActivityScenarioRule
activityRule = new ActivityScenarioRule<>(MainActivity.class); @Test public void verifyTextViewContent() { onView(withId(R.id.my_text_view)) .check(matches(withText("Hello World!"))); } } - Espressoテストを実行する: Android Studioまたはコマンドラインを使用してEspressoテストを実行する。
./gradlew connectedAndroidTest
FlutterでXCUITestを使用する
XCUITestはiOSアプリケーション用のUIテストフレームワークである。FlutterでXCUITestを使用するには、以下の手順に従う。
- UIテストターゲットを作成する: XcodeでFlutterプロジェクトに新しいUIテストターゲットを作成する。
- XCUITestの依存関係を追加する: Podfileに必要なXCUITestの依存関係が含まれていることを確認する。
- XCUITestケースを書く: 新しく作成したUIテストターゲットにXCUITestケースを作成する。例えば:
import XCTest class MyUITests: XCTestCase { override func setUpWithError() throws { continueAfterFailure = false XCUIApplication().launch() } func testExample() throws { let app = XCUIApplication() let label = app.staticTexts["my_label"] XCTAssertEqual(label.label, "Hello World!") } }
- XCUITestケースを実行する: UIテストターゲットを選択し、実行ボタンを押すか、コマンドラインを使用してXCUITestケースを実行する。
xcodebuild -scheme MyApp -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 12' test
Flutterとの統合
EspressoおよびXCUITestはネイティブのAndroidおよびiOSアプリ用に設計されているが、Flutterアプリのネイティブビューをターゲットにすることで使用することができる。ただし、以下の課題が存在する。
- 要素識別子: FlutterのUI要素にアクセスするために適切な識別子(Androidの場合は
@+id
、iOSの場合はアクセシビリティ識別子)を使用する必要がある。 - Flutterの同期: テストがFlutterのUIが完全にレンダリングされるのを待つようにする必要がある。これにはカスタム同期メカニズムが必要な場合がある。
プロジェクト構造例
EspressoおよびXCUITestをFlutterに統合した典型的なプロジェクト構造は以下のようになる。
my_flutter_app/
├── android/
│ ├── app/
│ │ ├── src/
│ │ │ ├── main/
│ │ │ └── androidTest/
│ │ │ └── java/
│ │ │ └── com/example/my_flutter_app/
│ │ │ └── MainActivityTest.java
├── ios/
│ ├── Runner/
│ │ └── UITests/
│ │ └── MyUITests.swift
├── lib/
└── test/
これらの手順と適切な識別子および同期技術を使用することで、FlutterアプリケーションのUIテストにEspressoおよびXCUITestを効果的に使用することができる。しかし、よりFlutterに特化したアプローチを求める場合は、integration_test
パッケージのようなFlutterのネイティブテストツールの使用を検討することをお勧めする。