Flutter测试框架插件given_when_then的使用
Flutter测试框架插件given_when_then
的使用
given_when_then
是一个Flutter包,旨在使测试更加易读。如果你还不熟悉Flutter的Widget测试,请先花点时间了解一下。
原则
- Given:我们觉得测试是代码行为的最佳文档。
- When:当我们阅读我们的测试时。
- Then:我们希望它们易于理解。
虽然Flutter的Widget测试非常强大,但有时会显得有些冗长。这个包的目的是通过复用代码来简化测试,并使其更易读。
示例对比
传统方式(不使用given_when_then
)
testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
await tester.pumpWidget(MyWidget(title: 'T', message: 'M'));
final titleFinder = find.text('T');
final messageFinder = find.text('M');
// 使用 `findsOneWidget` 匹配器验证 Text 小部件在小部件树中出现一次。
expect(titleFinder, findsOneWidget);
expect(messageFinder, findsOneWidget);
});
使用given_when_then
的方式
testWidgets('MyWidget has a title and message', harness((given, when, then) async {
await given.pumpMyWidget(title: 'T', message: 'M');
then.myTitleIs('T');
then.myMessageIs('M');
}));
可以看到,通过将细节移动到WidgetTestGiven
、WidgetTestWhen
和WidgetTestThen
类中,我们可以去除不必要的细节,使测试更加简洁明了。
完整示例Demo
为了更好地展示如何使用given_when_then
,下面是一个完整的示例:
首先,在你的pubspec.yaml
文件中添加依赖:
dependencies:
flutter:
sdk: flutter
given_when_then: ^0.1.0 # 确保使用最新版本
dev_dependencies:
flutter_test:
sdk: flutter
接下来,创建一个简单的Widget进行测试:
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
final String title;
final String message;
MyWidget({required this.title, required this.message});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(child: Text(message)),
),
);
}
}
然后,编写测试代码:
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:given_when_then/given_when_then.dart';
import 'my_widget.dart'; // 引入上面定义的MyWidget
void main() {
testWidgets('MyWidget has a title and message', harness((given, when, then) async {
await given.pumpMyWidget(title: 'Hello', message: 'World');
then.myTitleIs('Hello');
then.myMessageIs('World');
}));
}
// 自定义的辅助函数
extension Given on WidgetTestGiven {
Future<void> pumpMyWidget({required String title, required String message}) async {
await pumpWidget(MaterialApp(
home: MyWidget(title: title, message: message),
));
}
}
extension Then on WidgetTestThen {
void myTitleIs(String expectedTitle) {
expect(find.text(expectedTitle), findsOneWidget);
}
void myMessageIs(String expectedMessage) {
expect(find.text(expectedMessage), findsOneWidget);
}
}
以上就是如何使用given_when_then
插件来编写更清晰、更易维护的测试代码的方法。更多详细信息可以参考官方示例。
更多关于Flutter测试框架插件given_when_then的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter测试框架插件given_when_then的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,given_when_then
是一个在 Flutter 测试中用于结构化测试逻辑的流行模式。虽然它不是一个官方的 Flutter 插件,但它可以通过一些辅助函数或自定义的封装来实现。下面是一个如何在 Flutter 测试中使用 given_when_then
模式的示例。
首先,我们假设我们有一个简单的 Flutter 应用,它有一个计数器,用户可以通过按钮来增加计数。
1. 示例应用代码
// main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CounterScreen(),
);
}
}
class CounterScreen extends StatefulWidget {
@override
_CounterScreenState createState() => _CounterScreenState();
}
class _CounterScreenState extends State<CounterScreen> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
2. 测试代码
接下来,我们使用 given_when_then
模式来编写测试代码。我们将使用 Flutter 的测试框架 flutter_test
。
// counter_screen_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Given: A counter with initial value 0
await tester.pumpWidget(MaterialApp(home: CounterScreen()));
// Find the text widget that displays the counter value.
final counterTextFinder = find.text('0');
expect(counterTextFinder, findsOneWidget);
// When: The button is tapped
await tester.tap(find.byIcon(Icons.add));
await tester.pump(); // This pumps a frame to update the UI
// Then: The counter value is incremented by 1
final counterTextAfterIncrement = find.text('1');
expect(counterTextAfterIncrement, findsOneWidget);
});
}
解释
- Given: 设置测试的前提条件。在这里,我们通过
tester.pumpWidget
方法渲染了CounterScreen
组件,并检查初始计数是否为0
。 - When: 模拟用户操作。在这个例子中,我们通过
tester.tap
方法模拟了用户点击浮动按钮的操作,并通过tester.pump
方法更新了 UI。 - Then: 验证结果。我们检查更新后的计数是否为
1
。
通过这种方式,我们可以确保我们的测试代码清晰、结构化,并且易于理解和维护。这种 given_when_then
模式不仅适用于 Flutter 测试,也广泛适用于其他类型的软件测试。