Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DriverError: Failed to fulfill Tap due to remote error flutter

I have some customized TextFiels and they are for entering a pin and I called them PinInputField. When I'm running integration test using flutter drive, all of the input fields will receive given text, except last one and stops running test. Here is the code: P.s: the I'm using HookWidget

    final focusNodes = List.generate(6, (_) => new FocusNode());
    final values = List.generate(6, (_) => useState<String>(''));

Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    for (int i = 0; i < values.length; i++)
                      PinInputField(
                        key: ValueKey('$i'),
                        width: MediaQuery.of(context).size.width / 11.71,
                        height: 80,
                        fontSize: 50,
                        marginRight: 16,
                        input: values[i],
                        focusNode: focusNodes[i],
                        nextFocusNode: i == 5 ? null : focusNodes[i + 1],
                      )
                  ],
                )

and here is the tests:

    test('test main card settings items', () async {
      final cardSettingsItem = find.byValueKey('settings.cardSettings');
       final mainSettingsList = find.byValueKey('mainSettingsList');
      final profileButton = find.byValueKey('Profile');
      final changePinButton = find.byValueKey('Cambiar pin');
      final changePinInputField0 = find.byValueKey('0');
      final changePinInputField1 = find.byValueKey('1');
      final changePinInputField2 = find.byValueKey('2');
      final changePinInputField3 = find.byValueKey('3');
      final changePinInputField4 = find.byValueKey('4');
      final changePinInputField5 = find.byValueKey('5');
      final changePinScreenButton = find.byValueKey('changePinScreenButton');
      sleep(Duration(seconds: 3));
      await driver.tap(profileButton);
      sleep(Duration(seconds: 2));
      await driver.scrollIntoView(mainSettingsList);
      sleep(Duration(seconds: 3));
      await driver.tap(cardSettingsItem);
      sleep(Duration(seconds: 3));
      await driver.tap(changePinButton);
      sleep(Duration(seconds: 4));
      await driver.tap(changePinInputField0);
      sleep(Duration(seconds: 2));
      await driver.enterText("0");
      sleep(Duration(seconds: 1));
      await driver.tap(changePinInputField1);
      sleep(Duration(seconds: 2));
      await driver.enterText("1");
      sleep(Duration(seconds: 1));
      await driver.tap(changePinInputField2);
      sleep(Duration(seconds: 2));
      await driver.enterText("2");
      sleep(Duration(seconds: 1));
      await driver.tap(changePinInputField3);
      sleep(Duration(seconds: 2));
      await driver.enterText("3");
      sleep(Duration(seconds: 1));
      await driver.tap(changePinInputField4);
      sleep(Duration(seconds: 2));
      await driver.enterText("4");
      sleep(Duration(seconds: 4));
      await driver.tap(changePinInputField5);
      sleep(Duration(seconds: 1));
      await driver.enterText("5");
      sleep(Duration(seconds: 5));
      await driver.tap(changePinScreenButton);
      sleep(Duration(seconds: 4));
    });

and here is the log:

 DriverError: Failed to fulfill Tap due to remote error
  Original error: Bad state: The client closed with pending request "ext.flutter.driver".
  Original stack trace:
  #0      new Client.withoutJson.<anonymous closure> (package:json_rpc_2/src/client.dart:70:24)
  #1      StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
  #2      StackZoneSpecification._registerCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:119:48)
  #3      _rootRun (dart:async/zone.dart:1120:38)
  #4      _CustomZone.run (dart:async/zone.dart:1021:19)
  #5      _FutureListener.handleWhenComplete (dart:async/future_impl.dart:150:18)
  #6      Future._propagateToListeners.handleWhenCompleteCallback (dart:async/future_impl.dart:609:39)
  #7      Future._propagateToListeners (dart:async/future_impl.dart:665:37)
  #8      Future._propagateToListeners (dart:async/future_impl.dart:566:9)
  #9      Future._completeWithValue (dart:async/future_impl.dart:483:5)
  #10     Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:513:7)
  #11     StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart:209:15)
  #12     StackZoneSpecification._registerCallback.<anonymous closure> (package:stack_trace/src/stack_zone_specification.dart:119:48)
  #13     _rootRun (dart:async/zone.dart:1124:13)
  #14     _CustomZone.run (dart:async/zone.dart:1021:19)
  #15     _CustomZone.runGuarded (dart:async/zone.dart:923:7)
  #16     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:963:23)
  #17     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
  #18     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
  #19     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:391:30)
  #20     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5)
  #21     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:172:12)

like image 210
Mo Meshkani Avatar asked Jul 12 '19 19:07

Mo Meshkani


2 Answers

This issue mostly occurs when the test times out before it is actually completed. The default timeout used for a test to run is 30 seconds, here your sleep durations add up to more than 30 seconds, hence the connection closed with pending requests.

I don't understand why to sleep for a certain duration after each action, may be you can reduce/remove sleep. If sleeps are mandatory for your case try to pass the appropriate timeout to the test.

Example:

test(
  'test main card settings items',
  () async {
    final cardSettingsItem = find.byValueKey('settings.cardSettings');
    final mainSettingsList = find.byValueKey('mainSettingsList');
    final profileButton = find.byValueKey('Profile');
    final changePinButton = find.byValueKey('Cambiar pin');
    final changePinInputField0 = find.byValueKey('0');
    final changePinInputField1 = find.byValueKey('1');
    final changePinInputField2 = find.byValueKey('2');
    final changePinInputField3 = find.byValueKey('3');
    final changePinInputField4 = find.byValueKey('4');
    final changePinInputField5 = find.byValueKey('5');
    final changePinScreenButton = find.byValueKey('changePinScreenButton');
    sleep(Duration(seconds: 3));
    await driver.tap(profileButton);
    sleep(Duration(seconds: 2));
    await driver.scrollIntoView(mainSettingsList);
    sleep(Duration(seconds: 3));
    await driver.tap(cardSettingsItem);
    sleep(Duration(seconds: 3));
    await driver.tap(changePinButton);
    sleep(Duration(seconds: 4));
    await driver.tap(changePinInputField0);
    sleep(Duration(seconds: 2));
    await driver.enterText("0");
    sleep(Duration(seconds: 1));
    await driver.tap(changePinInputField1);
    sleep(Duration(seconds: 2));
    await driver.enterText("1");
    sleep(Duration(seconds: 1));
    await driver.tap(changePinInputField2);
    sleep(Duration(seconds: 2));
    await driver.enterText("2");
    sleep(Duration(seconds: 1));
    await driver.tap(changePinInputField3);
    sleep(Duration(seconds: 2));
    await driver.enterText("3");
    sleep(Duration(seconds: 1));
    await driver.tap(changePinInputField4);
    sleep(Duration(seconds: 2));
    await driver.enterText("4");
    sleep(Duration(seconds: 4));
    await driver.tap(changePinInputField5);
    sleep(Duration(seconds: 1));
    await driver.enterText("5");
    sleep(Duration(seconds: 5));
    await driver.tap(changePinScreenButton);
    sleep(Duration(seconds: 4));
  },
  timeout: Timeout(
    Duration(minutes: 2),
  ),
);

Hope that helps!

like image 130
Hemanth Raj Avatar answered Oct 09 '22 03:10

Hemanth Raj


I've struggled with the default 30 sec timeout as well. And it only was a problem when the Flutter Driver tests were run on remote CI/CD. Locally test ran great. I did two things that seem to work for remote CI/CD:

  1. Specified the timeout @Hemanth prescribed above. Thanks @Hemanth 🙏🏽!
  2. Added clearTimeline()at the start of each test.
   test('Home page should properly work', () async {
      await driver.clearTimeline();
      await HomePage(driver).appears()
          .then((a) => a.exploreHomePage());
    },
      timeout: Timeout(
        Duration(minutes: 2),
      ),
    );

Note: Implementing timeout & clearTimeline() allowed the longer running tests to complete. But I would recommend adding to each test regardless of size. I too initially tried sleeps, and ended up removing them all after using timeout & clearTimeline().

Hope this helps.

like image 39
Ruel Abadam Avatar answered Oct 09 '22 03:10

Ruel Abadam