内容简介:许多我们build的Widget不仅仅显示信息,也响应用户交互。包括可点击的按钮,在屏幕拖动控件,或者在文本框里输入文本。为了测试那些互动,我们需要一种在测试环境模拟它们的方法。为了这么做,我们需要使用这个
许多我们build的Widget不仅仅显示信息,也响应用户交互。包括可点击的按钮,在屏幕拖动控件,或者在文本框里输入文本。
为了测试那些互动,我们需要一种在测试环境模拟它们的方法。为了这么做,我们需要使用 flutter_test
类库的 WidgetTester
类。
这个 WidgetTester
提供了输入文本,点击,拖拽的方法。
在很多情况下,用户交互将会更新我们app的状态。在测试环境里,在状态改变后Flutter不会自动重新构建Widgets。为了确保我们的Widget树在我们模拟用户交互以后重新build,我们必须调用 WidgetTester
提供的 pump
或者 pumpAndSettle
方法。
步骤:
- 创建一个Widget用于测试
- 在输入框里输入文本
- 确保点击按钮会添加todo
- 确保滑动删除todo
1. 创建一个Widget用于测试
在这个例子里,我们将会创建一个基础的todo app。它将会有3个需要我们测试的主要功能:
TextField FloatingActionButton
为了保持焦点在测试上,这个例子将不会提供详细的构建todo app的界面。如果想学习更多关于如何构建app,请查看以下相关文章:
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. 在输入框里输入文本
现在我们有了一个todo app,我们可以开始写我们的测试了!在这个示例里,我们将会从输入文本到 TextField
开始。
我们可以这样完成任务:
- 在测试环境build一个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测试的核心概念,请查看下面的文章:
3. 确保点击按钮会添加todo
当我们在 TextField
里输入文本之后,我们希望点击 FloatingActionButton
会添加 item 到列表里。
这些步骤包括3步:
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); }); 复制代码
3. 滑动从列表中删除一个item
最后,我们要确保在滑动删除一条todo后可以从列表中删除它。这将包括以下3个步骤:
-
使用
drag
方法执行滑动删除操作。 -
使用
pumpAndSettle
方法不断的重新build我们的Widget树直到dismiss动画完成。 - 确保 item 从屏幕中消失。
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), ), ), ); } } 复制代码
以上所述就是小编给大家介绍的《Testing Flutter apps翻译-点击,拖动和输入文本》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 使用RxJava实现ImageView的拖动、旋转和缩放
- ios – 我正在使用XCode 7和Swift,我的控制拖动动作不起作用
- 探讨把一个元素从它所在的div 拖动到另一个div内的实现方法
- 基于标签特定文本表示的文本多标签分类
- 论文浅尝 | 通过文本到文本神经问题生成的机器理解
- 文本挖掘从小白到精通(三)---主题模型和文本数据转换
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
深入理解OpenCV
[巴西]Daniel Lelis Baggio / 刘波 / 机械工业出版社 / 2014-9 / 59
opencv是最常见的计算机视觉库之一,它提供了许多经过优化的复杂算法。本书对已掌握基本opencv技术同时想提高计算机视觉的实践经验的开发者来讲是一本非常好的书。每章都有一个单独的项目,其背景也在这些章节中进行了介绍。因此,读者可以依次学习这些项目,也可以直接跳到感兴趣的项目进行学习。 《深入理解opencv:实用计算机视觉项目解析》详细讲解9个实用的计算机视觉项目,通过本书的学习,读者可......一起来看看 《深入理解OpenCV》 这本书的介绍吧!