Flutter运行多个集成测试时应用重装导致登录状态丢失如何解决
问题根因
默认flutter test运行每个独立的_test.dart测试文件时,都会创建全新的应用进程,测试执行完成后直接销毁进程,前一个测试产生的所有运行时数据、本地持久化的登录凭证都会被清空,所以第二个测试启动时是全新的应用环境,自然没有登录状态,卡在登录页。
解决方案
方案1:将关联测试合并到同一测试文件(最推荐,执行效率最高)
同一个测试文件的main函数下的多个testWidgets用例,默认共享同一个应用进程,不会重启应用,你可以把登录、主页这类强关联的测试放在同一个文件中,将app.main()放到setUpAll中全局只执行一次即可。
示例代码:
// integration_test/app_flow_test.dart import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'package:your_app/main.dart' as app; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); // 全局启动一次应用,所有测试用例共享这个应用实例 setUpAll(() async { app.main(); await tester.pumpAndSettle(); }); group('端到端流程测试', () { testWidgets('测试登录流程', (WidgetTester tester) async { final Finder textFieldFinder = find.byType(TextFormField); expect(textFieldFinder, findsNWidgets(2)); final userName = textFieldFinder.first; final password = textFieldFinder.last; await tester.enterText(userName, 'myusername'); await tester.enterText(password, 'mypassword'); expect(find.text('Login'), findsOneWidget); await tester.tap(find.text('Login')); await tester.pumpAndSettle(); expect(find.byKey(Key('createTicketBtn')), findsOneWidget); }); testWidgets('测试主页显示', (WidgetTester tester) async { // 直接复用前面的登录状态,不需要重新登录 expect(find.byKey(Key('createTicketBtn')), findsOneWidget); }); }); }
这个方案适合业务流程关联度高的测试,执行速度最快,不会有重复的登录操作。
方案2:封装公共登录方法,每个测试文件前置执行
如果你需要保留多测试文件的拆分结构,可以把登录逻辑封装成公共工具函数,每个需要登录态的测试文件执行测试前,先调用登录函数完成登录,就算应用重启也能正常拿到登录态。
步骤:
- 抽离公共登录工具:
// integration_test/utils/test_helper.dart import 'package:flutter_test/flutter_test.dart'; Future<void> login(WidgetTester tester) async { final Finder textFieldFinder = find.byType(TextFormField); expect(textFieldFinder, findsNWidgets(2)); final userName = textFieldFinder.first; final password = textFieldFinder.last; await tester.enterText(userName, 'myusername'); await tester.enterText(password, 'mypassword'); await tester.tap(find.text('Login')); await tester.pumpAndSettle(); }
- 改造每个需要登录的测试文件,以homepage_test.dart为例:
import 'utils/test_helper.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); group('end to end tests', () { testWidgets('test homepage', (tester) async { app.main(); await tester.pumpAndSettle(); // 前置执行登录 await login(tester); expect(find.byKey(Key('createTicketBtn')), findsOneWidget); }); }); }
这个方案的优势是测试文件拆分清晰,耦合度低,缺点是每个测试文件都会重复执行一次登录流程,执行时间会更长。
内容的提问来源于stack exchange,提问作者Son Tieu
相关产品推荐
相关产品推荐

