Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Isolates don't work with flutter_driver #24703

Open
faustinoribeiro opened this issue Nov 25, 2018 · 17 comments

Comments

Projects
None yet
9 participants
@faustinoribeiro
Copy link

commented Nov 25, 2018

Isolates spawned using "compute" don't execute properly while executed in an integration test which in turn results in incorrect app behavior.
How to reproduce:

  1. add:
import 'package:flutter/foundation.dart';
  1. add function:
String _test(String s) {
  return s;
}
  1. modify _incrementCounter function:
  void _incrementCounter() async {
    final s = await compute(_test, 'hello');
    print(s);

    setState(() {
      _counter++;
    });
  }

The app works properly when executing flutter run, but the integration test fails (flutter drive --target=test_driver/app.dart)

@zoechi

This comment has been minimized.

Copy link
Contributor

commented Nov 26, 2018

Tests use https://pub.dartlang.org/packages/fake_async by default.
Try with https://docs.flutter.io/flutter/flutter_test/WidgetTester/runAsync.html to get real async behavior.

Please consider asking support questions in one of the other channels listed at http://flutter.io/support .

@faustinoribeiro

This comment has been minimized.

Copy link
Author

commented Nov 26, 2018

Thanks for the quick response.
I will go to support first next time instead of wrongly assuming it is a bug.
It would be nice to have a "gotcha" section in the documentation about cases like this one.

Keep the great work, Flutter is the first mobile framework I really enjoy working with. I have with 3 other frameworks in the past and it was rarely smooth as Flutter.

@faustinoribeiro

This comment has been minimized.

Copy link
Author

commented Nov 26, 2018

Getting back to this issue (please let me know if I should move this to support).
The suggested solution using runAsync applies to widgets testing if I understand correctly.
As I mentioned in my initial comment, I am in early stage of integration testing with flutter_driver.
I am probably missing the obvious, but how do I use runAsync (or something else) to get "compute" isolates to execute properly in that context?

@zoechi

This comment has been minimized.

Copy link
Contributor

commented Nov 26, 2018

I don't know if isolates are supposed to work in this setup but I assume so (haven't tried myself).

#21368 shows a code snippet.
It's about wrapping your test code with runAsync.

See also #5728

@faustinoribeiro

This comment has been minimized.

Copy link
Author

commented Nov 27, 2018

I tried to follow the examples you provide by wrapping my app with runAsync with the hope that the integration tests run smoothly, but the app doesn't even launch. I don't have time to run further tests at this time, so I will come back to this in a couple of weeks. Thanks for the help.

@zoechi

This comment has been minimized.

Copy link
Contributor

commented Nov 27, 2018

@Hixie who might know if this is supposed to work?
I tried GitHub search but couldn't find unit tests for compute() that could be used as example.

@jeroentrappers

This comment has been minimized.

Copy link

commented Nov 28, 2018

Could you give an example of how to wrap the app under test in runAsync ?

@faustinoribeiro

This comment has been minimized.

Copy link
Author

commented Nov 29, 2018

This is what I tried:

import 'package:flutter_driver/driver_extension.dart';
import 'package:flutter_test/flutter_test.dart';
import '../lib/my_app.dart';

void main() {
    enableFlutterDriverExtension();

    testWidgets(
        'app test',
        (WidgetTester tester) async {
            final app = MyApp();

            await tester.runAsync(() async {
                await tester.pumpWidget(app);

                await tester.idle();
            });
        }
    );
}
@Hixie

This comment has been minimized.

Copy link
Contributor

commented Nov 30, 2018

Generally driver tests are not expected to use flutter_test. The device side is expected to just be the app, and the driver side is expected to be a command-line app. Using testWidgets with driver tests is going to cause a world of pain.

@faustinoribeiro

This comment has been minimized.

Copy link
Author

commented Dec 1, 2018

Yes, I guessed that much, but just gave a shot.
This is still surprising that driver tests would make isolates fail (assuming I am not doing something really wrong). How is that even possible? I might need (once I get back to working on integration tests) to use some type of flag to not use compute() while testing. This would however mean that I am not doing proper testing.

@ddikman

This comment has been minimized.

Copy link

commented Jan 10, 2019

I am experiencing this as well in my application when attempting to test with the driver. My application loads assets at startup and ends up hanging on a call to AssetBundle.loadString which has a compute call.

The code is open source so I can share that but if it helps I'm happy to reproduce it in an isolated repo.

@jaripekkala

This comment has been minimized.

Copy link

commented Mar 15, 2019

Meanwhile using a workaround that probably doesn't suit for everybody's needs

import 'package:flutter/foundation.dart' as flutter show compute;
import 'package:flutter/foundation.dart' show ComputeCallback;

Future<R> compute<Q, R>(ComputeCallback<Q, R> callback, Q message) async {
  if (isInDebugMode) {
    return callback(message);
  }

  return await flutter.compute(callback, message);
}
@faustinoribeiro

This comment has been minimized.

Copy link
Author

commented Mar 15, 2019

I implemented a similar approach when trying to figure out why my tests were failing. It works, but it's far from perfect though because you're not testing your app as it will be shipped. It's acceptable if you have a couple of simple compute operations, but not so much when you have a lot more of those in critical places (like I currently have in many of my app API calls).

@MariaMelnik

This comment has been minimized.

Copy link

commented Mar 18, 2019

Seems like there isn't any workaround for Isolate with async function because of #25890
I have case with authentication in Isolate (with async function inside) and it turns out I don't have a way to login to my app during integration test.

@The-Redhat

This comment has been minimized.

Copy link

commented Apr 6, 2019

@Hixie Hey, is anything planned to resolve this issue ?

@The-Redhat

This comment has been minimized.

Copy link

commented May 1, 2019

Hey @zoechi I think this issue should be added to the Goals milestone. It prevents me from adding integration tests to my which is really annoying for a production app. Thanks for your help!

@eikob

This comment has been minimized.

Copy link

commented May 29, 2019

This is really annoying and came totally unexpected when using the screenshot package and the Future from DefaultAssetBundle.loadString() just never happened to return. Using .load() instead and manually doing the conversion fixed it, but no way to find out why without looking into the source code.

Also, this can break basically anything, as we have no idea what calls the compute() function under the hood.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.