Flutter集成测试中如何等待Finder可见才能执行下一次代码?

Pat*_*kal 9 unit-testing dart flutter flutter-integration-test

信息:
我创建了一个示例 Flutter 单元测试来测试登录屏幕,其中我将电子邮件和密码作为输入字段以及登录按钮。

要求:
需要测试错误情况,为此,我按照以下步骤编写了代码。

  1. 打开main.dart
  2. 填写电子邮件和密码字段
  3. onTap 事件在登录按钮上完成。在这里,API 将被调用,加载程序将显示在屏幕上,直到 API 获得成功或失败响应。
  4. 需要检查是否显示失败对话框和消息。

问题/查询:
现在,当 API 调用时,我想等待加载程序可见,直到加载程序消失。因此,到目前为止,我只是手动延迟执行下一个代码,但我想让它动态化。那么,让我知道我们如何根据可见的加载器进行动态延迟?

代码:

void main() {
  group('App Test', () {
    IntegrationTestWidgetsFlutterBinding.ensureInitialized();

    testWidgets('Login Fail Test', (WidgetTester tester) async {
      await app.main();
      await tester.pumpAndSettle();

      await tester.pump(new Duration(seconds: 2));

      final emailField = find.byType(TextFormField).first;
      final passwordField = find.byType(TextFormField).last;
      final loginButton = find.byType(RaisedButton).first;

      await tester.enterText(emailField, 'Test');
      await tester.pumpAndSettle();
      await tester.pump(new Duration(seconds: 1));

      await tester.enterText(passwordField, 'Test123');
      await tester.pumpAndSettle();
      await tester.pump(new Duration(seconds: 1));

      await tester.tap(loginButton);
      await tester.pumpAndSettle();
      await tester.pump(new Duration(seconds: 3));

     
      final dialog = find.byType(AlertDialog).first;
      await tester.element(dialog);
      await tester.pumpAndSettle();
      await tester.pump(new Duration(seconds: 1));

      final dialogButton = find.byType(FlatButton).first;
      await tester.tap(dialogButton);
      await tester.pumpAndSettle();
      await tester.pump(new Duration(seconds: 2));
    });
}
Run Code Online (Sandbox Code Playgroud)

bac*_*113 5

我有一个名为utils.dart此类功能的文件。在这种情况下,我使用以下函数,该函数基本上会轮询直到查找器有效

// utils.dart

Future<void> pumpUntilFound(
  WidgetTester tester,
  Finder finder, {
  Duration timeout = const Duration(seconds: 10),
}) async {
  bool timerDone = false;
  final timer = Timer(timeout, () => timerDone = true);
  while (timerDone != true) {
    await tester.pump();

    final found = tester.any(finder);
    if (found) {
      timerDone = true;
    }
  }
  timer.cancel();
}
Run Code Online (Sandbox Code Playgroud)

您还可以让它在超时时抛出异常,但是错误消息没有帮助,所以我通常会用一个expect

它看起来像

// my_test.dart

final fab = find.byKey(const ValueKey('fab'));
await pumpUntilFound(widgetTester, fab);
expect(fab, findsOneWidget);
Run Code Online (Sandbox Code Playgroud)

  • 您的问题是等待“Finder 可见”,没有办法让 Finder 在不渲染新帧的情况下变得可见(这就是 Pump() 所做的)。我同意监视您的特定网络请求以等待其完成会更有效,但上面的答案是您问题的解决方案 (2认同)

Mai*_*zen -2

尝试像这样包裹:

testWidgets('test',
    (WidgetTester tester) async {
    await tester.runAsync(() async {

      // test code here

    });
 });
Run Code Online (Sandbox Code Playgroud)

如果您使用:

await tester.pumpAndSettle();
Run Code Online (Sandbox Code Playgroud)

进而:

  final widget = find.byKey(Key('whatever'));
Run Code Online (Sandbox Code Playgroud)

它会动态地发现