软件测试是发现程序错误衡量软件质量必不少的一个环节,在企业中会有专门的软件测试工程师来负责软件测试和质量的障。作为一名Flutter开发人员了解Flutter测试的方法和手段有助于减少程序的Bug开发出更高质量的应用。那么Flutter是如何进行测试的呢?
在本篇教程中将下大家分享Flutter的主流测试方式以和案例,在Flutter中主要有以下三种类型的测试:
- 单元测试
- Widget测试
- 集成测试
单元测试
测试单一功能、方法或类,单元测试通常不会读取/写入磁盘、渲染到屏幕,也不会从运行测试的进程外部接收用户操作。单元测试的目标是在各种条件下验证逻辑单元的正确性。
如果所测试对象有外部依赖,那么外部依赖要能够被模拟出来,否则是无法进行单元测试。
所需依赖
dev_dependencies:
flutter_test:
sdk: flutter
案例
///单元测试
void main() {
///测试HiCache的存储和读取
test('测试HiCache', () async {
//fix ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
TestWidgetsFlutterBinding.ensureInitialized();
//fix MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences)
SharedPreferences.setMockInitialValues({});
await HiCache.preInit();
var key = "testHiCache", value = "Hello.";
HiCache.getInstance().setString(key, value);
expect(HiCache.getInstance().get(key), value);
});
}
在这个案例中我们对项目中的缓存模块HiCache
进行了单元测试,主要用来测试它的存储和读取功能是否正常。
Widget测试
Widget 测试可以用于测试单独的 class, function, 和 Widget。
Widget测试具有一定的局限性,所测试的Widget必须要能够独立运行,或者所以依赖条件能够被模拟出来。
所需依赖
dev_dependencies:
flutter_test:
sdk: flutter
按照上述要求整个APP有哪些Widget能进行Widget测试?
案例
...
class UnKnownPage extends StatefulWidget {
@override
_UnKnownPageState createState() => _UnKnownPageState();
}
class _UnKnownPageState extends State<UnKnownPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: Text('404'),
),
);
}
}
...
///Widget测试
void main() {
testWidgets('测试UnKnownPage', (WidgetTester tester) async {
//UnKnownPage虽然没有Flutter框架之外的依赖,但因为用到了Scaffold所以需要用MaterialApp包裹
await tester.pumpWidget(MaterialApp(home: UnKnownPage()));
expect(find.text('404'), findsOneWidget);
});
}
在这个案例中我们对项目中的UnKnownPage
Widget进行了测试,主要用来测试该页面中是否存在一个内容为404的Text。
集成测试
集成测试主要是测试各部分一起运行或者测试一个应用在真实设备上运行的表现的时候就要用到集成测试。
所需依赖
dev_dependencies:
flutter_test:
sdk: flutter
integration_test:
sdk: flutter
主要步骤
- 添加测试驱动
- 编写测试用例
- 运行测试用例
- 查看结果
添加测试驱动
添加测试驱动的目的是为了方便通过flutter drive命令运行集成测试:
在项目根目录创建test_driver
目录并添加文件integration_test.dart
:
import 'package:integration_test/integration_test_driver.dart';
Future<void> main() => integrationDriver();
编写测试用例
在项目根目录创建integration_test
目录并添加文件app_test.dart
。接下来我们就来测试下登录模块的跳转功能:
import 'package:flutter/material.dart';
import 'package:flutter_bili_app/main.dart' as app;
import 'package:flutter_bili_app/navigator/hi_navigator.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('Test login jump', (WidgetTester tester) async {
//构建应用
app.main();
//捕获一帧
await tester.pumpAndSettle();
//通过key来查找注册按钮
var registrationBtn = find.byKey(Key('registration'));
//触发按钮的点击事件
await tester.tap(registrationBtn);
//捕获一帧
await tester.pumpAndSettle();
await Future.delayed(Duration(seconds: 3));
//判断是否跳转到了注册页
expect(HiNavigator.getInstance().getCurrent().routeStatus,
RouteStatus.registration);
//获取返回按钮,并触发返回上一页
var backBtn = find.byType(BackButton);
await tester.tap(backBtn);
await tester.pumpAndSettle();
await Future.delayed(Duration(seconds: 3));
//判断是返回到登录页
expect(
HiNavigator.getInstance().getCurrent().routeStatus, RouteStatus.login);
});
}
在这个案例中我们通过获取当前页APP页面上的帧,然后基于捕获的这一帧查找到对应控件,并模拟了点击。为了能够判断登录模块的跳转逻辑是否正常在上述代码中我们通过HiNavigator
获取到当前的页面路由状态来进行判断。
运行测试用例
运行集成测试的测试用例可以通过以下命令来完成:
flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart
- –driver:用于指定测试驱动的路径;
- –targe:用于指定测试用例的路径;
下面实现运行效果图:
如果APP之前已经登录过那么需要将其先卸载来清除登录缓存,以便APP能够在测试的时候正常进入到登录页。