Flutter行为驱动开发插件flutter_gherkin_wrapper的使用

Flutter行为驱动开发插件flutter_gherkin_wrapper的使用

flutter_gherkin_wrapper 是一个基于 gherkin 包的封装,用于在简化模式下使用 Cucumber/Gherkin 语法执行小部件和集成测试。它需要与 flutter_gherkin_generator 包一起使用。

开始使用

检查 示例

安装

dev_dependencies:
  flutter_gherkin_generator: 1.0.4
  flutter_gherkin_wrapper: 1.0.4
  build_runner: ^2.4.6

运行

dart run build_runner build --delete-conflicting-outputs
flutter test

初始化

// 从资源生成步骤
// ./test/e2e/given/generic.dart
@GenerateGherkinResources(['../steps'])
class Generics extends GivenGeneric {
  @override
  RegExp get pattern => RegExp('%step%');

  @override
  // 执行子步骤
  Future<void> executeStep() async {
    final reporter = FileReporter();
    final step = await FileReader().getFromString('''%feature%''', reporter);
    final result = await FileRunner(FileRunner.tester, reporter).run(step);
    if (!result) {
      reporter.publish();
    }
    expectSync(result, true);
  }
}
# /test/e2e/steps/open_expense_form.resource.feature
Feature: Verify Basic Actions

  Scenario: Opened Expense Form
    Given I am on "Home" page
     When I tap "Add Bill, Income or Transfer" button
     Then I can see "Add new Bill" button

执行

// 生成步骤列表
@GenerateListOfClasses(['given', 'when', 'then'])
import 'steps_iterator.list.dart';

void main() {
  Iterable<File> features = Directory('./test/e2e')
      .listSync(recursive: true)
      .where(
          (entity) => entity is File && entity.path.endsWith('.test.feature'))
      .cast<File>();

  setUpAll(() {
    TestWidgetsFlutterBinding.ensureInitialized();
    ScreenCapture.enableScreenCapture();
    ExecutableStepIterator.inject(classList);
    // MainTest.cleanUpData();
  });

  group('Run All End-To-End Tests', () {
    for (var file in features) {
      testWidgets(file.path, (WidgetTester tester) async {
        // await MainTest.init(tester);
        final runner = FileRunner(tester);
        await runner.init(file);
        // ! 为了在并发请求中避免冲突
        expectSync(await runner.run(), true);
        await tester.pumpAndSettle();
      }, timeout: const Timeout(Duration(minutes: 5)));
    }
  });
}
# /test/e2e/bill/create_different_expenses.test.feature
Feature: Verify Expenses Functionality

  Scenario Outline: Added different Expenses
    Given Opened Expense Form
     When I select "&lt;account&gt;" from "AccountSelector" with "Enter Account Identifier" tooltip
      And ...

示例代码

// 检查 "Fingrom" 应用程序的广泛使用:
/* 
https://github.com/lyskouski/app-finance/tree/main/test/e2e

Feature: Verify Expenses Functionality

  Scenario: Set Up
    Given Created different Account types
      And Created different Budget types

  Scenario Outline: Added different Expenses
    Given Opened Expense Form
     When I select "&lt;account&gt;" from "AccountSelector" with "Enter Account Identifier" tooltip
      And I select "&lt;budget&gt;" from "BudgetSelector" with "Enter Budget Category Name" tooltip
      And I enter "&lt;amount&gt;" to "Set Amount" text field
      And I select "&lt;currency&gt;" from "CodeCurrencySelector" with "Currency Type (Code)" tooltip
      And I enter "&lt;exchange&gt;" to "&lt;cur&gt; Conversion" text field
      And I enter "&lt;account&gt; - &lt;budget&gt;" to "Set Expense Details" text field
      And I tap "Add new Bill" button
     Then I can see "Accounts, total" component
      And I can see "&lt;account_rest&gt;" component
      And I can see "&lt;budget_note&gt;" component
      And I can see "&lt;budget_left&gt;" component

    Examples:
    | account      | cur | budget    | amount | currency | exchange | account_rest |       budget_note |   budget_left |
    | Bank Account | EUR | Limited   |     20 | PLN      |     0.50 |       €90.00 |  €10.00 / €100.00 |   €90.00 left |
    | Cash         | USD | Limited   |     50 | PLN      |     2.00 |      $900.00 |  €35.00 / €100.00 |   €65.00 left |
    | Credit Card  | JPY | Unlimited |    100 | PLN      |     0.01 |       ¥1,499 |         Unlimited | $200.00 spent |
    | Debit Card   | GBP | Group / 1 |     25 | PLN      |     0.40 |      £490.26 |  $50.00 / $125.00 |         Group |
    | Bank Account | EUR | Group / 2 |      5 | PLN      |     2.20 |       €79.00 |  $60.00 / $125.00 |         Group |
    | Cash         | USD | Group / 2 |     10 | PLN      |     4.50 |      $855.00 | $105.00 / $125.00 |         Group |

  Scenario: Tear Down
    Given I am on "Currencies" page
     Then I can see "PLN-EUR" component
     Then I can see "2.2" component
     Then I can see "PLN-USD" component
     Then I can see "4.5" component
     Then I can see "PLN-JPY" component
     Then I can see "0.01" component
     Then I can see "PLN-GBP" component
     Then I can see "0.4" component
*/

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

// import 'test/main_test.dart';
import 'package:flutter_gherkin_wrapper/flutter_gherkin_wrapper.dart';

void main() {
  Iterable<File> features = Directory('./test/e2e')
      .listSync(recursive: true)
      .where(
          (entity) => entity is File && entity.path.endsWith('.test.feature'))
      .cast<File>();

  setUpAll(() {
    TestWidgetsFlutterBinding.ensureInitialized();
    // MainTest.cleanUpData();
  });

  group('Run All End-To-End Tests', () {
    for (var file in features) {
      testWidgets(file.path, (WidgetTester tester) async {
        // await MainTest.init(tester);
        final runner = FileRunner(tester);
        await runner.init(file);
        // ! 为了在并发请求中避免冲突
        expectSync(await runner.run(), true);
        await tester.pumpAndSettle();
      }, timeout: const Timeout(Duration(minutes: 5)));
    }
  });
}

更多关于Flutter行为驱动开发插件flutter_gherkin_wrapper的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter行为驱动开发插件flutter_gherkin_wrapper的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用flutter_gherkin_wrapper插件进行行为驱动开发(BDD)的代码案例。flutter_gherkin_wrapper是一个Flutter库,它允许你使用Gherkin语法编写BDD测试。

环境设置

首先,确保你的Flutter项目已经创建好,并且在pubspec.yaml文件中添加flutter_gherkinflutter_driver依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_test:
    sdk: flutter

dev_dependencies:
  flutter_driver:
    sdk: flutter
  flutter_gherkin: ^x.y.z  # 替换为最新版本号

然后运行flutter pub get来安装依赖。

创建测试环境

  1. 创建测试文件夹和文件

在你的项目根目录下创建一个test_driver文件夹,并在其中创建一个名为app.dart的文件,用于启动Flutter应用:

// test_driver/app.dart
import 'package:flutter_driver/flutter_driver.dart';
import 'package:flutter_gherkin/flutter_gherkin.dart';
import 'package:your_app_name/main.dart' as app; // 替换为你的主应用文件

void main() {
  enableFlutterDriverExtension();
  app.main();
}
  1. 配置Gherkin

test_driver文件夹中创建一个名为gherkin.dart的文件,用于配置Gherkin:

// test_driver/gherkin.dart
import 'package:flutter_gherkin/flutter_gherkin.dart';
import 'package:gherkin/gherkin.dart';

Future<void> main() {
  final config = FlutterTestConfiguration()
      ..featureDirectory = 'test_driver/features' // 存放你的feature文件
      ..stepDefinitions = [
        // 你可以在这里添加你的步骤定义文件
      ]
      ..reporter = [
        ProgressReporter(),
        JsonReporter(path: './report.json'), // 可选:生成JSON格式的测试报告
      ]
      ..hook = () async {}; // 可选:设置全局钩子

  return GherkinRunner()
      .execute(configuration: config);
}
  1. 编写Feature文件

test_driver/features文件夹中创建一个名为example.feature的文件,用于编写Gherkin测试用例:

# test_driver/features/example.feature
Feature: Example feature

  Scenario: Simple test
    Given I am on the home screen
    When I tap on the button
    Then I should see a message
  1. 编写步骤定义

test_driver文件夹中创建一个名为step_definitions的文件夹,并在其中创建一个名为example_steps.dart的文件,用于定义步骤:

// test_driver/step_definitions/example_steps.dart
import 'package:flutter_driver/flutter_driver.dart';
import 'package:flutter_gherkin/flutter_gherkin.dart';
import 'package:gherkin/gherkin.dart';

class ExampleSteps extends DefaultWorld implements IWorld {
  FlutterDriver? _driver;

  @override
  Future<void> setUp() async {
    _driver = await FlutterDriver.connect();
  }

  @override
  Future<void> tearDown() async {
    await _driver?.close();
    _driver = null;
  }

  @Given(r'I am on the home screen')
  Future<void> iAmOnTheHomeScreen() async {
    // 实现导航到首页的逻辑
  }

  @When(r'I tap on the button')
  Future<void> iTapOnTheButton() async {
    // 实现点击按钮的逻辑
    await _driver!.tap(find.byTooltip('Button Tooltip')); // 替换为实际的查找器
  }

  @Then(r'I should see a message')
  Future<void> iShouldSeeAMessage() async {
    // 实现验证消息显示的逻辑
    SerializableFinder messageFinder = find.text('Message Text'); // 替换为实际的查找器
    expect(await _driver!.waitFor(messageFinder), findsOneWidget);
  }
}
  1. 运行测试

确保在gherkin.dart文件中将步骤定义文件添加到stepDefinitions列表中,然后运行以下命令来执行测试:

flutter drive --target=test_driver/app.dart

总结

以上代码案例展示了如何在Flutter项目中使用flutter_gherkin_wrapper插件进行行为驱动开发。你需要设置测试环境、编写Feature文件、定义步骤,并运行测试。根据你的实际需求,你可能需要调整代码中的查找器和逻辑。

回到顶部