benchmarkWidgets function

Future<void> benchmarkWidgets (WidgetTesterCallback callback, { bool mayRunWithAsserts: false, bool semanticsEnabled: false })

Runs the callback inside the Flutter benchmark environment.

Use this function for benchmarking custom StatelessWidgets and StatefulWidgets when you want to be able to use features from TestWidgetsFlutterBinding. The callback, when run, will be given a new instance of WidgetTester. The find object provides convenient widget Finders for use with the WidgetTester.

The callback can be asynchronous (using async/await or using explicit Futures). If it is, then benchmarkWidgets will return a Future that completes when the callback's does. Otherwise, it will return a Future that is always complete.

If the callback is asynchronous, make sure you await the call to benchmarkWidgets, otherwise it won't run!

If the semanticsEnabled parameter is set to true, WidgetTester.ensureSemantics will have been called before the tester is passed to the callback, and that handle will automatically be disposed after the callback is finished.

Benchmarks must not be run in checked mode, because the performance is not representative. To avoid this, this function will print a big message if it is run in checked mode. Unit tests of this method pass mayRunWithAsserts, but it should not be used for actual benchmarking.

Example:

main() async {
  assert(false); // fail in checked mode
  await benchmarkWidgets((WidgetTester tester) async {
    await tester.pumpWidget(new MyWidget());
    final Stopwatch timer = new Stopwatch()..start();
    for (int index = 0; index < 10000; index += 1) {
      await tester.tap(find.text('Tap me'));
      await tester.pump();
    }
    timer.stop();
    debugPrint('Time taken: ${timer.elapsedMilliseconds}ms');
  });
  exit(0);
}

Implementation

Future<void> benchmarkWidgets(
  WidgetTesterCallback callback, {
  bool mayRunWithAsserts = false,
  bool semanticsEnabled = false,
}) {
  assert(() {
    if (mayRunWithAsserts)
      return true;

    print('┏╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍┓');
    print('┇ ⚠ THIS BENCHMARK IS BEING RUN WITH ASSERTS ENABLED ⚠  ┇');
    print('┡╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍┦');
    print('│                                                       │');
    print('│  Numbers obtained from a benchmark while asserts are  │');
    print('│  enabled will not accurately reflect the performance  │');
    print('│  that will be experienced by end users using release  ╎');
    print('│  builds. Benchmarks should be run using this command  ┆');
    print('│  line:  flutter run --release benchmark.dart          ┊');
    print('│                                                        ');
    print('└─────────────────────────────────────────────────╌┄┈  🐢');
    return true;
  }());
  final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
  assert(binding is! AutomatedTestWidgetsFlutterBinding);
  final WidgetTester tester = WidgetTester._(binding);
  SemanticsHandle semanticsHandle;
  if (semanticsEnabled == true) {
    semanticsHandle = tester.ensureSemantics();
  }
  tester._recordNumberOfSemanticsHandles();
  return binding.runTest(
    () async {
      await callback(tester);
      semanticsHandle?.dispose();
    },
    tester._endOfTestVerifications,
  ) ?? Future<void>.value();
}