Flutter集成测试辅助插件integration_test_helper的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter集成测试辅助插件integration_test_helper的使用

简介

integration_test_helper 是一个用于加速Flutter应用端到端(E2E)测试部署的插件。它提供了预配置的方法,使得编写集成测试更加模块化和高效,减少了代码冗余,并且支持动态加载JSON数据进行黑盒测试。此外,它还支持所有主要的Widget交互操作,如点击、滑动等。

功能特点

  • 快速部署:通过预配置的方法,减少重复代码,提高测试效率。
  • 黑盒测试:支持从项目资源目录加载JSON数据进行测试,适用于ListView和其他类型的Widgets。
  • 平台特定实现:可以根据不同的平台(如Android和iOS)提供不同的测试逻辑。
  • 完整的测试覆盖率:帮助开发者编写更全面的测试用例,减少回归问题。

使用示例

1. 添加依赖

pubspec.yaml 文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.2
  drawer_manager: ^0.0.4

dev_dependencies:
  flutter_test:
    sdk: flutter
  integration_test:
    sdk: flutter
  integration_test_helper: ^latest_version

2. 创建主应用文件 lib/main.dart

创建一个包含Drawer导航的应用程序,用于展示不同页面。以下是 main.dart 的完整代码:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:drawer_manager/drawer_manager.dart';

import 'hello.dart'; // 自定义页面

void main() {
  runApp(setupMainWidget());
}

Widget setupMainWidget() {
  WidgetsFlutterBinding.ensureInitialized();
  return const MyApp();
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<DrawerManagerProvider>(
      create: (_) => DrawerManagerProvider(),
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(primarySwatch: Colors.blue),
        home: const MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key}) : super(key: key);

  String _getTitle(int index) {
    switch (index) {
      case 0:
        return 'Hello 1';
      case 1:
        return 'Hello 2';
      default:
        return '';
    }
  }

  Widget _getTitleWidget() {
    return Consumer<DrawerManagerProvider>(builder: (context, dmObj, _) {
      return Text(
        _getTitle(dmObj.selection),
        key: const Key('app-bar-text'),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    final drawerSelections = [
      const HelloPage(position: 1),
      const HelloPage(position: 2),
    ];

    final manager = Provider.of<DrawerManagerProvider>(context, listen: false);

    return Scaffold(
      appBar: AppBar(title: _getTitleWidget()),
      body: manager.body,
      drawer: DrawerManager(
        context,
        drawerElements: [
          const DrawerHeader(
            decoration: BoxDecoration(color: Colors.blue),
            child: Padding(
              padding: EdgeInsets.only(bottom: 20),
              child: Icon(
                Icons.account_circle,
                color: Colors.blueGrey,
                size: 96,
              ),
            ),
          ),
          DrawerTile(
            key: const Key('drawer-hello-1'),
            context: context,
            leading: const Icon(Icons.hail_rounded),
            title: Text(_getTitle(0)),
            onTap: () async {},
          ),
          DrawerTile(
            key: const Key('drawer-hello-2'),
            context: context,
            leading: const Icon(Icons.hail_rounded),
            title: Text(_getTitle(1)),
            onTap: () async {},
          ),
        ],
        tileSelections: drawerSelections,
      ),
    );
  }
}

3. 创建页面文件 lib/hello.dart

创建一个简单的页面,用于展示不同的文本内容。以下是 hello.dart 的完整代码:

import 'package:flutter/material.dart';

class HelloPage extends StatelessWidget {
  final int position;

  const HelloPage({Key? key, required this.position}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        'Hello, Flutter $position!',
        key: Key('hello-page-text-$position'),
        textAlign: TextAlign.center,
        style: const TextStyle(
          color: Color(0xff0085E0),
          fontSize: 48,
          fontWeight: FontWeight.bold,
        ),
      ),
    );
  }
}

4. 创建集成测试文件 integration_test/app_features.dart

integration_test 目录下创建一个测试文件,用于编写集成测试用例。以下是 app_features.dart 的完整代码:

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

import 'package:example/main.dart' as app;
import 'app_feature_groups.dart';

void main() async {
  IntegrationTestHelperBinding.ensureInitialized();

  testWidgets('Testing end to end single-screen integration', (WidgetTester tester) async {
    final main = app.setupMainWidget();
    final integrationTestGroups = ScreenIntegrationTestGroups();
    await integrationTestGroups.initializeTests(tester, main);

    await integrationTestGroups.testHelloFlutterFeature();
  }, timeout: const Timeout(Duration(minutes: 1)));
}

5. 创建测试组文件 integration_test/app_feature_groups.dart

integration_test 目录下创建一个测试组文件,用于定义具体的测试逻辑。以下是 app_feature_groups.dart 的完整代码:

import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test_helper/integration_test_helper.dart';

class ScreenIntegrationTestGroups extends BaseIntegrationTest {
  @override
  Future<void> setupInitialData() async {
    // 初始化测试数据
  }

  @override
  Future<bool> isPlatformAndroid() async {
    return Future.value(true);
  }

  Future<void> showHelloFlutter({required int position}) async {
    print('Showing Hello, Flutter $position!');
    if (Platform.isAndroid) {
      await tapForTooltip('Open navigation menu');
      await tapForKey('drawer-hello-$position');
    }
    await waitForUI();
  }

  Future<void> testHelloFlutterFeature() async {
    await showHelloFlutter(position: 1);
    await verifyTextForKey('app-bar-text', 'Hello 1');
    await verifyTextForKey('hello-page-text-1', 'Hello, Flutter 1!');

    await showHelloFlutter(position: 2);
    await verifyTextForKey('app-bar-text', 'Hello 2');
    await verifyTextForKey('hello-page-text-2', 'Hello, Flutter 2!');
  }
}

6. 创建驱动文件 test_driver/app_features_test.dart

test_driver 目录下创建一个驱动文件,用于运行集成测试。以下是 app_features_test.dart 的完整代码:

import 'package:integration_test/integration_test_driver.dart';

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

7. 运行集成测试

在终端中运行以下命令来启动集成测试:

flutter drive -t integration_test/app_features.dart

更多关于Flutter集成测试辅助插件integration_test_helper的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter集成测试辅助插件integration_test_helper的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter项目中,integration_test_helper 插件通常用于简化和标准化集成测试流程。尽管Flutter社区没有官方的 integration_test_helper 插件,但开发者通常会创建自定义的辅助类来帮助管理集成测试中的共享逻辑。

以下是一个示例,展示了如何创建一个简单的 integration_test_helper.dart 文件,并在集成测试中使用它。

1. 创建 integration_test_helper.dart

首先,在你的项目根目录下创建一个 test_driver 文件夹(如果还没有的话),然后在该文件夹中创建一个 integration_test_helper.dart 文件。

// test_driver/integration_test_helper.dart
import 'package:flutter_driver/flutter_driver.dart';
import 'package:flutter_test/flutter_test.dart';

class IntegrationTestHelper {
  FlutterDriver driver;

  IntegrationTestHelper(this.driver);

  Future<void> tapOnButtonWithText(String text) async {
    SerializableFinder buttonFinder = find.text(text);
    await driver.tap(buttonFinder);
  }

  Future<String> getTextFromWidgetWithText(String key) async {
    SerializableFinder textFinder = find.byTooltip(key); // or use find.byValueKey, etc.
    String text = await driver.getText(textFinder);
    return text;
  }

  // Add more helper functions as needed
}

2. 编写集成测试

接下来,在你的 integration_test 文件夹中创建一个测试文件,例如 example_test.dart,并在其中使用你创建的辅助类。

// integration_test/example_test.dart
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';
import 'package:your_app/test_driver/integration_test_helper.dart';

void main() {
  group('Integration tests', () {
    FlutterDriver driver;
    IntegrationTestHelper testHelper;

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

    tearDownAll(() async {
      if (driver != null) {
        driver.close();
      }
    });

    test('taps on a button and reads the text', () async {
      // Launch the app with a route name
      await driver.tap(find.byTooltip('Open Home Screen')); // Adjust this to match your app's startup logic
      await Future<void>.delayed(const Duration(seconds: 2)); // Allow time for the screen to load

      // Use the helper function to tap on a button
      await testHelper.tapOnButtonWithText('Tap Me');

      // Use the helper function to read text from a widget
      String resultText = await testHelper.getTextFromWidgetWithText('resultTextKey');

      // Verify the result
      expect(resultText, 'Expected Text');
    });
  });
}

3. 运行集成测试

确保你的 pubspec.yaml 文件中包含了 flutter_driver 依赖,并且你已经添加了 integration_test 目录到你的项目中。

# pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  flutter_driver:
    sdk: flutter

dev_dependencies:
  test: ^1.16.0
  flutter_test:
    sdk: flutter

然后,你可以使用以下命令运行集成测试:

flutter drive --target=integration_test/example_test.dart

总结

通过创建一个 integration_test_helper.dart 文件,并将常用的测试操作封装成方法,可以极大地简化集成测试的代码,提高测试的可读性和可维护性。上面的例子展示了如何定义和使用这样的辅助类。根据你的具体需求,你可以进一步扩展这个辅助类,添加更多的实用方法。

回到顶部