testWidgets function Null safety

  1. @isTest
void testWidgets(
  1. String description,
  2. WidgetTesterCallback callback,
  3. {bool? skip,
  4. Timeout? timeout,
  5. @Deprecated('This parameter has no effect. Use `timeout` instead. ' 'This feature was deprecated after v2.6.0-1.0.pre.') Duration? initialTimeout,
  6. bool semanticsEnabled = true,
  7. TestVariant<Object?> variant = const DefaultTestVariant(),
  8. dynamic tags}
)

Runs the callback inside the Flutter test environment.

Use this function for testing custom StatelessWidgets and StatefulWidgets.

The callback can be asynchronous (using async/await or using explicit Futures).

The timeout argument specifies the backstop timeout implemented by the test package. If set, it should be relatively large (minutes). It defaults to ten minutes for tests run by flutter test, and is unlimited for tests run by flutter run; specifically, it defaults to TestWidgetsFlutterBinding.defaultTestTimeout. (The initialTimeout parameter has no effect. It was previously used with TestWidgetsFlutterBinding.addTime but that feature was removed.)

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. It defaults to true.

This function uses the test function in the test package to register the given callback as a test. The callback, when run, will be given a new instance of WidgetTester. The find object provides convenient widget Finders for use with the WidgetTester.

When the variant argument is set, testWidgets will run the test once for each value of the TestVariant.values. If variant is not set, the test will be run once using the base test environment.

If the tags are passed, they declare user-defined tags that are implemented by the test package.

See also:

Sample code

testWidgets('MyWidget', (WidgetTester tester) async {
  await tester.pumpWidget(MyWidget());
  await tester.tap(find.text('Save'));
  expect(find.text('Success'), findsOneWidget);
});

Implementation

@isTest
void testWidgets(
  String description,
  WidgetTesterCallback callback, {
  bool? skip,
  test_package.Timeout? timeout,
  @Deprecated(
    'This parameter has no effect. Use `timeout` instead. '
    'This feature was deprecated after v2.6.0-1.0.pre.'
  )
  Duration? initialTimeout,
  bool semanticsEnabled = true,
  TestVariant<Object?> variant = const DefaultTestVariant(),
  dynamic tags,
}) {
  assert(variant != null);
  assert(variant.values.isNotEmpty, 'There must be at least one value to test in the testing variant.');
  final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized() as TestWidgetsFlutterBinding;
  final WidgetTester tester = WidgetTester._(binding);
  for (final dynamic value in variant.values) {
    final String variationDescription = variant.describeValue(value);
    // IDEs may make assumptions about the format of this suffix in order to
    // support running tests directly from the editor (where they may have
    // access to only the test name, provided by the analysis server).
    // See https://github.com/flutter/flutter/issues/86659.
    final String combinedDescription = variationDescription.isNotEmpty
        ? '$description (variant: $variationDescription)'
        : description;
    test(
      combinedDescription,
      () {
        tester._testDescription = combinedDescription;
        SemanticsHandle? semanticsHandle;
        if (semanticsEnabled == true) {
          semanticsHandle = tester.ensureSemantics();
        }
        tester._recordNumberOfSemanticsHandles();
        test_package.addTearDown(binding.postTest);
        return binding.runTest(
          () async {
            binding.reset(); // TODO(ianh): the binding should just do this itself in _runTest
            debugResetSemanticsIdCounter();
            Object? memento;
            try {
              memento = await variant.setUp(value);
              await callback(tester);
            } finally {
              await variant.tearDown(value, memento);
            }
            semanticsHandle?.dispose();
          },
          tester._endOfTestVerifications,
          description: combinedDescription,
          timeout: initialTimeout,
        );
      },
      skip: skip,
      timeout: timeout ?? binding.defaultTestTimeout,
      tags: tags,
    );
  }
}