内容简介:我们构建的许多widget不仅显示信息,还要响应用户交互。这包括用户可以点击的按钮,在屏幕上拖动条目或在TextField中输入文本。为了测试这些交互,我们需要一种在测试环境中模拟它们的方法。为此,我们可以使用
我们构建的许多widget不仅显示信息,还要响应用户交互。这包括用户可以点击的按钮,在屏幕上拖动条目或在TextField中输入文本。
为了测试这些交互,我们需要一种在测试环境中模拟它们的方法。为此,我们可以使用 flutter_test 库提供的 WidgetTester 类。
WidgetTester
提供了输入文本,点击和拖动的方法。
- enterText
- tap
- darg
在许多情况下,用户交互将更新我们的应用程序的状态。在测试环境中,当状态更改时,Flutter不会自动重建widget。为了确保在模拟用户交互之后重建我们的Widget树,我们必须调用 WidgetTester
提供的 pump
或 pumpAndSettle
方法。
路径
- 创建一个要测试的widget
- 在文本字段中输入文本
- 确保点击按钮添加待办事项
- 确保滑动删除会删除待办事项
1.创建一个要测试的widget
对于此示例,我们将创建一个基本的待办事项应用程序。它将有三个我们想要测试的主要功能:
- 在TextField中输入文本
- 点击FloatingActionButton会将文本添加到待办事项列表中
- 滑动删除会从列表中删除该条目
为了将重点放在测试上,此配方将不提供有关如何构建待办事项应用程序的详细指南。要了解有关如何构建此应用程序的更多信息,请参阅相关配方:
class TodoList extends StatefulWidget { @override _TodoListState createState() => _TodoListState(); } class _TodoListState extends State<TodoList> { static const _appTitle = 'Todo List'; final todos = <String>[]; final controller = TextEditingController(); @override Widget build(BuildContext context) { return MaterialApp( title: _appTitle, home: Scaffold( appBar: AppBar( title: Text(_appTitle), ), body: Column( children: [ TextField( controller: controller, ), Expanded( child: ListView.builder( itemCount: todos.length, itemBuilder: (BuildContext context, int index) { final todo = todos[index]; return Dismissible( key: Key('$todo$index'), onDismissed: (direction) => todos.removeAt(index), child: ListTile(title: Text(todo)), background: Container(color: Colors.red), ); }, ), ), ], ), floatingActionButton: FloatingActionButton( onPressed: () { setState(() { todos.add(controller.text); controller.clear(); }); }, child: Icon(Icons.add), ), ), ); } }
2.在 text field
中输入文本
现在我们有了一个todo应用程序,我们就可以开始编写测试了!在这种情况下,我们首先在 TextField
中输入文本。
我们可以通过以下方式完成此任务
- 在测试环境中构建Widget
-
使用
WidgetTester
中的 enterText 方法
testWidgets('Add and remove a todo', (WidgetTester tester) async { // Build the Widget await tester.pumpWidget(TodoList()); // Enter 'hi' into the TextField await tester.enterText(find.byType(TextField), 'hi'); });
注意:此配方基于之前的Widget测试配方。要了解Widget测试的核心概念,请参阅以下配方:
3.确保点击按钮添加待办事项
在我们将文本输入TextField之后,我们要确保点击FloatingActionButton将该项添加到列表中。
这将涉及三个步骤:
- 使用tap方法点击添加按钮
- 使用pump方法更改状态后重建Widget
- 确保列表项显示在页面上
testWidgets('Add and remove a todo', (WidgetTester tester) async { // Enter text code... // Tap the add button await tester.tap(find.byType(FloatingActionButton)); // Rebuild the Widget after the state has changed await tester.pump(); // Expect to find the item on screen expect(find.text('hi'), findsOneWidget); });
4. 确保滑动删除会删除待办事项
最后,我们可以确保对todo项执行滑动删除操作会将其从列表中删除。这将涉及三个步骤:
- 使用 drag 方法执行滑动到解除操作。
- 使用 pumpAndSettle 方法不断重建我们的Widget树,直到dismiss动画完成。
- 确保屏幕上不再显示该条目。
testWidgets('Add and remove a todo', (WidgetTester tester) async { // Enter text and add the item... // Swipe the item to dismiss it await tester.drag(find.byType(Dismissible), Offset(500.0, 0.0)); // Build the Widget until the dismiss animation ends await tester.pumpAndSettle(); // Ensure the item is no longer on screen expect(find.text('hi'), findsNothing); });
完整代码
一旦我们完成了这些步骤,我们应该有了带有测试的一个工作的应用程序,其测试部分能确保它正常工作!
import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('Add and remove a todo', (WidgetTester tester) async { // Build the Widget await tester.pumpWidget(TodoList()); // Enter 'hi' into the TextField await tester.enterText(find.byType(TextField), 'hi'); // Tap the add button await tester.tap(find.byType(FloatingActionButton)); // Rebuild the Widget with the new item await tester.pump(); // Expect to find the item on screen expect(find.text('hi'), findsOneWidget); // Swipe the item to dismiss it await tester.drag(find.byType(Dismissible), Offset(500.0, 0.0)); // Build the Widget until the dismiss animation ends await tester.pumpAndSettle(); // Ensure the item is no longer on screen expect(find.text('hi'), findsNothing); }); } class TodoList extends StatefulWidget { @override _TodoListState createState() => _TodoListState(); } class _TodoListState extends State<TodoList> { static const _appTitle = 'Todo List'; final todos = <String>[]; final controller = TextEditingController(); @override Widget build(BuildContext context) { return MaterialApp( title: _appTitle, home: Scaffold( appBar: AppBar( title: Text(_appTitle), ), body: Column( children: [ TextField( controller: controller, ), Expanded( child: ListView.builder( itemCount: todos.length, itemBuilder: (BuildContext context, int index) { final todo = todos[index]; return Dismissible( key: Key('$todo$index'), onDismissed: (direction) => todos.removeAt(index), child: ListTile(title: Text(todo)), background: Container(color: Colors.red), ); }, ), ), ], ), floatingActionButton: FloatingActionButton( onPressed: () { setState(() { todos.add(controller.text); controller.clear(); }); }, child: Icon(Icons.add), ), ), ); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Web聊天工具的富文本输入框
- 由Vue实现限制文本框输入长度引发的思考
- 由Vue实现限制文本框输入长度引发的思考
- Testing Flutter apps翻译-点击,拖动和输入文本
- Egret 5.4.1 版本发布,修复文本输入、自定义字体宽度异常等问题
- Android输入系统(一)输入事件传递流程和InputManagerService的诞生
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。