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 "<account>" 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 "<account>" from "AccountSelector" with "Enter Account Identifier" tooltip
And I select "<budget>" from "BudgetSelector" with "Enter Budget Category Name" tooltip
And I enter "<amount>" to "Set Amount" text field
And I select "<currency>" from "CodeCurrencySelector" with "Currency Type (Code)" tooltip
And I enter "<exchange>" to "<cur> Conversion" text field
And I enter "<account> - <budget>" to "Set Expense Details" text field
And I tap "Add new Bill" button
Then I can see "Accounts, total" component
And I can see "<account_rest>" component
And I can see "<budget_note>" component
And I can see "<budget_left>" 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
更多关于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_gherkin
和flutter_driver
依赖:
dependencies:
flutter:
sdk: flutter
flutter_test:
sdk: flutter
dev_dependencies:
flutter_driver:
sdk: flutter
flutter_gherkin: ^x.y.z # 替换为最新版本号
然后运行flutter pub get
来安装依赖。
创建测试环境
- 创建测试文件夹和文件
在你的项目根目录下创建一个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();
}
- 配置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);
}
- 编写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
- 编写步骤定义
在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);
}
}
- 运行测试
确保在gherkin.dart
文件中将步骤定义文件添加到stepDefinitions
列表中,然后运行以下命令来执行测试:
flutter drive --target=test_driver/app.dart
总结
以上代码案例展示了如何在Flutter项目中使用flutter_gherkin_wrapper
插件进行行为驱动开发。你需要设置测试环境、编写Feature文件、定义步骤,并运行测试。根据你的实际需求,你可能需要调整代码中的查找器和逻辑。