Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter: flutter_driver error message and app screen stays black while testing

I'm trying to set up some integration tests for my Flutter app, but I'm running into some troubles. While running my app in debug mode works fine, the app stays black when I'm trying to run it with flutter_driver.
This is the code of my flutter_driver/app.dart code:

import 'package:flutter_driver/driver_extension.dart';
import 'package:[MY_APP_NAME]/main.dart' as app;

void main() {
  // This line enables the extension.
  enableFlutterDriverExtension();

  // Call the `main()` function of the app, or call `runApp` with
  // any widget you are interested in testing.
  app.main();
}  

This is the code of my flutter_driver/app_test.dart file:


// Imports the Flutter Driver API.
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';

void main() {
  group('My first test group', () {
    // First, define the Finders and use them 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 welcomeQuestion = find.byValueKey('welcomeQuestion');
    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('check flutter driver health', () async {
      Health health = await driver.checkHealth();
      print(health.status);
    });

    test('Check welcomeQuestion', () async {
      // Use the `driver.getText` method to verify the counter starts at 0.
      expect(await driver.getText(welcomeQuestion), "Are you feeling good today?");
    });
  });
}

This is the error message I'm getting while running flutter drive --target=test_driver/app.dart to perform the test:

00:00 +1 -1: [APP-NAME] Check welcomeQuestion [E]
  DriverError: Error in Flutter application: Uncaught extension error while executing get_text: 'package:flutter_driver/src/extension/extension.dart': Failed assertion: line 189 pos 14: 'WidgetsBinding.instance.isRootWidgetAttached || !command.require
sRootWidgetAttached': No root widget is attached; have you remembered to call runApp()?
  #0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:40:39)
  #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5)
  #2      FlutterDriverExtension.call (package:flutter_driver/src/extension/extension.dart:189:14)
  <asynchronous suspension>
  #3      BindingBase.registerServiceExtension.<anonymous closure> (package:flutter/src/foundation/binding.dart:512:32)
  <asynchronous suspension>
  #4      _runExtension (dart:developer-patch/developer.dart:84:23)

  Original error: null
  Original stack trace:
  null

  package:flutter_driver/src/driver/driver.dart 433:7   FlutterDriver._sendCommand
  ===== asynchronous gap ===========================
  dart:async/future_impl.dart 22:43                     _Completer.completeError
  dart:async-patch/async_patch.dart 40:18               _AsyncAwaitCompleter.completeError
  package:flutter_driver/src/driver/driver.dart         FlutterDriver._sendCommand
  ===== asynchronous gap ===========================
  dart:async/zone.dart 1053:19                          _CustomZone.registerUnaryCallback
  dart:async-patch/async_patch.dart 77:23               _asyncThenWrapperHelper
  package:flutter_driver/src/driver/driver.dart         FlutterDriver._sendCommand
  package:flutter_driver/src/driver/driver.dart 677:41  FlutterDriver.getText
  ===== asynchronous gap ===========================
  dart:async/zone.dart 1053:19                          _CustomZone.registerUnaryCallback
  dart:async-patch/async_patch.dart 77:23               _asyncThenWrapperHelper
  package:test_api/src/backend/declarer.dart            Declarer.test.<fn>.<fn>.<fn>
  package:test_api/src/backend/invoker.dart 250:15      Invoker.waitForOutstandingCallbacks.<fn>
  ===== asynchronous gap ===========================
  dart:async/zone.dart 1045:19                          _CustomZone.registerCallback
  dart:async/zone.dart 962:22                           _CustomZone.bindCallbackGuarded
  dart:async/timer.dart 52:45                           new Timer
  dart:async/timer.dart 87:9                            Timer.run
  dart:async/future.dart 174:11                         new Future
  package:test_api/src/backend/invoker.dart 399:21      Invoker._onRun.<fn>.<fn>.<fn>

00:00 +1 -1: [APP-NAME] (tearDownAll)
00:00 +1 -1: Some tests failed.

Unhandled exception:
Dummy exception to set exit code.
#0      _rootHandleUncaughtError.<anonymous closure> (dart:async/zone.dart:1112:29)
#1      _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#2      _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#3      _Timer._runTimers (dart:isolate-patch/timer_impl.dart:391:30)
#4      _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:416:5)
#5      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:172:12)
Stopping application instance.
Driver tests failed: 255

What's important to mention is that the app screen stays black, so it seems like the driver can't attach to the original app and run it correctly. Does anybody have an idea how to fix that?

Update

running flutter --version:

Flutter 1.7.8+hotfix.4 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 20e59316b8 (8 weeks ago) • 2019-07-18 20:04:33 -0700
Engine • revision fee001c93f
Tools • Dart 2.4.0

And here's the blackened version of my main.dart:

import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_statusbarcolor/flutter_statusbarcolor.dart';
[... + many additional imports from other private packages]

void main() async {
  //load the json config globally
  await Config().loadConfig();
  await SharedPrefsService().init();
  await RealmService().init();
  SessionHistoryService().init();
  final Router router = Router();

  [... a lot of router.define() functions....]

  //set statusbar color
  FlutterStatusbarcolor.setStatusBarWhiteForeground(true);

  SystemChrome.setPreferredOrientations(
      [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]).then((_) {
    runApp(new MaterialApp(
        localizationsDelegates: [
          const AppLocalizationsDelegate(),
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate
        ],
        supportedLocales: [
          const Locale('en', 'US'), // English
          const Locale('de', 'DE'), // German
          // ... other locales the app supports
        ],
        localeResolutionCallback:
            (Locale locale, Iterable<Locale> supportedLocales) {
          for (Locale supportedLocale in supportedLocales) {
            if (supportedLocale.languageCode == locale.languageCode ||
                supportedLocale.countryCode == locale.countryCode) {
              //For Localization Testing:
              // return const Locale('de', 'DE');
              return supportedLocale;
            }
          }

          return supportedLocales.first;
        },
        title: 'MY APP NAME',
        home: SharedPrefsService().isFirstLaunch()
            ? FirstLaunchScreen(true)
            : MainMenuPage(),
        onGenerateRoute: router.generator));
  });
}
like image 813
patreu22 Avatar asked Sep 09 '19 21:09

patreu22


2 Answers

In my case, this was enough:

// connects with the current running application
driver = await FlutterDriver.connect();

// Wait for the first frame to be rasterized during the app launch.
await driver.waitUntilFirstFrameRasterized();

Well, not sure why it was downvoted, here is the gh issue about that: https://github.com/flutter/flutter/issues/41029

Update: It seems that we have a new library that will replace FlutterDriver, and you won't need to care about these issues anymore: https://medium.com/flutter/updates-on-flutter-testing-f54aa9f74c7e :)

like image 89
Guilherme V. Avatar answered Oct 16 '22 10:10

Guilherme V.


I had same issue and it seems that test starts executing before .init() methods from main() in main.dart are finished. Try setting pause at the beginning of your test and see if it works, in my case did. We are looking for a solution how to wait until whole main() is executed and than start the test execution, without using hard coded pause. Hope it helps

test('Check welcomeQuestion', () async {

  await sleep(Duration(seconds: 5));

  // Use the `driver.getText` method to verify the counter starts at 0.
  expect(await driver.getText(welcomeQuestion), "Are you feeling good today?");
});
like image 5
Nemanja Knežević Avatar answered Oct 16 '22 10:10

Nemanja Knežević