翻译首页bash
在单元测试的介绍里,咱们学习到了如何使用test
包测试Dart类,为了测试Widget类,咱们须要一些由flutter test
包提供的额外工具,这些工具随Flutter SDK发布。app
这个flutter_test
包提供了如下用于测试Widget的工具:less
testWidgets
函数。这个函数将自动对每一个测试用例建立一个WidgetTester
,并用于替代普通的test
函数。若是上面的内容听不懂的话,不要紧,让咱们经过一些例子来将上面的碎片信息串联到一块儿。async
步骤:ide
flutter_test
依赖。WidgetTester
build一个WidgetFinder
搜索咱们的Widget。Matcher
验证咱们的Widget是否工做正常。flutter_test
依赖。在咱们开始写测试以前,咱们须要在pubspec.yaml
文件的dev_dependencies
行下面添加flutter_test
包。若是你经过命令行或者编译器建立的Flutter项目,那么该依赖已经添加好了。函数
dev_dependencies:
flutter_test:
sdk: flutter
复制代码
下一步,咱们须要建立一个能让咱们测试的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),
),
),
);
}
}
复制代码
如今咱们有了一个能够用来测试的Widget,咱们能够编写咱们第一个测试用例了!咱们将会使用flutter_test
包提供的testWidgets
函数完成一个测试用例。这个testWidgets
函数将会容许咱们定义一个Widget测试用例并建立一个WidgetTester
给咱们使用。post
咱们的测试将会验证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!
});
}
复制代码
WidgetTester
build一个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生命周期更细粒度的控制,这在测试的时候特别有用。
Finder
搜索咱们的Widget。如今咱们已经在测试环境构建了咱们的Widget,咱们想要经过使用Finder
在Widget树里搜索咱们的title
和message
Widget。这将容许咱们验证是否正确显示了那些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');
});
}
复制代码
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
:
验证没有Widget被找到。
验证一个或者多个Widget被找到。
验证指定数量的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),
),
),
);
}
}
复制代码