integration_test

此包支持在设备和模拟器上对 Flutter 代码进行自驾测试。
它将 flutter_test 的结果适配为与 flutter drive 兼容的格式
以及原生的 Android instrumentation 测试。

用法

pubspec.yamldev_dependencies 部分添加 integration_testflutter_test 包的依赖。对于插件,请在示例应用的
pubspec.yaml 中进行操作。
为您的包创建一个 integration_test/ 目录。在此目录中,

integration_test:
  sdk: flutter

创建一个 <name>_test.dart 文件,并使用以下内容作为起点进行断言。
创建 integration_test/ 目录。在此目录中,
创建 <name>_test.dart 文件,并使用以下内容作为起点进行断言。

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

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets("failing test example", (WidgetTester tester) async {
    expect(2 + 2, equals(5));
  });
}

驱动程序入口点

需要一个配套的驱动程序脚本,该脚本可以跨所有
集成测试共享。在 test_driver/ 目录中创建一个名为 integration_test.dart 的文件,其内容如下:
test_driver/ 目录中,内容如下:

import 'package:integration_test/integration_test_driver.dart';

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

您也可以使用不同的驱动程序脚本来定制被测应用的行为。
例如,FlutterDriver 也可以通过不同的 选项 进行参数化。
选项
请参阅 扩展驱动程序 示例。

软件包结构

您的包应该具有如下结构:

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

示例

使用 Flutter Driver 运行测试

可以使用 flutter drive 命令启动这些测试。

要使用
test_driver/integration_test.dart 驱动程序运行 integration_test/foo_test.dart 测试,请使用以下命令:

flutter drive \
  --driver=test_driver/integration_test.dart \
  --target=integration_test/foo_test.dart

Web

请确保您已 启用 Web 支持
然后 下载并运行
Web 驱动程序并使其在另一个进程中运行。

使用以下命令执行测试:

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

截图

您可以使用 integration_test 在测试期间的特定时间截取移动设备或
Web 浏览器上渲染的 UI 的屏幕截图。

此功能目前支持 Android、iOS 和 Web。

Android 和 iOS

integration_test/screenshot_test.dart

void main() {
  final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized()
      as IntegrationTestWidgetsFlutterBinding;

  testWidgets('screenshot', (WidgetTester tester) async {
    // Build the app.
    app.main();

    // This is required prior to taking the screenshot (Android only).
    await binding.convertFlutterSurfaceToImage();

    // Trigger a frame.
    await tester.pumpAndSettle();
    await binding.takeScreenshot('screenshot-1');
  });
}

您可以使用驱动程序脚本从设备中拉取屏幕截图。
这样,您就可以将图片本地存储在计算机上。在 iOS 上,
屏幕截图也将在 Xcode 测试结果中提供。

test_driver/integration_test.dart

import 'dart:io';
import 'package:integration_test/integration_test_driver_extended.dart';

Future<void> main() async {
  await integrationDriver(
    onScreenshot: (String screenshotName, List<int> screenshotBytes) async {
      final File image = File('$screenshotName.png');
      image.writeAsBytesSync(screenshotBytes);
      // Return false if the screenshot is invalid.
      return true;
    },
  );
}

Web

integration_test/screenshot_test.dart

void main() {
  final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized()
      as IntegrationTestWidgetsFlutterBinding;

  testWidgets('screenshot', (WidgetTester tester) async {
    // Build the app.
    app.main();

    // Trigger a frame.
    await tester.pumpAndSettle();
    await binding.takeScreenshot('screenshot-1');
  });
}

Android 设备测试

在您的应用程序的
android/app/src/androidTest/java/com/example/myapp/ 目录中创建一个 instrumentation 测试文件(将
com、example 和 myapp 替换为您的应用的包名对应的值)。您可以将
此测试文件命名为 MainActivityTest.java 或您选择的任何其他名称。

package com.example.myapp;

import androidx.test.rule.ActivityTestRule;
import dev.flutter.plugins.integration_test.FlutterTestRunner;
import org.junit.Rule;
import org.junit.runner.RunWith;

@RunWith(FlutterTestRunner.class)
public class MainActivityTest {
  @Rule
  public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class, true, false);
}

更新您的应用程序的 myapp/android/app/build.gradle,以确保它
使用 androidx 版本的 AndroidJUnitRunner 并将 androidx 库作为
依赖项。

android {
  ...
  defaultConfig {
    ...
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
  }
}

dependencies {
    testImplementation 'junit:junit:4.12'

    // https://developer.android.com.cn/jetpack/androidx/releases/test/#1.2.0
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

要在本地 Android 设备(模拟或
实体)上运行 integration_test/foo_test.dart,请执行以下操作:

./gradlew app:connectedAndroidTest -Ptarget=`pwd`/../integration_test/foo_test.dart

Firebase Test Lab

如果您是第一次使用 Firebase Test Lab 进行测试,您需要遵循
Firebase Test Lab
文档
中的指南
来设置项目。

要使用 Firebase Test Lab 在 Android 设备上运行测试,请使用 gradle 命令构建一个
Android 的 instrumentation 测试,并在最后一个部分中根据建议创建 androidTest

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

将构建的 apks 上传到 Firebase Test Lab,并确保替换 <PATH_TO_KEY_FILE>、
<PROJECT_NAME>、<RESULTS_BUCKET> 和 <RESULTS_DIRECTORY> 为您的值。

gcloud auth activate-service-account --key-file=<PATH_TO_KEY_FILE>
gcloud --quiet config set project <PROJECT_NAME>
gcloud firebase test android run --type instrumentation \
  --app build/app/outputs/apk/debug/app-debug.apk \
  --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk\
  --timeout 2m \
  --results-bucket=<RESULTS_BUCKET> \
  --results-dir=<RESULTS_DIRECTORY>

您可以在命令行中传递其他参数,例如
您想测试的设备。请参阅
gcloud firebase test android run.

iOS 设备测试

在 Xcode 中打开 ios/Runner.xcworkspace。如果您的项目
还没有测试目标,请通过 File > New > Target... 创建一个,并选择 Unit Testing Bundle
Product Name 更改为 RunnerTests。确保 Target to be Tested 设置为 Runner,语言设置为 Objective-C
选择 Finish
确保 RunnerTests 的 **iOS Deployment Target** 在 **Build Settings** 部分与 Runner 相同。

通过将新测试目标嵌入到现有的 Runner 目标中,将其添加到 ios/Podfile

target 'Runner' do
  # Do not change existing lines.
  ...

  target 'RunnerTests' do
    inherit! :search_paths
  end
end

要从命令行构建 integration_test/foo_test.dart,请运行:

flutter build ios --config-only integration_test/foo_test.dart

在 Xcode 中,为新目标添加一个名为 RunnerTests.m(或您选择的任何名称)的测试文件,并
替换该文件。

@import XCTest;
@import integration_test;

INTEGRATION_TEST_IOS_RUNNER(RunnerTests)

运行 Product > Test 以在您选择的设备上运行集成测试。

要将其部署到 Firebase Test Lab,您可以遵循以下步骤:

在您的 Flutter 应用的根目录下执行此脚本:

output="../build/ios_integ"
product="build/ios_integ/Build/Products"
dev_target="14.3"

# Pass --simulator if building for the simulator.
flutter build ios integration_test/foo_test.dart --release

pushd ios
xcodebuild -workspace Runner.xcworkspace -scheme Runner -config Flutter/Release.xcconfig -derivedDataPath $output -sdk iphoneos build-for-testing
popd

pushd $product
zip -r "ios_tests.zip" "Release-iphoneos" "Runner_iphoneos$dev_target-arm64.xctestrun"
popd

您可以通过运行以下命令在本地验证您的测试是否成功:

xcodebuild test-without-building -xctestrun "build/ios_integ/Build/Products/Runner_iphoneos14.3-arm64.xctestrun" -destination id=<YOUR_DEVICE_ID>

一切正常后,您可以将生成的 zip 文件上传到 Firebase Test Lab(更改模型为您自己的值)。

gcloud firebase test ios run --test "build/ios_integ/Build/Products/ios_tests.zip" --device model=iphone11pro,version=14.1,locale=fr_FR,orientation=portrait

GitHub

查看 Github