Skip to content

WidgetTest.pump(elapsedTime) doesn't advance time reliably #348

Description

@HansMuller

Using WidgetTest.pump(elapsedTime) to advance animations and completions in a test can be difficult because just calling the function once doesn't necessarily roll all of the test's state forward by the specified time. The unit test below illustrates a simple version of the problem: it's necessary to call pump(1 second) twice to get the 200ms performance from one end to the other. More complex widgets, see for example snack_bar_test.dart, require more blind test pumping.

import 'package:flutter/animation.dart';
import 'package:flutter/widgets.dart';

import 'package:test/test.dart';

import 'widget_tester.dart';

void main() {
  test('Time does not move', () {
    testWidgets((WidgetTester tester) {
      tester.pumpWidget(new Container());

      Performance performance = new Performance(duration: const Duration(milliseconds: 200))
        ..forward();
      print("performance.progress=${performance.progress} expect 0.0");

      tester.pump(new Duration(seconds: 1));
      print("performance.progress=${performance.progress} expect 1.0");

      tester.pump(new Duration(seconds: 1));
      print("performance.progress=${performance.progress} is actually 1.0");

      performance.reverse();
      tester.pump(new Duration(seconds: 1));
      print("performance.progress=${performance.progress} expect 0.0");

      tester.pump(new Duration(seconds: 1));
      print("performance.progress=${performance.progress} is actualy 0.0");
    });
  });
}

Activity

  1. added
    a: tests"flutter test", flutter_test, or one of our tests
    toolAffects the "flutter" command-line tool. See also t: labels.
    on Nov 12, 2015
  2. HansMuller commented on Nov 13, 2015

    @HansMuller
    ContributorAuthor

    It seemed like addling tester.async.flushMicrotasks(); calls after pump(), would run the completer that advanced the performance's timeline. That doesn't appear to be the case.

  3. abarth commented on Nov 13, 2015

    @abarth
    Contributor

    Pump already calls flushMicrotasks. Maybe the issue is that flushMicrotasks doesn't fully drain the microtask queue? The docs say it should:

      /// Runs all remaining microtasks, including those scheduled as a result of
      /// running them, until there are no more microtasks scheduled.
      ///
      /// Does not run timers.
    
  4. Hixie commented on Nov 18, 2015

    @Hixie
    Contributor

    The reason is that performances don't actually start when you call forward() or reverse(), they start at the next frame (the next call to pump(), in tests). This is good, it means all the animations will have consistent frame-aligned timings. If we didn't do this, then five animations started in the same 16ms interval might all have different start times.

    Thus, just adding the two lines marked <---- below solves the problem:

    import 'package:flutter/animation.dart';
    import 'package:flutter/widgets.dart';
    
    import 'package:test/test.dart';
    
    import 'widget_tester.dart';
    
    void main() {
      test('Time does not move', () {
        testWidgets((WidgetTester tester) {
          tester.pumpWidget(new Container());
    
          Performance performance = new Performance(duration: const Duration(milliseconds: 200))
            ..forward();
          tester.pump(); // <----
          print("performance.progress=${performance.progress} expect 0.0");
    
          tester.pump(new Duration(seconds: 1));
          print("performance.progress=${performance.progress} expect 1.0");
    
          tester.pump(new Duration(seconds: 1));
          print("performance.progress=${performance.progress} is actually 1.0");
    
          performance.reverse();
          tester.pump(); // <----
          tester.pump(new Duration(seconds: 1));
          print("performance.progress=${performance.progress} expect 0.0");
    
          tester.pump(new Duration(seconds: 1));
          print("performance.progress=${performance.progress} is actually 0.0");
        });
      });
    }
  5. github-actions commented on Sep 7, 2021

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  6. locked as resolved and limited conversation to collaborators on Sep 7, 2021
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

    a: tests"flutter test", flutter_test, or one of our teststoolAffects the "flutter" command-line tool. See also t: labels.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions