Widget测试介绍

发表于:2019-4-29 11:53

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:o动感超人o    来源:掘金

  在单元测试的介绍里,我们学习到了如何使用test包测试Dart类,为了测试Widget类,我们需要一些由flutter test包提供的额外工具,这些工具随Flutter SDK发布。
  这个flutter_test包提供了以下用于测试Widget的工具:
  WidgetTester:该工具允许我们在测试环境里build Widget并与之交互。
  使用testWidgets函数。这个函数将自动对每个测试用例创建一个WidgetTester,并用于替代普通的test函数。
  Finder classes:该工具允许我们在测试环境里查找Widget。
  Widget Matcher:一些常量,帮助我们验证在测试环境里是否找到一个或者多个Widget。
  如果上面的内容听不懂的话,没关系,让我们通过一些例子来将上面的碎片信息串联到一起。
  步骤:
  添加flutter_test依赖。
  创建一个Widget用来测试。
  创建一个testWidgets测试方法。
  使用WidgetTesterbuild一个Widget
  使用Finder搜索我们的Widget。
  使用Matcher验证我们的Widget是否工作正常。
  1. 添加flutter_test依赖。
  在我们开始写测试之前,我们需要在pubspec.yaml文件的dev_dependencies行下面添加flutter_test包。如果你通过命令行或者编译器创建的Flutter项目,那么该依赖已经添加好了。
   dev_dependencies:
  flutter_test:
  sdk: flutter
  2. 创建一个Widget用来测试。
  下一步,我们需要创建一个能让我们测试的Widget。在这个例子里,我们创建了显示一个标题和一条信息的Widget。
   class MyWidget extends StatelessWidget {
  final String title;
  final String message;
  const MyWidget({
  Key key,
  @required this.title,
  @required this.message,
  }) : super(key: key);
  @override
  Widget build(BuildContext context) {
  return MaterialApp(
  title: 'Flutter Demo',
  home: Scaffold(
  appBar: AppBar(
  title: Text(title),
  ),
  body: Center(
  child: Text(message),
  ),
  ),
  );
  }
  }
  3. 创建一个testWidgets测试方法
  现在我们有了一个可以用来测试的Widget,我们可以编写我们第一个测试用例了!我们将会使用flutter_test包提供的testWidgets函数完成一个测试用例。这个testWidgets函数将会允许我们定义一个Widget测试用例并创建一个WidgetTester给我们使用。
  我们的测试将会验证MyWidget类是否正常显示给定的标题和信息。
   void main() {
  // Define a test. The TestWidgets function will also provide a WidgetTester
  // for us to work with. The WidgetTester will allow us to build and interact
  // with Widgets in the test environment.
  testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
  // Test code will go here!
  });
  }
  4. 使用WidgetTesterbuild一个Widget
  下一步,我们将会在测试环境里build我们的MyWidget类。为了这么做,我们将使用WidgetTester提供的pumpWidget方法。这个pumpWidget方法将会build和渲染我们提供的Widget。
  在这个示例里,我们将会创建一个显示标题“T”和消息“M”的MyWidget实例。
   void main() {
  testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
  // Create the Widget tell the tester to build it
  await tester.pumpWidget(MyWidget(title: 'T', message: 'M'));
  });
  }
   备注:
  第一次调用pumpWidget之后,WidgetTester提供了重新创建相同Widget的其他方式。如果你使用StatefulWidget或者动画,这将会非常有用。
  例如,如果我们点击一个按钮,并且这个按钮调用了setState方法,Flutter不会在测试环境里rebuild你的Widget。我们需要使用下面的方法之一来告诉Flutter再一次build我们的Widget。
  tester.pump()
  在一个给定的时间以后rebuild你的Widget。
  tester.pumpAndSettle()
  在给定的时间不断重复调用pump方法直到不再有任何绘制任务。一般用于等待所有动画完成。
  这些方法提供了比build生命周期更细粒度的控制,这在测试的时候特别有用。
  5. 使用Finder搜索我们的Widget。
  现在我们已经在测试环境构建了我们的Widget,我们想要通过使用Finder在Widget树里搜索我们的title和messageWidget。这将允许我们验证是否正确显示了那些Widget!
  在这个例子里,我们将会使用flutter_test包提供的顶级find方法去创建我们的Finder类。因为我们知道我们在寻找Text widget,所以我们可以使用find.text方法。
  有关Finder类的更多信息,请查看在Widget测试里查找Widget。
   void main() {
  testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
  await tester.pumpWidget(MyWidget(title: 'T', message: 'M'));
  // Create our Finders
  final titleFinder = find.text('T');
  final messageFinder = find.text('M');
  });
  }
 6. 使用Matcher验证我们的Widget是否工作正常。
  最后,我们可以使用flutter_test包提供的Matcher常量来验证title和message Text Widgets是否出现在屏幕。
  Matcher类是test包的核心部分,并且提供了通用的方式去验证给定的值是否符合我们的期望。
  在这个例子里,我们想要我们的Widgets只在屏幕出现一次。因此,我们可以使用findsOneWidget这个Matcher。
   void main() {
  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');
  // Use the `findsOneWidget` matcher provided by flutter_test to verify our
  // Text Widgets appear exactly once in the Widget tree
  expect(titleFinder, findsOneWidget);
  expect(messageFinder, findsOneWidget);
  });
  }
  额外的Matcher:
  在findsOneWidget以外,flutter_test为常见用例提供了额外的Matcher:
  findsNothing
  验证没有Widget被找到。
  findsWidgets
  验证一个或者多个Widget被找到。
  findsNWidgets
  验证指定数量的Widget被找到。
  完整示例:
   import 'package:flutter/material.dart';
  import 'package:flutter_test/flutter_test.dart';
  void main() {
  // Define a test. The TestWidgets function will also provide a WidgetTester
  // for us to work with. The WidgetTester will allow us to build and interact
  // with Widgets in the test environment.
  testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
  // Create the Widget tell the tester to build it
  await tester.pumpWidget(MyWidget(title: 'T', message: 'M'));
  // Create our Finders
  final titleFinder = find.text('T');
  final messageFinder = find.text('M');
  // Use the `findsOneWidget` matcher provided by flutter_test to verify our
  // Text Widgets appear exactly once in the Widget tree
  expect(titleFinder, findsOneWidget);
  expect(messageFinder, findsOneWidget);
  });
  }
  class MyWidget extends StatelessWidget {
  final String title;
  final String message;
  const MyWidget({
  Key key,
  @required this.title,
  @required this.message,
  }) : super(key: key);
  @override
  Widget build(BuildContext context) {
  return MaterialApp(
  title: 'Flutter Demo',
  home: Scaffold(
  appBar: AppBar(
  title: Text(title),
  ),
  body: Center(
  child: Text(message),
  ),
  ),
  );
  }
  }
 
      上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号