Flutter Integration Testingでは、testパッケージではなくSDKのintegration_testパッケージを使う

 前のエントリ「テストコードのデザインパターン:Robotパターン」を書いた際に情報提供いただいたネタです。
 現在、FlutterのIntegration Testでは、flutter_driverパッケージとtestパッケージの組み合わせではなく、SDKのintegration_testパッケージでテストコードを記述することが公式で推奨されています。

An introduction to integration testing - Flutter

Note: The integration_test package is now the recommended way to write integration 
tests. See the Integration testing page for details.

 SDKのintegration_testパッケージは、先月stable版がリリースされたFlutter2から利用可能になっているものです。

 integration_testパッケージは旧来のパッケージと比べて、次のようなメリットがあります。

  • Firebase Test Labでの実行をサポート
  • flutter_test APIを使って、Widget Testと同等の構文でIntegration Testを記述できる
  • 旧来のFlutter Driveコマンドに対応していて、物理デバイスでもエミュレータでもIntegration Testを実行できる

 今回はこのintegration_testパッケージを使った簡単なテストコードを示します。

pubspec.yaml

dev_dependencies:
  ...
  integration_test:
    sdk: flutter
  flutter_test:
    sdk: flutter
  ...

テストコード

 旧来のIntegration Testのテストコードは次のようになります

import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';

void main() {
  FlutterDriver driver;

  setUpAll(() async {
    driver = await FlutterDriver.connect();
  });

  tearDownAll(() async {
    await driver.close();
  });

  group('E2E Test for Login', () {
    test('authenticate a user', () async {
      await driver.tap(find.byValueKey('usernameTextField'));
      await driver.enterText('hoge hoge');

      await driver.tap(find.byValueKey('passwordTextField'));
      await driver.enterText('sample password');

      await driver.tap(find.byValueKey('login'));

      final indexMenuFinder = find.text('Execute');
      await driver.waitFor(indexMenuFinder);
      expect(await driver.getText(indexMenuFinder), 'Execute');
    });
  });
}

 integration_testパッケージを使用すると、上記のテストコードは次のように記述できます。Widget Testと同じようなスタイルになります。

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

import 'package:flutter_app/main.dart' as app;

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('E2E Test for Login', () {
    testWidgets('authenticate a user', (WidgetTester tester) async {
      app.main();
      await tester.pumpAndSettle();

      await tester.enterText(find.byKey(Key('usernameTextField')), 'hoge hoge');
      await tester.enterText(find.byKey(Key('passwordTextField')), 'sample password');

      await tester.tap(find.byKey(Key('login')));

      await tester.pumpAndSettle();

      expect(find.text('Execute'), findsOneWidget);
    });
  });
}