单元测试和Widget测试对测试单独的类、方法或者Widget很有用。然而,他们通常不能测试单独部分如何作为一个整体一起工作或者查看应用程序在一个真实设备上运行时的性能。集成测试就是用来解决该问题的。
集成测试成对使用:首先,将已检测的应用程序部署到真实设备或模拟器,然后从单独的测试套件“驱动”应用程序,检查以确保一切正常。
要创建此测试对,我们可以使用flutter_driver包。 它提供了创建检测程序并从测试套件中驱动这些程序的工具。
在本文中,我们将学习如何测试计数器应用程序。 它将演示如何设置集成测试,如何验证应用程序显示的特定文本,如何点击特定的Widgets以及如何运行集成测试。
步骤:
- 创建一个要测试的应用
- 添加
flutter_driver
依赖项 - 创建测试文件
- 检查应用程序
- 编写集成测试代码
- 运行集成测试
1. 创建一个要测试的应用
首先,我们将要创建一个用来测试的应用程序!在这个例子里,我们将会测试通过flutter create
命令创建的计数器应用程序,这个应用程序允许用户点击按钮增加计数。
此外,我们将会提供ValueKey
给Text
和 FloatingActionButton
Widgets。这将允许我们在测试套件里识别这些特定的Widgets并与之互动。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Counter App',
home: MyHomePage(title: 'Counter App Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
// Provide a Key to this specific Text Widget. This allows us
// to identify this specific Widget from inside our test suite and
// read the text.
key: Key('counter'),
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
// Provide a Key to this the button. This allows us to find this
// specific button and tap it inside the test suite.
key: Key('increment'),
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
2. 添加flutter_driver
依赖项
下一步,我们需要flutter_driver
包去写集成测试,我们要在pubspec.yaml
文件的dev_dependencies
下面添加flutter_driver
依赖。
为了使用实际的测试函数和断言,我们也要添加test
依赖。
dev_dependencies:
flutter_driver:
sdk: flutter
test: any
3. 创建测试文件
和单元测试、Widget测试不一样,集成测试组件没有和被测试的应用程序运行在同一进程。所以,我们需要在相同的目录里创建2个文件。按照惯例,这个目录的名字叫 test_driver
。
-
第一个文件包含应用程序的“已检测”版本。这个检测允许我们“驱动”应用程序并且记录测试组件对它的性能分析。这个文件可以起任何合理的名字。在这个例子里,创建的文件名字叫
test_driver/app.dart
。 -
第二个文件包含测试组件,它用来驱动应用程序并验证应用程序是否按照预期的正常运行。这个测试组件也能记录性能分析。这个测试文件的名字必须和包含被检测应用程序的名字对应,并在文件名字后面添加
_test
作为结尾。所以创建的第二个文件的名字叫test_driver/app_test.dart
。
现在的目录结构是这样的:
counter_app/
lib/
main.dart
test_driver/
app.dart
app_test.dart
4. 检查应用程序
现在,我们可以检测这个应用程序了,这包括以下2步:
- 启用 flutter driver 扩展
- 运行应用程序
我们将会把下面的代码写到test_driver/app.dart
文件里。
import 'package:flutter_driver/driver_extension.dart';
import 'package:counter_app/main.dart' as app;
void main() {
// This line enables the extension
enableFlutterDriverExtension();
// Call the `main()` function of your app or call `runApp` with any widget you
// are interested in testing.
app.main();
}
5. 编写集成测试代码
现在我们有一个可检测的应用程序了,我们可以对它写测试代码了!这将包括以下4步:
- 创建
SeralizableFinders
去查找特定的Widget。 - 在我们的测试运行在
setUpAll
函数之前先连接到我们的应用程序。 - 对重要场景进行测试
- 在我们的测试完成以后,
teardownAll
函数里断开和应用程序的连接。
// Imports the Flutter Driver API
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';
void main() {
group('Counter App', () {
// First, define the Finders. We can use these to locate Widgets from the
// test suite. Note: the Strings provided to the `byValueKey` method must
// be the same as the Strings we used for the Keys in step 1.
final counterTextFinder = find.byValueKey('counter');
final buttonFinder = find.byValueKey('increment');
FlutterDriver driver;
// Connect to the Flutter driver before running any tests
setUpAll(() async {
driver = await FlutterDriver.connect();
});
// Close the connection to the driver after the tests have completed
tearDownAll(() async {
if (driver != null) {
driver.close();
}
});
test('starts at 0', () async {
// Use the `driver.getText` method to verify the counter starts at 0.
expect(await driver.getText(counterTextFinder), "0");
});
test('increments the counter', () async {
// First, tap on the button
await driver.tap(buttonFinder);
// Then, verify the counter text has been incremented by 1
expect(await driver.getText(counterTextFinder), "1");
});
});
}
6. 运行集成测试
现在我们有了一个可检测的应用程序和一个测试组件,我们可以运行我们的测试了!首先确定已经启动了Android模拟器或iOS模拟器,或者将你的电脑连接到一个真实的iOS / Android 设备。
然后,在你项目的根目录运行下面的命令:
flutter drive --target=test_driver/app.dart
该命令做了以下事情:
- 构建
--target
指定的应用程序并且将它安装到模拟器或者真实设备。 - 载入应用程序。
- 运行
test_driver/
文件夹下面的app_test.dart
文件。