Skip to content

flutter drive options -d and --browser-name have confusing behavior #67090

Open

Description

@yjbanov

Currently if you run flutter drive -d chrome (and likely -d edge) but without --browser-name we will run the web test and succeed. However, there are two issues with this:

  • We already have a way to specify the browser when running driver tests --browser-name=BROWSER, so why is -d chrome allowed?
  • When running with -d chrome you will see the browser opened once, closed immediately, then opened again. It's ultimately harmless but confusing. (hypothesis: the first browser is opened by Flutter tool's existing logic for launching browsers for flutter run, and the second browser is launched by WebDriver).

It is also possible to run with --browser-name but without -d, but that will attempt to run an Android test, which may produce false positives (you think your web test succeeded but you actually ran an Android test).

Possible solution: only use the -d BROWSER and make it consistent with flutter run. Bypass Flutter tool's browser launching logic and delegate to WebDriver.

Activity

  1. added
    toolAffects the "flutter" command-line tool. See also t: labels.
    t: flutter driver"flutter driver", flutter_drive, or a driver test
    platform-webWeb applications specifically
    P3Issues that are less important to the Flutter project
    on Oct 1, 2020
  2. changed the title [-]`flutter drive` should not accept `-d BROWSER`[/-] [+]`flutter drive` options `-d` and `--browser-name` have confusing behavior[/+] on Oct 1, 2020
  3. self-assigned this
    on Oct 1, 2020
  4. zpsean commented on Mar 25, 2022

    @zpsean

    @yjbanov @darshankawar this key point of the issue #100447 to address is that expecting the Chrome (as device) is not to be opened. In this post, it is stated as harmless but confusing, but I think, as stated in #100447 post, is harmful, as we can Not reply on the real test results with the Chrome existence (device one).


    Both Chrome instances have test executed. However, the Chrome is launched not via chromedriver has major negative impact to test:

    For js, css loading, increase the networking pressure as need to load two copies
    For some write, delete scenarios, the test will result in unexpected results (as two Chromes both will try to execute delete action)

  5. zpsean commented on Mar 25, 2022

    @zpsean

    We can have more discussion how two use option -d and --browser-name, maybe to prevent the Chrome (as device) to be opened have high priority as its impact (negative) to test .

  6. garrettApproachableGeek commented on Apr 22, 2022

    @garrettApproachableGeek

    Under the current running of integration tests on chrome the tests always run twice and there is no way to only run once. This can cause tests that should pass to fail as shown on #102250

  7. ariCETester commented on Jun 22, 2022

    @ariCETester

    I am running into this as well. Integration tests interact with a dynamo DB on AWS. The duplicate writing and deleting is a real problem.

  8. removed
    P3Issues that are less important to the Flutter project
    on Oct 14, 2022
  9. 8 remaining items

  10. ZacharyBohn commented on Apr 20, 2023

    @ZacharyBohn

    This is causing duplicate writes to firestore in my integration tests.

    The way that our company has gotten around this is to just add the Android platform and run the tests from there. It's more work, but at least the tests are able to run successfully.

  11. Justus-M commented on Jun 30, 2023

    @Justus-M

    This is causing duplicate writes to firestore in my integration tests.

    The way that our company has gotten around this is to just add the Android platform and run the tests from there. It's more work, but at least the tests are able to run successfully.

    Thanks for sharing this.

    We actually now have Mac and windows versions of the app, but are still concerned about web specific behavior and libraries

  12. Justus-M commented on Jul 25, 2023

    @Justus-M

    This is causing duplicate writes to firestore in my integration tests.

    The way that our company has gotten around this is to just add the Android platform and run the tests from there. It's more work, but at least the tests are able to run successfully.

    Thanks for sharing this.

    We actually now have Mac and windows versions of the app, but are still concerned about web specific behavior and libraries

    As kindly suggested by @ZacharyBohn, I started relying on desktop tests. Unfortunately, due to some libraries (ex. riverpod) behaving differently on web, it resulted in a pretty broken app being deployed, despite successful desktop integration tests.

    It's clear that running tests on other platforms does not ensure that the web app will function.

    This issue seems to be a huge bottleneck in creating production grade web apps with flutterfire.

    Are there any updates on this?

  13. Justus-M commented on Sep 15, 2023

    @Justus-M

    This is causing duplicate writes to firestore in my integration tests.

    I finally came up with a workaround to "pause" the duplicate test, and then exit the duplicate when the original test completes:

    Before starting your tests, create a firestore document with a specific id (ex. 'flag')
     
    In each test, check if the document exists.
    a. The document exists: Delete it and continue the test. After the test, add the document back.
    b. the document doesn't exist: Stream the collection and wait for the document to be added. When it is added, exit the function (do not continue the test).
    

    Basically this makes sure only the first test actually runs through, and the second test skips the actual testing and completes successfully once the first test completes (it is waiting for the first test to add the document back.

    It's a bit messy, but it works, and web testing is SUPER important because many packages behave differently on web and relying on other platforms for testing will likely result in shipping buggy web apps (I learned this the hard way after only testing on mac and windows for the past few months).

    Here is the code I use to wrap each test:

    Future<void> webTestWrapper(Future<void> Function() theTest) async {
      await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
    
      if (kIsWeb) {
       //get document 'flag' from collection 'flag'
        var doc = await FirestoreService.get().getDocument('flag', 'flag');
        if (doc == null) {
        //the doc was already deleted, so this is the duplicate test
          var waiting = true;
          //stream collection 'flag', stop waiting when the document is back
          stream = await FirestoreService.get().stream('flag', (docs) {
            if (doc?['testflag'] == true) {
              waiting = false;
            }
          });
          while (waiting) {
            await Future.delayed(const Duration(milliseconds: 500));
          }
          await stream?.cancel();
          //original test completed, exit this duplicate test
          return;
        }
        //this is the original test, delete the flag document
        await FirestoreService.get().deleteDocument('flag', 'flag');
      }
      //run the actual tests
      await theTest();
    
      if (kIsWeb) {
        //original test complete, add the flag document back for the next test, and to exit the duplicate test
        var doc = await FirestoreService.get()
            .addDocument('flag', {'testflag': true}, 'flag');
      }
    }
    
  14. MoaidAlrazhy commented on May 21, 2024

    @MoaidAlrazhy

    flutter drive --driver="test_driver/integration_test.dart" --target="integration_test/integration_test.dart" -d web-server --no-headless

    seems valid work around to run a single instance.

  15. ZacharyBohn commented on May 23, 2024

    @ZacharyBohn

    This is causing duplicate writes to firestore in my integration tests.

    I finally came up with a workaround to "pause" the duplicate test, and then exit the duplicate when the original test completes:

    Before starting your tests, create a firestore document with a specific id (ex. 'flag')
     
    In each test, check if the document exists.
    a. The document exists: Delete it and continue the test. After the test, add the document back.
    b. the document doesn't exist: Stream the collection and wait for the document to be added. When it is added, exit the function (do not continue the test).
    

    Basically this makes sure only the first test actually runs through, and the second test skips the actual testing and completes successfully once the first test completes (it is waiting for the first test to add the document back.

    It's a bit messy, but it works, and web testing is SUPER important because many packages behave differently on web and relying on other platforms for testing will likely result in shipping buggy web apps (I learned this the hard way after only testing on mac and windows for the past few months).

    Here is the code I use to wrap each test:

    Future<void> webTestWrapper(Future<void> Function() theTest) async {
      await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
    
      if (kIsWeb) {
       //get document 'flag' from collection 'flag'
        var doc = await FirestoreService.get().getDocument('flag', 'flag');
        if (doc == null) {
        //the doc was already deleted, so this is the duplicate test
          var waiting = true;
          //stream collection 'flag', stop waiting when the document is back
          stream = await FirestoreService.get().stream('flag', (docs) {
            if (doc?['testflag'] == true) {
              waiting = false;
            }
          });
          while (waiting) {
            await Future.delayed(const Duration(milliseconds: 500));
          }
          await stream?.cancel();
          //original test completed, exit this duplicate test
          return;
        }
        //this is the original test, delete the flag document
        await FirestoreService.get().deleteDocument('flag', 'flag');
      }
      //run the actual tests
      await theTest();
    
      if (kIsWeb) {
        //original test complete, add the flag document back for the next test, and to exit the duplicate test
        var doc = await FirestoreService.get()
            .addDocument('flag', {'testflag': true}, 'flag');
      }
    }
    

    Yeah we tried something similar and got it to work. I appreciate you sharing your work around!

    Just seems super crazy that the Flutter team put a double instance of the app into the codebase. Now we have to use weird arounds. Flutter web is not stable, despite what is claimed.

  16. desmond206x commented on Sep 13, 2024

    @desmond206x

    Tests will be executed twice for web.. 4 years and still no solution for this?

    I wasted more than one day to find this issue, because I debugged all of our code until I found out, that we start the flutter drive command with -d chrome in some cases.

    Wrap-up:
    flutter drive --driver=test_driver\test_driver.dart --target=integration_test\example_test.dart -d chrome --browser-name chrome -> Runs the test twice. One Chrome instance is visible. One hidden?

    flutter drive --driver=test_driver\test_driver.dart --target=integration_test\example_test.dart -d web-server --browser-name chrome --no-headless -> Runs the test only once. Chrome instance is visible.

  17. linchen2chris commented on Sep 26, 2024

    @linchen2chris
    Contributor

    The command flutter drive --driver=test_driver/test_driver.dart --target=integration_test/example_test.dart -d web-server --browser-name chrome --no-headless has been functioning correctly in our company for over two years and across hundreds of test cases.
    so I am pretty sure -d web-server --browser-name is the answer, hope it can helps.

  18. Justus-M commented on Aug 27, 2025

    @Justus-M

    This is still an issue that prevents integration tests on web from working properly.

    We tried -d web-server --browser-name and it works, but then you don't have any logs/prints which also makes it pretty unusable.

    Since web now supports hot reload it seems like it is getting some more love - Maybe now is the time to fix integration tests? @darshankawar @kevmoo

  19. blazetill commented on Oct 2, 2025

    @blazetill

    I found a workaround for the duplicate browser issue

    The Issue

    flutter drive -d chrome launches two browser instances:

    1. Regular Chrome (main test instance)
    2. HeadlessChrome (duplicate instance that also runs tests)

    Both run the same tests, causing duplicate execution.

    Workaround

    Add user agent detection to kill the HeadlessChrome duplicate instance early in your integration test:

    void main() {
      if (kIsWeb && html.window.navigator.userAgent.contains('HeadlessChrome')) {
        return; // Kill the HeadlessChrome duplicate instance
      }
      // Run tests only in regular Chrome instance
      runTests();
    }
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listcustomer: dentplatform-webWeb applications specificallyt: flutter driver"flutter driver", flutter_drive, or a driver testteam-webOwned by Web platform teamtoolAffects the "flutter" command-line tool. See also t: labels.triaged-webTriaged by Web platform team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions