整合測試

本篇描述瞭如何使用 integration_test package 來執行整合測試。使用該 package 編寫的測試具有以下屬性:

  • 相容 flutter drive 指令,用於在真機或模擬器上執行測試。

  • 能夠透過 Firebase Test Lab 在各種裝置上進行自動化測試。

  • 相容 flutter_test API,能夠使用類似 widget 測試 的風格進行編寫。

概覽

單元測試、Widget 測試和整合測試

Flutter 支援三種型別的測試。 單元測試 驗證一個方法或類別的行為。 Widget 測試 無需執行應用程式就可以驗證 Flutter widget 的行為。 整合測試(又名端到端測試或 GUI 測試)執行整個應用程式。

宿主和目標裝置

在開發過程中,宿主 就是你的編碼平台,應用程式在 目標 裝置上執行,就像你在臺式電腦上編寫程式碼,並在行動裝置、瀏覽器或者桌面程式上執行你的應用程式,(如果你使用的是 web 瀏覽器或桌面應用程式,宿主也是目標裝置)

integration_test

integration_test package

integration_test package 編寫的測試可以:

  1. 直接在目標裝置上執行,允許使用 Firebase Test Lab 在多個 Android/iOS 裝置上進行測試。

  2. 使用 flutter test integration_test 指令執行。

  3. 使用 flutter_test API,讓整合測試編寫風格更像 Widget 測試

從 flutter_driver 遷移

現在還在使用 flutter_driver 的專案可以透過以下方式遷移到 integration_test,請檢視 從 flutter_driver 遷移 指南。

專案設定

在你的 pubspec.yaml 檔案中加入 integration_testflutter_test

$ flutter pub add 'dev:flutter_test:{"sdk":"flutter"}'  'dev:integration_test:{"sdk":"flutter"}'
"flutter_test" is already in "dev_dependencies". Will try to update the constraint.
Resolving dependencies... 
  collection 1.17.2 (1.18.0 available)
+ file 6.1.4 (7.0.0 available)
+ flutter_driver 0.0.0 from sdk flutter
+ fuchsia_remote_debug_protocol 0.0.0 from sdk flutter
+ integration_test 0.0.0 from sdk flutter
  material_color_utilities 0.5.0 (0.8.0 available)
  meta 1.9.1 (1.10.0 available)
+ platform 3.1.0 (3.1.2 available)
+ process 4.2.4 (5.0.0 available)
  stack_trace 1.11.0 (1.11.1 available)
  stream_channel 2.1.1 (2.1.2 available)
+ sync_http 0.3.1
  test_api 0.6.0 (0.6.1 available)
+ vm_service 11.7.1 (11.10.0 available)
+ webdriver 3.0.2
Changed 9 dependencies!

在你的專案中,建立一個 integration_test 目錄,新目錄中建立一個新檔案 <name>_test.dart

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

void main() {
  testWidgets('tap on the floating action button, verify counter',
      (tester) async {
    // Load app widget.
    await tester.pumpWidget(const MyApp());

    // Verify the counter starts at 0.
    expect(find.text('0'), findsOneWidget);

    // Finds the floating action button to tap on.
    final fab = find.byKey(const Key('increment'));

    // Emulate a tap on the floating action button.
    await tester.tap(fab);

    // Trigger a frame.
    await tester.pumpAndSettle();

    // Verify the counter increments by 1.
    expect(find.text('0'), findsNothing);
    expect(find.text('1'), findsOneWidget);
  });
}

如果你想了解更多範例,請檢視 samples 中的 testing_app

目錄結構

lib/
  ...
integration_test/
  foo_test.dart
  bar_test.dart
test/
  # Other unit tests go here.

另見:

使用 Flutter 指令執行測試

這些測試可以用 flutter test 指令執行,其中 <DEVICE_ID>:是可選項,可以透過 flutter devices 指定裝置 ID 或顯示模式:

$ flutter test integration_test/foo_test.dart -d <DEVICE_ID>

上面的指令將執行 foo_test.dart 中的測試。要在預設裝置上執行該目錄下的所有測試,請執行:

$ flutter test integration_test

在瀏覽器中執行測試

下載安裝 ChromeDriver 並在 4444 連接埠執行:

$ chromedriver --port=4444

為了使用 flutter drive 進行測試,請建立一個新的目錄,其中包含一個新的檔案 test_driver/integration_test.dart

import 'package:integration_test/integration_test_driver.dart';

Future<void> main() => integrationDriver();

然後將 IntegrationTestWidgetsFlutterBinding.ensureInitialized() 新增到你的 integration_test/<name>_test.dart 檔案中:

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

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized(); // NEW

  testWidgets('tap on the floating action button, verify counter',
      (tester) async {
    // Load app widget.
    await tester.pumpWidget(const MyApp());

    // Verify the counter starts at 0.
    expect(find.text('0'), findsOneWidget);

    // Finds the floating action button to tap on.
    final fab = find.byKey(const Key('increment'));

    // Emulate a tap on the floating action button.
    await tester.tap(fab);

    // Trigger a frame.
    await tester.pumpAndSettle();

    // Verify the counter increments by 1.
    expect(find.text('0'), findsNothing);
    expect(find.text('1'), findsOneWidget);
  });
}

最後在一個獨立的程序中,執行 flutter_drive

$ flutter drive \
   --driver=test_driver/integration_test.dart \
   --target=integration_test/counter_test.dart \
   -d web-server

瞭解更多訊息,請檢視 Running Flutter driver tests with web 指南。

在 Firebase Test Lab 進行測試

你可以透過 Firebase Test Lab 同時使用 Android 和 iOS 目標裝置進行測試。

Android 設定

請遵循 integration_test README 中的 Android Device Testing 進行設定。

iOS 設定

請遵循 integration_test README 中的 iOS Device Testing 進行設定。

Firebase Test Lab 專案設定

進入 Firebase 控制台, 如果你還沒有新的專案,就建立一個新專案。然後導向選單到 Quality > Test Lab:

Firebase Test Lab Console

上傳 Android APK

使用 Gradle 建立一個 APK:

$ pushd android
# flutter build generates files in android/ for building the app
flutter build apk
./gradlew app:assembleAndroidTest
./gradlew app:assembleDebug -Ptarget=integration_test/<name>_test.dart
$ popd

上面指令中的 <name>_test.dart 是在剛才 專案設定 建立的檔案。

<flutter_project_directory>/build/app/outputs/apk/debug 內打包完成的 “debug” APK 檔案上傳到網頁上的 Android Robo Test。這將啟動一個 Robo 測試,並允許你執行其他測試:

Firebase Test Lab upload

點選 Run a test, 選擇 Instrumentation 測試型別,並上傳以下兩個檔案

  • <flutter_project_directory>/build/app/outputs/apk/debug/<file>.apk
  • <flutter_project_directory>/build/app/outputs/apk/androidTest/debug/<file>.apk

Firebase Test Lab upload two APKs

如果發生故障,你可以透過選擇紅色圖示檢視輸出內容:

Firebase Test Lab test results

透過指令上傳 Android APK

關於透過指令上傳 APK 的說明,請檢視 integration_test README 中的 Firebase Test Lab

上傳 Xcode 測試

瞭解如何將 .zip 檔案上傳到 Firebase 控制台的 Firebase Test Lab,請檢視 Firebase TestLab iOS instructions

透過指令上傳 Xcode 測試

關於如何透過指令上傳 .zip 檔案的說明,請檢視 integration_test README 中的 iOS Device Testing