revert #48985 (#49572)

diff --git a/dev/bots/test/common.dart b/dev/bots/test/common.dart
index 4060c06..6ca543f 100644
--- a/dev/bots/test/common.dart
+++ b/dev/bots/test/common.dart
@@ -13,7 +13,7 @@
 // TODO(ianh): Remove this file once https://github.com/dart-lang/matcher/issues/98 is fixed
 
 /// A matcher that compares the type of the actual value to the type argument T.
-Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();
+test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
 
 void tryToDelete(Directory directory) {
   // This should not be necessary, but it turns out that
diff --git a/dev/bots/test/prepare_package_test.dart b/dev/bots/test/prepare_package_test.dart
index 9f4a122..2f33ac9 100644
--- a/dev/bots/test/prepare_package_test.dart
+++ b/dev/bots/test/prepare_package_test.dart
@@ -25,7 +25,7 @@
         expectAsync1((List<String> commandLine) async {
           return processRunner.runProcess(commandLine);
         })(<String>['this_executable_better_not_exist_2857632534321']),
-        throwsA(isInstanceOf<PreparePackageException>()));
+        throwsA(isA<PreparePackageException>()));
     try {
       await processRunner.runProcess(<String>['this_executable_better_not_exist_2857632534321']);
     } on PreparePackageException catch (e) {
@@ -64,7 +64,7 @@
             expectAsync1((List<String> commandLine) async {
               return processRunner.runProcess(commandLine);
             })(<String>['echo', 'test']),
-            throwsA(isInstanceOf<PreparePackageException>()));
+            throwsA(isA<PreparePackageException>()));
       });
     });
     group('ArchiveCreator for $platformName', () {
@@ -185,8 +185,7 @@
           'git reset --hard $testRef': <ProcessResult>[ProcessResult(0, -1, 'output2', '')],
         };
         processManager.fakeResults = calls;
-        expect(expectAsync0(creator.initializeRepo),
-            throwsA(isInstanceOf<PreparePackageException>()));
+        expect(expectAsync0(creator.initializeRepo), throwsA(isA<PreparePackageException>()));
       });
 
       test('non-strict mode calls the right commands', () async {
diff --git a/dev/devicelab/test/common.dart b/dev/devicelab/test/common.dart
index 9449f93..64db237 100644
--- a/dev/devicelab/test/common.dart
+++ b/dev/devicelab/test/common.dart
@@ -11,4 +11,4 @@
 // TODO(ianh): Remove this file once https://github.com/dart-lang/matcher/issues/98 is fixed
 
 /// A matcher that compares the type of the actual value to the type argument T.
-Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();
+test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
diff --git a/dev/integration_tests/android_semantics_testing/lib/src/flutter_test_alternative.dart b/dev/integration_tests/android_semantics_testing/lib/src/flutter_test_alternative.dart
index c2aacda6..1865b6f 100644
--- a/dev/integration_tests/android_semantics_testing/lib/src/flutter_test_alternative.dart
+++ b/dev/integration_tests/android_semantics_testing/lib/src/flutter_test_alternative.dart
@@ -11,4 +11,4 @@
 export 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
 
 /// A matcher that compares the type of the actual value to the type argument T.
-Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();
+test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
diff --git a/dev/tools/test/common.dart b/dev/tools/test/common.dart
index 4060c06..6ca543f 100644
--- a/dev/tools/test/common.dart
+++ b/dev/tools/test/common.dart
@@ -13,7 +13,7 @@
 // TODO(ianh): Remove this file once https://github.com/dart-lang/matcher/issues/98 is fixed
 
 /// A matcher that compares the type of the actual value to the type argument T.
-Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();
+test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
 
 void tryToDelete(Directory directory) {
   // This should not be necessary, but it turns out that
diff --git a/dev/tools/vitool/test/vitool_test.dart b/dev/tools/vitool/test/vitool_test.dart
index fffcef2..9bb65ca 100644
--- a/dev/tools/vitool/test/vitool_test.dart
+++ b/dev/tools/vitool/test/vitool_test.dart
@@ -17,7 +17,7 @@
   test('parsePixels', () {
     expect(parsePixels('23px'), 23);
     expect(parsePixels('9px'), 9);
-    expect(() { parsePixels('9pt'); }, throwsA(isInstanceOf<ArgumentError>()));
+    expect(() { parsePixels('9pt'); }, throwsArgumentError);
   });
 
   test('parsePoints', () {
diff --git a/examples/flutter_gallery/lib/demo/cupertino/cupertino_picker_demo.dart b/examples/flutter_gallery/lib/demo/cupertino/cupertino_picker_demo.dart
index 9ce07f6..f45819e 100644
--- a/examples/flutter_gallery/lib/demo/cupertino/cupertino_picker_demo.dart
+++ b/examples/flutter_gallery/lib/demo/cupertino/cupertino_picker_demo.dart
@@ -108,6 +108,7 @@
       onTap: () async {
         await showCupertinoModalPopup<void>(
           context: context,
+          semanticsDismissible: true,
           builder: (BuildContext context) {
             return _BottomPicker(
               child: CupertinoPicker(
@@ -144,6 +145,7 @@
       onTap: () {
         showCupertinoModalPopup<void>(
           context: context,
+          semanticsDismissible: true,
           builder: (BuildContext context) {
             return _BottomPicker(
               child: CupertinoTimerPicker(
@@ -176,6 +178,7 @@
       onTap: () {
         showCupertinoModalPopup<void>(
           context: context,
+          semanticsDismissible: true,
           builder: (BuildContext context) {
             return _BottomPicker(
               child: CupertinoDatePicker(
@@ -207,6 +210,7 @@
       onTap: () {
         showCupertinoModalPopup<void>(
           context: context,
+          semanticsDismissible: true,
           builder: (BuildContext context) {
             return _BottomPicker(
               child: CupertinoDatePicker(
@@ -238,6 +242,7 @@
       onTap: () {
         showCupertinoModalPopup<void>(
           context: context,
+          semanticsDismissible: true,
           builder: (BuildContext context) {
             return _BottomPicker(
               child: CupertinoDatePicker(
diff --git a/packages/flutter/lib/src/cupertino/picker.dart b/packages/flutter/lib/src/cupertino/picker.dart
index f20f796..2ab858d 100644
--- a/packages/flutter/lib/src/cupertino/picker.dart
+++ b/packages/flutter/lib/src/cupertino/picker.dart
@@ -35,7 +35,8 @@
 /// that child the initially selected child.
 ///
 /// Can be used with [showCupertinoModalPopup] to display the picker modally at the
-/// bottom of the screen.
+/// bottom of the screen. When calling [showCupertinoModalPopup], be sure to set
+/// `semanticsDismissible` to true to enable dismissing the modal via semantics.
 ///
 /// Sizes itself to its parent. All children are sized to the same size based
 /// on [itemExtent].
diff --git a/packages/flutter/lib/src/cupertino/route.dart b/packages/flutter/lib/src/cupertino/route.dart
index 61e88f6..8ecbaec 100644
--- a/packages/flutter/lib/src/cupertino/route.dart
+++ b/packages/flutter/lib/src/cupertino/route.dart
@@ -792,14 +792,18 @@
     this.barrierColor,
     this.barrierLabel,
     this.builder,
+    bool semanticsDismissible,
     ImageFilter filter,
     RouteSettings settings,
   }) : super(
          filter: filter,
          settings: settings,
-       );
+       ) {
+    _semanticsDismissible = semanticsDismissible;
+  }
 
   final WidgetBuilder builder;
+  bool _semanticsDismissible;
 
   @override
   final String barrierLabel;
@@ -811,7 +815,7 @@
   bool get barrierDismissible => true;
 
   @override
-  bool get semanticsDismissible => false;
+  bool get semanticsDismissible => _semanticsDismissible ?? false;
 
   @override
   Duration get transitionDuration => _kModalPopupTransitionDuration;
@@ -871,6 +875,9 @@
 /// popup to the [Navigator] furthest from or nearest to the given `context`. It
 /// is `false` by default.
 ///
+/// The `semanticsDismissble` argument is used to determine whether the
+/// semantics of the modal barrier are included in the semantics tree.
+///
 /// The `builder` argument typically builds a [CupertinoActionSheet] widget.
 /// Content below the widget is dimmed with a [ModalBarrier]. The widget built
 /// by the `builder` does not share a context with the location that
@@ -891,6 +898,7 @@
   @required WidgetBuilder builder,
   ImageFilter filter,
   bool useRootNavigator = true,
+  bool semanticsDismissible,
 }) {
   assert(useRootNavigator != null);
   return Navigator.of(context, rootNavigator: useRootNavigator).push(
@@ -899,6 +907,7 @@
       barrierLabel: 'Dismiss',
       builder: builder,
       filter: filter,
+      semanticsDismissible: semanticsDismissible,
     ),
   );
 }
diff --git a/packages/flutter/lib/src/cupertino/segmented_control.dart b/packages/flutter/lib/src/cupertino/segmented_control.dart
index 04c276b..4d5cb5f 100644
--- a/packages/flutter/lib/src/cupertino/segmented_control.dart
+++ b/packages/flutter/lib/src/cupertino/segmented_control.dart
@@ -61,6 +61,8 @@
 ///
 /// See also:
 ///
+///  * [CupertinoSegmentedControl], a segmented control widget in the style used
+///    up until iOS 13.
 ///  * <https://developer.apple.com/design/human-interface-guidelines/ios/controls/segmented-controls/>
 class CupertinoSegmentedControl<T> extends StatefulWidget {
   /// Creates an iOS-style segmented control bar.
diff --git a/packages/flutter/lib/src/cupertino/sliding_segmented_control.dart b/packages/flutter/lib/src/cupertino/sliding_segmented_control.dart
index d923851..b593fd8 100644
--- a/packages/flutter/lib/src/cupertino/sliding_segmented_control.dart
+++ b/packages/flutter/lib/src/cupertino/sliding_segmented_control.dart
@@ -118,6 +118,8 @@
 ///
 /// See also:
 ///
+///  * [CupertinoSlidingSegmentedControl], a segmented control widget in the
+///    style introduced in iOS 13.
 ///  * <https://developer.apple.com/design/human-interface-guidelines/ios/controls/segmented-controls/>
 class CupertinoSlidingSegmentedControl<T> extends StatefulWidget {
   /// Creates an iOS-style segmented control bar.
diff --git a/packages/flutter/lib/src/painting/image_cache.dart b/packages/flutter/lib/src/painting/image_cache.dart
index 75e8d05..7a296ae 100644
--- a/packages/flutter/lib/src/painting/image_cache.dart
+++ b/packages/flutter/lib/src/painting/image_cache.dart
@@ -32,7 +32,7 @@
 /// {@tool snippet}
 ///
 /// This sample shows how to supply your own caching logic and replace the
-/// global [imageCache] varible.
+/// global [imageCache] variable.
 ///
 /// ```dart
 /// /// This is the custom implementation of [ImageCache] where we can override
@@ -64,7 +64,6 @@
 /// }
 /// ```
 /// {@end-tool}
-
 class ImageCache {
   final Map<Object, _PendingImage> _pendingImages = <Object, _PendingImage>{};
   final Map<Object, _CachedImage> _cache = <Object, _CachedImage>{};
@@ -141,12 +140,13 @@
   }
 
   /// Evicts a single entry from the cache, returning true if successful.
-  /// Pending images waiting for completion are removed as well, returning true if successful.
+  /// Pending images waiting for completion are removed as well, returning true
+  /// if successful.
   ///
-  /// When a pending image is removed the listener on it is removed as well to prevent
-  /// it from adding itself to the cache if it eventually completes.
+  /// When a pending image is removed the listener on it is removed as well to
+  /// prevent it from adding itself to the cache if it eventually completes.
   ///
-  /// The [key] must be equal to an object used to cache an image in
+  /// The `key` must be equal to an object used to cache an image in
   /// [ImageCache.putIfAbsent].
   ///
   /// If the key is not immediately available, as is common, consider using
diff --git a/packages/flutter/lib/src/painting/image_stream.dart b/packages/flutter/lib/src/painting/image_stream.dart
index 79d257d..9fefe96 100644
--- a/packages/flutter/lib/src/painting/image_stream.dart
+++ b/packages/flutter/lib/src/painting/image_stream.dart
@@ -15,7 +15,7 @@
 /// actual data of the image once it has been obtained.
 @immutable
 class ImageInfo {
-  /// Creates an [ImageInfo] object for the given image and scale.
+  /// Creates an [ImageInfo] object for the given [image] and [scale].
   ///
   /// Both the image and the scale must not be null.
   const ImageInfo({ @required this.image, this.scale = 1.0 })
@@ -35,9 +35,9 @@
   ///
   /// For example, if this is 2.0 it means that there are four image pixels for
   /// every one logical pixel, and the image's actual width and height (as given
-  /// by the [dart:ui.Image.width] and [dart:ui.Image.height] properties) are double the
-  /// height and width that should be used when painting the image (e.g. in the
-  /// arguments given to [Canvas.drawImage]).
+  /// by the [dart:ui.Image.width] and [dart:ui.Image.height] properties) are
+  /// double the height and width that should be used when painting the image
+  /// (e.g. in the arguments given to [Canvas.drawImage]).
   final double scale;
 
   @override
@@ -58,11 +58,11 @@
 
 /// Interface for receiving notifications about the loading of an image.
 ///
-/// This class overrides `operator ==` and `hashCode` to compare the individual
+/// This class overrides [operator ==] and [hashCode] to compare the individual
 /// callbacks in the listener, meaning that if you add an instance of this class
 /// as a listener (e.g. via [ImageStream.addListener]), you can instantiate a
 /// _different_ instance of this class when you remove the listener, and the
-/// listener will be properly removed as long all associated callbacks are
+/// listener will be properly removed as long as all associated callbacks are
 /// equal.
 ///
 /// Used by [ImageStream] and [ImageStreamCompleter].
diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart
index 1b89c0e..171bdc7 100644
--- a/packages/flutter/lib/src/rendering/editable.dart
+++ b/packages/flutter/lib/src/rendering/editable.dart
@@ -409,8 +409,14 @@
   ) {
     // Changes made by the keyboard can sometimes be "out of band" for listening
     // components, so always send those events, even if we didn't think it
-    // changed.
-    if (nextSelection == selection && cause != SelectionChangedCause.keyboard) {
+    // changed. Also, focusing an empty field is sent as a selection change even
+    // if the selection offset didn't change.
+    final bool focusingEmpty = nextSelection.baseOffset == 0
+      && nextSelection.extentOffset == 0
+      && !hasFocus;
+    if (nextSelection == selection
+        && cause != SelectionChangedCause.keyboard
+        && !focusingEmpty) {
       return;
     }
     if (onSelectionChanged != null) {
diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart
index af1ea37..8553064 100644
--- a/packages/flutter/lib/src/rendering/proxy_box.dart
+++ b/packages/flutter/lib/src/rendering/proxy_box.dart
@@ -2472,7 +2472,6 @@
       return;
     _translation = value;
     markNeedsPaint();
-    markNeedsSemanticsUpdate();
   }
 
   @override
diff --git a/packages/flutter/test/animation/futures_test.dart b/packages/flutter/test/animation/futures_test.dart
index 0965ec8..e389f1c 100644
--- a/packages/flutter/test/animation/futures_test.dart
+++ b/packages/flutter/test/animation/futures_test.dart
@@ -172,10 +172,10 @@
     final TickerFuture f = controller1.forward();
     await tester.pump(); // start ticker
     await tester.pump(const Duration(milliseconds: 200)); // end ticker
-    expect(f.asStream().single, isInstanceOf<Future<void>>());
+    expect(f.asStream().single, isA<Future<void>>());
     await f.catchError((dynamic e) { throw 'do not reach'; });
     expect(await f.then<bool>((_) => true), isTrue);
-    expect(f.whenComplete(() => false), isInstanceOf<Future<void>>());
-    expect(f.timeout(const Duration(seconds: 5)), isInstanceOf<Future<void>>());
+    expect(f.whenComplete(() => false), isA<Future<void>>());
+    expect(f.timeout(const Duration(seconds: 5)), isA<Future<void>>());
   });
 }
diff --git a/packages/flutter/test/cupertino/picker_test.dart b/packages/flutter/test/cupertino/picker_test.dart
index 2d39125..b5ff312 100644
--- a/packages/flutter/test/cupertino/picker_test.dart
+++ b/packages/flutter/test/cupertino/picker_test.dart
@@ -153,7 +153,6 @@
     testWidgets(
       'scrolling calls onSelectedItemChanged and triggers haptic feedback',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
         final List<int> selectedItems = <int>[];
         final List<MethodCall> systemCalls = <MethodCall>[];
 
@@ -200,15 +199,11 @@
             arguments: 'HapticFeedbackType.selectionClick',
           ),
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
 
     testWidgets(
       'do not trigger haptic effects on non-iOS devices',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.android;
         final List<int> selectedItems = <int>[];
         final List<MethodCall> systemCalls = <MethodCall>[];
 
@@ -238,13 +233,9 @@
         await tester.drag(find.text('0'), const Offset(0.0, -100.0));
         expect(selectedItems, <int>[1]);
         expect(systemCalls, isEmpty);
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: TargetPlatformVariant(TargetPlatform.values.where((TargetPlatform platform) => platform != TargetPlatform.iOS).toSet()));
 
     testWidgets('a drag in between items settles back', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
       final FixedExtentScrollController controller =
           FixedExtentScrollController(initialItem: 10);
       final List<int> selectedItems = <int>[];
@@ -297,11 +288,9 @@
         moreOrLessEquals(350.0, epsilon: 0.5),
       );
       expect(selectedItems, <int>[9]);
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets('a big fling that overscrolls springs back', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
       final FixedExtentScrollController controller =
           FixedExtentScrollController(initialItem: 10);
       final List<int> selectedItems = <int>[];
@@ -357,8 +346,6 @@
         // Falling back to 0 shouldn't produce more callbacks.
         <int>[8, 6, 4, 2, 0],
       );
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
   });
 }
diff --git a/packages/flutter/test/cupertino/refresh_test.dart b/packages/flutter/test/cupertino/refresh_test.dart
index 64fbe51..738e4c9 100644
--- a/packages/flutter/test/cupertino/refresh_test.dart
+++ b/packages/flutter/test/cupertino/refresh_test.dart
@@ -74,8 +74,6 @@
 
   final VoidCallback uiTestGroup = () {
     testWidgets("doesn't invoke anything without user interaction", (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       await tester.pumpWidget(
         Directionality(
           textDirection: TextDirection.ltr,
@@ -96,13 +94,9 @@
         tester.getTopLeft(find.widgetWithText(Container, '0')),
         const Offset(0.0, 0.0),
       );
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets('calls the indicator builder when starting to overscroll', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       await tester.pumpWidget(
         Directionality(
           textDirection: TextDirection.ltr,
@@ -136,15 +130,11 @@
         tester.getTopLeft(find.widgetWithText(Container, '0')),
         const Offset(0.0, 50.0),
       );
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       "don't call the builder if overscroll doesn't move slivers like on Android",
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.android;
-
         await tester.pumpWidget(
           Directionality(
             textDirection: TextDirection.ltr,
@@ -169,14 +159,9 @@
           tester.getTopLeft(find.widgetWithText(Container, '0')),
           const Offset(0.0, 0.0),
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: TargetPlatformVariant.only(TargetPlatform.android));
 
     testWidgets('let the builder update as canceled drag scrolls away', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       await tester.pumpWidget(
         Directionality(
           textDirection: TextDirection.ltr,
@@ -228,13 +213,9 @@
         tester.getTopLeft(find.widgetWithText(Container, '0')),
         const Offset(0.0, 0.0),
       );
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets('drag past threshold triggers refresh task', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       final List<MethodCall> platformCallLog = <MethodCall>[];
 
       SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
@@ -295,14 +276,11 @@
         platformCallLog.last,
         isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.mediumImpact'),
       );
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       'refreshing task keeps the sliver expanded forever until done',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         await tester.pumpWidget(
           Directionality(
             textDirection: TextDirection.ltr,
@@ -370,15 +348,11 @@
           60.0, // Default value.
         ));
         verifyNoMoreInteractions(mockHelper);
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       'refreshing task keeps the sliver expanded forever until completes with error',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
         final FlutterError error = FlutterError('Oops');
         double errorCount = 0;
 
@@ -460,14 +434,9 @@
             errorCount++;
           },
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets('expanded refreshing sliver scrolls normally', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       refreshIndicator = const Center(child: Text('-1'));
 
       await tester.pumpWidget(
@@ -541,13 +510,9 @@
         tester.getRect(find.widgetWithText(Center, '0')),
         const Rect.fromLTRB(0.0, 60.0, 800.0, 260.0),
       );
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets('expanded refreshing sliver goes away when done', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       refreshIndicator = const Center(child: Text('-1'));
 
       await tester.pumpWidget(
@@ -616,13 +581,9 @@
         tester.getRect(find.widgetWithText(Center, '0')),
         const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
       );
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets('builder still called when sliver snapped back more than 90%', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       refreshIndicator = const Center(child: Text('-1'));
 
       await tester.pumpWidget(
@@ -704,15 +665,11 @@
         60.0, // Default value.
       ));
       expect(find.text('-1'), findsOneWidget);
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       'retracting sliver during done cannot be pulled to refresh again until fully retracted',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         refreshIndicator = const Center(child: Text('-1'));
 
         await tester.pumpWidget(
@@ -791,17 +748,12 @@
           40.0,
           100.0, // Default value.
           60.0, // Default value.
-        ));
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+      ));
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       'sliver held in overscroll when task finishes completes normally',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         refreshIndicator = const Center(child: Text('-1'));
 
         await tester.pumpWidget(
@@ -848,10 +800,7 @@
           tester.getRect(find.widgetWithText(Center, '0')),
           const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       'sliver scrolled away when task completes properly removes itself',
@@ -861,8 +810,6 @@
           // the indicator can be scrolled away while refreshing.
           return;
         }
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         refreshIndicator = const Center(child: Text('-1'));
 
         await tester.pumpWidget(
@@ -940,16 +887,11 @@
           tester.getRect(find.widgetWithText(Center, '0')),
           const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       "don't do anything unless it can be overscrolled at the start of the list",
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         refreshIndicator = const Center(child: Text('-1'));
 
         await tester.pumpWidget(
@@ -973,16 +915,11 @@
         await tester.fling(find.byType(Container).first, const Offset(0.0, -200.0), 3000.0);
 
         verifyNoMoreInteractions(mockHelper);
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       'without an onRefresh, builder is called with arm for one frame then sliver goes away',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         refreshIndicator = const Center(child: Text('-1'));
 
         await tester.pumpWidget(
@@ -1024,10 +961,7 @@
           tester.getRect(find.widgetWithText(Center, '0')),
           const Rect.fromLTRB(0.0, 0.0, 800.0, 200.0),
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets('Should not crash when dragged', (WidgetTester tester) async {
       await tester.pumpWidget(
@@ -1051,13 +985,11 @@
       await tester.pump();
 
       expect(tester.takeException(), isNull);
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
   };
 
   final VoidCallback stateMachineTestGroup = () {
     testWidgets('starts in inactive state', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       await tester.pumpWidget(
         Directionality(
           textDirection: TextDirection.ltr,
@@ -1076,13 +1008,9 @@
         CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder, skipOffstage: false))),
         RefreshIndicatorMode.inactive,
       );
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets('goes to drag and returns to inactive in a small drag', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       await tester.pumpWidget(
         Directionality(
           textDirection: TextDirection.ltr,
@@ -1111,13 +1039,9 @@
         CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder, skipOffstage: false))),
         RefreshIndicatorMode.inactive,
       );
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets('goes to armed the frame it passes the threshold', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       await tester.pumpWidget(
         Directionality(
           textDirection: TextDirection.ltr,
@@ -1147,15 +1071,11 @@
         CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
         RefreshIndicatorMode.armed,
       );
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       'goes to refresh the frame it crossed back the refresh threshold',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         await tester.pumpWidget(
           Directionality(
             textDirection: TextDirection.ltr,
@@ -1191,16 +1111,11 @@
           CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
           RefreshIndicatorMode.refresh,
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       'goes to done internally as soon as the task finishes',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         await tester.pumpWidget(
           Directionality(
             textDirection: TextDirection.ltr,
@@ -1243,16 +1158,11 @@
           CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
           RefreshIndicatorMode.done,
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       'goes back to inactive when retracting back past 10% of arming distance',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         await tester.pumpWidget(
           Directionality(
             textDirection: TextDirection.ltr,
@@ -1306,16 +1216,11 @@
           CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder))),
           RefreshIndicatorMode.inactive,
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       'goes back to inactive if already scrolled away when task completes',
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         await tester.pumpWidget(
           Directionality(
             textDirection: TextDirection.ltr,
@@ -1370,16 +1275,11 @@
           tester.getTopLeft(find.widgetWithText(Container, '0')).dy,
           moreOrLessEquals(-145.0332383665717),
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets(
       "don't have to build any indicators or occupy space during refresh",
       (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
         refreshIndicator = const Center(child: Text('-1'));
 
         await tester.pumpWidget(
@@ -1425,10 +1325,7 @@
           CupertinoSliverRefreshControl.state(tester.element(find.byType(LayoutBuilder, skipOffstage: false))),
           RefreshIndicatorMode.inactive,
         );
-
-        debugDefaultTargetPlatformOverride = null;
-      },
-    );
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
     testWidgets('buildSimpleRefreshIndicator dark mode', (WidgetTester tester) async {
       const CupertinoDynamicColor color = CupertinoColors.inactiveGray;
diff --git a/packages/flutter/test/cupertino/route_test.dart b/packages/flutter/test/cupertino/route_test.dart
index ef2a58e..cf1c6be 100644
--- a/packages/flutter/test/cupertino/route_test.dart
+++ b/packages/flutter/test/cupertino/route_test.dart
@@ -3,11 +3,14 @@
 // found in the LICENSE file.
 
 import 'package:flutter/cupertino.dart';
+import 'package:flutter/foundation.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 import 'package:mockito/mockito.dart';
 
+import '../widgets/semantics_tester.dart';
+
 void main() {
   MockNavigatorObserver navigatorObserver;
 
@@ -1052,6 +1055,75 @@
     expect(rootObserver.dialogCount, 0);
     expect(nestedObserver.dialogCount, 1);
   });
+
+  testWidgets('showCupertinoModalPopup does not allow for semantics dismiss by default', (WidgetTester tester) async {
+    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
+    final SemanticsTester semantics = SemanticsTester(tester);
+    await tester.pumpWidget(CupertinoApp(
+      home: Navigator(
+        onGenerateRoute: (RouteSettings settings) {
+          return PageRouteBuilder<dynamic>(
+            pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
+              return GestureDetector(
+                onTap: () async {
+                  await showCupertinoModalPopup<void>(
+                    context: context,
+                    builder: (BuildContext context) => const SizedBox(),
+                  );
+                },
+                child: const Text('tap'),
+              );
+            },
+          );
+        },
+      ),
+    ));
+
+    // Push the route.
+    await tester.tap(find.text('tap'));
+    await tester.pumpAndSettle();
+
+    expect(semantics, isNot(includesNodeWith(
+      actions: <SemanticsAction>[SemanticsAction.tap],
+      label: 'Dismiss',
+    )));
+    debugDefaultTargetPlatformOverride = null;
+  });
+
+  testWidgets('showCupertinoModalPopup allows for semantics dismiss when set', (WidgetTester tester) async {
+    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
+    final SemanticsTester semantics = SemanticsTester(tester);
+    await tester.pumpWidget(CupertinoApp(
+      home: Navigator(
+        onGenerateRoute: (RouteSettings settings) {
+          return PageRouteBuilder<dynamic>(
+            pageBuilder: (BuildContext context, Animation<double> _, Animation<double> __) {
+              return GestureDetector(
+                onTap: () async {
+                  await showCupertinoModalPopup<void>(
+                    context: context,
+                    semanticsDismissible: true,
+                    builder: (BuildContext context) => const SizedBox(),
+                  );
+                },
+                child: const Text('tap'),
+              );
+            },
+          );
+        },
+      ),
+    ));
+
+    // Push the route.
+    await tester.tap(find.text('tap'));
+    await tester.pumpAndSettle();
+
+    expect(semantics, includesNodeWith(
+      actions: <SemanticsAction>[SemanticsAction.tap],
+      label: 'Dismiss',
+    ));
+    debugDefaultTargetPlatformOverride = null;
+  });
 }
 
 class MockNavigatorObserver extends Mock implements NavigatorObserver {}
diff --git a/packages/flutter/test/cupertino/switch_test.dart b/packages/flutter/test/cupertino/switch_test.dart
index 2935cec..3857a26 100644
--- a/packages/flutter/test/cupertino/switch_test.dart
+++ b/packages/flutter/test/cupertino/switch_test.dart
@@ -43,7 +43,6 @@
   });
 
   testWidgets('Switch emits light haptic vibration on tap', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     final Key switchKey = UniqueKey();
     bool value = false;
 
@@ -80,11 +79,9 @@
 
     expect(log, hasLength(1));
     expect(log.single, isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.lightImpact'));
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
 
   testWidgets('Using other widgets that rebuild the switch will not cause vibrations', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     final Key switchKey = UniqueKey();
     final Key switchKey2 = UniqueKey();
     bool value = false;
@@ -152,11 +149,9 @@
 
     expect(log, hasLength(4));
     expect(log[3], isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.lightImpact'));
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
 
   testWidgets('Haptic vibration triggers on drag', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     bool value = false;
     final List<MethodCall> log = <MethodCall>[];
 
@@ -191,11 +186,9 @@
 
     expect(log, hasLength(1));
     expect(log[0], isMethodCall('HapticFeedback.vibrate', arguments: 'HapticFeedbackType.lightImpact'));
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
 
   testWidgets('No haptic vibration triggers from a programmatic value change', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     final Key switchKey = UniqueKey();
     bool value = false;
 
@@ -244,8 +237,7 @@
     await tester.pump();
 
     expect(log, hasLength(0));
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
 
   testWidgets('Switch can drag (LTR)', (WidgetTester tester) async {
     bool value = false;
diff --git a/packages/flutter/test/cupertino/text_field_test.dart b/packages/flutter/test/cupertino/text_field_test.dart
index ce9ea76..0d6d514 100644
--- a/packages/flutter/test/cupertino/text_field_test.dart
+++ b/packages/flutter/test/cupertino/text_field_test.dart
@@ -425,9 +425,7 @@
     expect(editableText.cursorOffset, const Offset(-2.0 / 3.0, 0));
   });
 
-  testWidgets('Cursor animates on iOS', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
+  testWidgets('Cursor animates', (WidgetTester tester) async {
     await tester.pumpWidget(
       const CupertinoApp(
         home: CupertinoTextField(),
@@ -459,13 +457,9 @@
     await tester.pump(const Duration(milliseconds: 50));
 
     expect(renderEditable.cursorColor.alpha, 0);
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
 
-    debugDefaultTargetPlatformOverride = null;
-  });
-
-  testWidgets('Cursor radius is 2.0 on iOS', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
+  testWidgets('Cursor radius is 2.0', (WidgetTester tester) async {
     await tester.pumpWidget(
       const CupertinoApp(
         home: CupertinoTextField(),
@@ -476,9 +470,7 @@
     final RenderEditable renderEditable = editableTextState.renderEditable;
 
     expect(renderEditable.cursorRadius, const Radius.circular(2.0));
-
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
 
   testWidgets('Cupertino cursor android golden', (WidgetTester tester) async {
     final Widget widget = CupertinoApp(
@@ -507,9 +499,7 @@
     );
   });
 
-  testWidgets('Cupertino cursor iOS golden', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
+  testWidgets('Cupertino cursor golden', (WidgetTester tester) async {
     final Widget widget = CupertinoApp(
       home: Center(
         child: RepaintBoundary(
@@ -530,12 +520,13 @@
     await tester.tapAt(textOffsetToPosition(tester, testValue.length));
     await tester.pumpAndSettle();
 
-    debugDefaultTargetPlatformOverride = null;
     await expectLater(
       find.byKey(const ValueKey<int>(1)),
-      matchesGoldenFile('text_field_cursor_test.cupertino.1.png'),
+      matchesGoldenFile(
+        'text_field_cursor_test.cupertino_${describeEnum(debugDefaultTargetPlatformOverride).toLowerCase()}.1.png',
+      ),
     );
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
     'can control text content via controller',
@@ -2946,8 +2937,7 @@
     expect(editableText.cursorColor.value, 0x87654321);
   });
 
-  testWidgets('iOS shows selection handles', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
+  testWidgets('shows selection handles', (WidgetTester tester) async {
     const String testText = 'lorem ipsum';
     final TextEditingController controller = TextEditingController(text: testText);
 
@@ -2977,9 +2967,7 @@
 
     expect(left.opacity.value, equals(1.0));
     expect(right.opacity.value, equals(1.0));
-
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('when CupertinoTextField would be blocked by keyboard, it is shown with enough space for the selection handle', (WidgetTester tester) async {
     final ScrollController scrollController = ScrollController();
diff --git a/packages/flutter/test/flutter_test_alternative.dart b/packages/flutter/test/flutter_test_alternative.dart
index 694f751..a67c1c6 100644
--- a/packages/flutter/test/flutter_test_alternative.dart
+++ b/packages/flutter/test/flutter_test_alternative.dart
@@ -11,7 +11,7 @@
 export 'package:test_api/test_api.dart' hide TypeMatcher, isInstanceOf; // ignore: deprecated_member_use
 
 /// A matcher that compares the type of the actual value to the type argument T.
-Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();
+test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
 
 /// Whether we are running in a web browser.
 const bool isBrowser = identical(0, 0.0);
diff --git a/packages/flutter/test/foundation/consolidate_response_test.dart b/packages/flutter/test/foundation/consolidate_response_test.dart
index 208fe6c..43c4242 100644
--- a/packages/flutter/test/foundation/consolidate_response_test.dart
+++ b/packages/flutter/test/foundation/consolidate_response_test.dart
@@ -110,8 +110,7 @@
       });
       when(response.contentLength).thenReturn(-1);
 
-      expect(consolidateHttpClientResponseBytes(response),
-          throwsA(isInstanceOf<Exception>()));
+      expect(consolidateHttpClientResponseBytes(response), throwsException);
     });
 
     test('Propagates error to Future return value if onBytesReceived throws', () async {
diff --git a/packages/flutter/test/foundation/isolates_test.dart b/packages/flutter/test/foundation/isolates_test.dart
index c7cca03..bbd339d 100644
--- a/packages/flutter/test/foundation/isolates_test.dart
+++ b/packages/flutter/test/foundation/isolates_test.dart
@@ -27,9 +27,9 @@
 void main() {
   test('compute()', () async {
     expect(await compute(test1, 0), 1);
-    expect(compute(test2, 0), throwsA(isInstanceOf<Exception>()));
+    expect(compute(test2, 0), throwsException);
 
     expect(await compute(test1Async, 0), 1);
-    expect(compute(test2Async, 0), throwsA(isInstanceOf<Exception>()));
+    expect(compute(test2Async, 0), throwsException);
   });
 }
diff --git a/packages/flutter/test/foundation/service_extensions_test.dart b/packages/flutter/test/foundation/service_extensions_test.dart
index 4844dd4..ab0e26b 100644
--- a/packages/flutter/test/foundation/service_extensions_test.dart
+++ b/packages/flutter/test/foundation/service_extensions_test.dart
@@ -489,43 +489,51 @@
     extensionChangedEvent = extensionChangedEvents.last;
     expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
     expect(extensionChangedEvent['value'], 'iOS');
+    result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'macOS'}));
+    expect(result, <String, String>{'value': 'macOS'});
+    expect(binding.reassembled, 2);
+    expect(defaultTargetPlatform, TargetPlatform.macOS);
+    expect(extensionChangedEvents.length, 2);
+    extensionChangedEvent = extensionChangedEvents.last;
+    expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
+    expect(extensionChangedEvent['value'], 'macOS');
     result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'android'}));
     expect(result, <String, String>{'value': 'android'});
-    expect(binding.reassembled, 2);
+    expect(binding.reassembled, 3);
     expect(defaultTargetPlatform, TargetPlatform.android);
-    expect(extensionChangedEvents.length, 2);
+    expect(extensionChangedEvents.length, 3);
     extensionChangedEvent = extensionChangedEvents.last;
     expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
     expect(extensionChangedEvent['value'], 'android');
     result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'fuchsia'}));
     expect(result, <String, String>{'value': 'fuchsia'});
-    expect(binding.reassembled, 3);
+    expect(binding.reassembled, 4);
     expect(defaultTargetPlatform, TargetPlatform.fuchsia);
-    expect(extensionChangedEvents.length, 3);
+    expect(extensionChangedEvents.length, 4);
     extensionChangedEvent = extensionChangedEvents.last;
     expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
     expect(extensionChangedEvent['value'], 'fuchsia');
     result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'default'}));
     expect(result, <String, String>{'value': 'android'});
-    expect(binding.reassembled, 4);
+    expect(binding.reassembled, 5);
     expect(defaultTargetPlatform, TargetPlatform.android);
-    expect(extensionChangedEvents.length, 4);
+    expect(extensionChangedEvents.length, 5);
     extensionChangedEvent = extensionChangedEvents.last;
     expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
     expect(extensionChangedEvent['value'], 'android');
     result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'iOS'}));
     expect(result, <String, String>{'value': 'iOS'});
-    expect(binding.reassembled, 5);
+    expect(binding.reassembled, 6);
     expect(defaultTargetPlatform, TargetPlatform.iOS);
-    expect(extensionChangedEvents.length, 5);
+    expect(extensionChangedEvents.length, 6);
     extensionChangedEvent = extensionChangedEvents.last;
     expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
     expect(extensionChangedEvent['value'], 'iOS');
     result = await hasReassemble(binding.testExtension('platformOverride', <String, String>{'value': 'bogus'}));
     expect(result, <String, String>{'value': 'android'});
-    expect(binding.reassembled, 6);
+    expect(binding.reassembled, 7);
     expect(defaultTargetPlatform, TargetPlatform.android);
-    expect(extensionChangedEvents.length, 6);
+    expect(extensionChangedEvents.length, 7);
     extensionChangedEvent = extensionChangedEvents.last;
     expect(extensionChangedEvent['extension'], 'ext.flutter.platformOverride');
     expect(extensionChangedEvent['value'], 'android');
diff --git a/packages/flutter/test/material/app_bar_test.dart b/packages/flutter/test/material/app_bar_test.dart
index fe8e7fa..3f8cd34 100644
--- a/packages/flutter/test/material/app_bar_test.dart
+++ b/packages/flutter/test/material/app_bar_test.dart
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter/services.dart';
@@ -83,66 +84,68 @@
     Size size = tester.getSize(title);
     expect(center.dx, lessThan(400 - size.width / 2.0));
 
-    // Clear the widget tree to avoid animating between Android and iOS.
-    await tester.pumpWidget(Container(key: UniqueKey()));
+    for (final TargetPlatform platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
+      // Clear the widget tree to avoid animating between platforms.
+      await tester.pumpWidget(Container(key: UniqueKey()));
 
-    await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: Scaffold(
-          appBar: AppBar(
-            title: const Text('X'),
+      await tester.pumpWidget(
+        MaterialApp(
+          theme: ThemeData(platform: platform),
+          home: Scaffold(
+            appBar: AppBar(
+              title: const Text('X'),
+            ),
           ),
         ),
-      ),
-    );
+      );
 
-    center = tester.getCenter(title);
-    size = tester.getSize(title);
-    expect(center.dx, greaterThan(400 - size.width / 2.0));
-    expect(center.dx, lessThan(400 + size.width / 2.0));
+      center = tester.getCenter(title);
+      size = tester.getSize(title);
+      expect(center.dx, greaterThan(400 - size.width / 2.0), reason: 'on ${describeEnum(platform)}');
+      expect(center.dx, lessThan(400 + size.width / 2.0), reason: 'on ${describeEnum(platform)}');
 
-    // One action is still centered.
+      // One action is still centered.
 
-    await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: Scaffold(
-          appBar: AppBar(
-            title: const Text('X'),
-            actions: const <Widget>[
-              Icon(Icons.thumb_up),
-            ],
+      await tester.pumpWidget(
+        MaterialApp(
+          theme: ThemeData(platform: platform),
+          home: Scaffold(
+            appBar: AppBar(
+              title: const Text('X'),
+              actions: const <Widget>[
+                Icon(Icons.thumb_up),
+              ],
+            ),
           ),
         ),
-      ),
-    );
+      );
 
-    center = tester.getCenter(title);
-    size = tester.getSize(title);
-    expect(center.dx, greaterThan(400 - size.width / 2.0));
-    expect(center.dx, lessThan(400 + size.width / 2.0));
+      center = tester.getCenter(title);
+      size = tester.getSize(title);
+      expect(center.dx, greaterThan(400 - size.width / 2.0), reason: 'on ${describeEnum(platform)}');
+      expect(center.dx, lessThan(400 + size.width / 2.0), reason: 'on ${describeEnum(platform)}');
 
-    // Two actions is left aligned again.
+      // Two actions is left aligned again.
 
-    await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: Scaffold(
-          appBar: AppBar(
-            title: const Text('X'),
-            actions: const <Widget>[
-              Icon(Icons.thumb_up),
-              Icon(Icons.thumb_up),
-            ],
+      await tester.pumpWidget(
+        MaterialApp(
+          theme: ThemeData(platform: platform),
+          home: Scaffold(
+            appBar: AppBar(
+              title: const Text('X'),
+              actions: const <Widget>[
+                Icon(Icons.thumb_up),
+                Icon(Icons.thumb_up),
+              ],
+            ),
           ),
         ),
-      ),
-    );
+      );
 
-    center = tester.getCenter(title);
-    size = tester.getSize(title);
-    expect(center.dx, lessThan(400 - size.width / 2.0));
+      center = tester.getCenter(title);
+      size = tester.getSize(title);
+      expect(center.dx, lessThan(400 - size.width / 2.0), reason: 'on ${describeEnum(platform)}');
+    }
   });
 
   testWidgets('AppBar centerTitle:true centers on Android', (WidgetTester tester) async {
diff --git a/packages/flutter/test/material/app_builder_test.dart b/packages/flutter/test/material/app_builder_test.dart
index c25825a..c174f47 100644
--- a/packages/flutter/test/material/app_builder_test.dart
+++ b/packages/flutter/test/material/app_builder_test.dart
@@ -17,7 +17,7 @@
         log.add('build');
         expect(Theme.of(context).primaryColor, Colors.green);
         expect(Directionality.of(context), TextDirection.ltr);
-        expect(child, isInstanceOf<Navigator>());
+        expect(child, isA<Navigator>());
         return const Placeholder();
       },
     );
diff --git a/packages/flutter/test/material/app_test.dart b/packages/flutter/test/material/app_test.dart
index b8c2a8d..5aaf52d 100644
--- a/packages/flutter/test/material/app_test.dart
+++ b/packages/flutter/test/material/app_test.dart
@@ -322,7 +322,7 @@
       ),
     );
     final dynamic exception = tester.takeException();
-    expect(exception is String, isTrue);
+    expect(exception, isA<String>());
     expect(exception.startsWith('Could not navigate to initial route.'), isTrue);
     expect(find.text('route "/"'), findsOneWidget);
     expect(find.text('route "/a"'), findsNothing);
@@ -474,7 +474,7 @@
       color: const Color(0xFF112233),
       home: const Placeholder(),
     ));
-    expect(key.currentState, isInstanceOf<NavigatorState>());
+    expect(key.currentState, isA<NavigatorState>());
     await tester.pumpWidget(const MaterialApp(
       color: Color(0xFF112233),
       home: Placeholder(),
@@ -485,7 +485,7 @@
       color: const Color(0xFF112233),
       home: const Placeholder(),
     ));
-    expect(key.currentState, isInstanceOf<NavigatorState>());
+    expect(key.currentState, isA<NavigatorState>());
   });
 
   testWidgets('Has default material and cupertino localizations', (WidgetTester tester) async {
diff --git a/packages/flutter/test/material/back_button_test.dart b/packages/flutter/test/material/back_button_test.dart
index 767767e..aeb8577 100644
--- a/packages/flutter/test/material/back_button_test.dart
+++ b/packages/flutter/test/material/back_button_test.dart
@@ -66,29 +66,37 @@
   });
 
   testWidgets('BackButton icon', (WidgetTester tester) async {
-    final Key iOSKey = UniqueKey();
     final Key androidKey = UniqueKey();
+    final Key iOSKey = UniqueKey();
+    final Key macOSKey = UniqueKey();
 
     await tester.pumpWidget(
       MaterialApp(
         home: Column(
           children: <Widget>[
             Theme(
+              data: ThemeData(platform: TargetPlatform.android),
+              child: BackButtonIcon(key: androidKey),
+            ),
+            Theme(
               data: ThemeData(platform: TargetPlatform.iOS),
               child: BackButtonIcon(key: iOSKey),
             ),
             Theme(
-              data: ThemeData(platform: TargetPlatform.android),
-              child: BackButtonIcon(key: androidKey),
+              data: ThemeData(platform: TargetPlatform.macOS),
+              child: BackButtonIcon(key: macOSKey),
             ),
           ],
         ),
       ),
     );
 
-    final Icon iOSIcon = tester.widget(find.descendant(of: find.byKey(iOSKey), matching: find.byType(Icon)));
     final Icon androidIcon = tester.widget(find.descendant(of: find.byKey(androidKey), matching: find.byType(Icon)));
-    expect(iOSIcon == androidIcon, false);
+    final Icon iOSIcon = tester.widget(find.descendant(of: find.byKey(iOSKey), matching: find.byType(Icon)));
+    final Icon macOSIcon = tester.widget(find.descendant(of: find.byKey(macOSKey), matching: find.byType(Icon)));
+    expect(iOSIcon.icon == androidIcon.icon, isFalse);
+    expect(macOSIcon.icon == androidIcon.icon, isFalse);
+    expect(macOSIcon.icon == iOSIcon.icon, isTrue);
   });
 
   testWidgets('BackButton color', (WidgetTester tester) async {
diff --git a/packages/flutter/test/material/bottom_navigation_bar_test.dart b/packages/flutter/test/material/bottom_navigation_bar_test.dart
index 51a9793..a3a2b89 100644
--- a/packages/flutter/test/material/bottom_navigation_bar_test.dart
+++ b/packages/flutter/test/material/bottom_navigation_bar_test.dart
@@ -1449,7 +1449,7 @@
           ),
         ),
       );
-    }, throwsA(isInstanceOf<AssertionError>()));
+    }, throwsAssertionError);
   });
 
   testWidgets(
diff --git a/packages/flutter/test/material/chip_theme_test.dart b/packages/flutter/test/material/chip_theme_test.dart
index e1f4fb1..db0b0f3 100644
--- a/packages/flutter/test/material/chip_theme_test.dart
+++ b/packages/flutter/test/material/chip_theme_test.dart
@@ -184,7 +184,7 @@
     expect(lightTheme.secondarySelectedColor, equals(customColor1.withAlpha(0x3d)));
     expect(lightTheme.labelPadding, equals(const EdgeInsets.symmetric(horizontal: 8.0)));
     expect(lightTheme.padding, equals(const EdgeInsets.all(4.0)));
-    expect(lightTheme.shape, equals(isInstanceOf<StadiumBorder>()));
+    expect(lightTheme.shape, isA<StadiumBorder>());
     expect(lightTheme.labelStyle.color, equals(Colors.black.withAlpha(0xde)));
     expect(lightTheme.secondaryLabelStyle.color, equals(customColor1.withAlpha(0xde)));
     expect(lightTheme.brightness, equals(Brightness.light));
@@ -202,7 +202,7 @@
     expect(darkTheme.secondarySelectedColor, equals(customColor1.withAlpha(0x3d)));
     expect(darkTheme.labelPadding, equals(const EdgeInsets.symmetric(horizontal: 8.0)));
     expect(darkTheme.padding, equals(const EdgeInsets.all(4.0)));
-    expect(darkTheme.shape, equals(isInstanceOf<StadiumBorder>()));
+    expect(darkTheme.shape, isA<StadiumBorder>());
     expect(darkTheme.labelStyle.color, equals(Colors.white.withAlpha(0xde)));
     expect(darkTheme.secondaryLabelStyle.color, equals(customColor1.withAlpha(0xde)));
     expect(darkTheme.brightness, equals(Brightness.dark));
@@ -220,7 +220,7 @@
     expect(customTheme.secondarySelectedColor, equals(customColor2.withAlpha(0x3d)));
     expect(customTheme.labelPadding, equals(const EdgeInsets.symmetric(horizontal: 8.0)));
     expect(customTheme.padding, equals(const EdgeInsets.all(4.0)));
-    expect(customTheme.shape, equals(isInstanceOf<StadiumBorder>()));
+    expect(customTheme.shape, isA<StadiumBorder>());
     expect(customTheme.labelStyle.color, equals(customColor1.withAlpha(0xde)));
     expect(customTheme.secondaryLabelStyle.color, equals(customColor2.withAlpha(0xde)));
     expect(customTheme.brightness, equals(Brightness.light));
@@ -263,7 +263,7 @@
     expect(lerp.selectedShadowColor, equals(middleGrey));
     expect(lerp.labelPadding, equals(const EdgeInsets.all(4.0)));
     expect(lerp.padding, equals(const EdgeInsets.all(3.0)));
-    expect(lerp.shape, equals(isInstanceOf<StadiumBorder>()));
+    expect(lerp.shape, isA<StadiumBorder>());
     expect(lerp.labelStyle.color, equals(middleGrey.withAlpha(0xde)));
     expect(lerp.secondaryLabelStyle.color, equals(middleGrey.withAlpha(0xde)));
     expect(lerp.brightness, equals(Brightness.light));
@@ -283,7 +283,7 @@
     expect(lerpANull25.selectedShadowColor, equals(Colors.white.withAlpha(0x40)));
     expect(lerpANull25.labelPadding, equals(const EdgeInsets.only(left: 0.0, top: 2.0, right: 0.0, bottom: 2.0)));
     expect(lerpANull25.padding, equals(const EdgeInsets.all(0.5)));
-    expect(lerpANull25.shape, equals(isInstanceOf<StadiumBorder>()));
+    expect(lerpANull25.shape, isA<StadiumBorder>());
     expect(lerpANull25.labelStyle.color, equals(Colors.black.withAlpha(0x38)));
     expect(lerpANull25.secondaryLabelStyle.color, equals(Colors.white.withAlpha(0x38)));
     expect(lerpANull25.brightness, equals(Brightness.light));
@@ -301,7 +301,7 @@
     expect(lerpANull75.selectedShadowColor, equals(Colors.white.withAlpha(0xbf)));
     expect(lerpANull75.labelPadding, equals(const EdgeInsets.only(left: 0.0, top: 6.0, right: 0.0, bottom: 6.0)));
     expect(lerpANull75.padding, equals(const EdgeInsets.all(1.5)));
-    expect(lerpANull75.shape, equals(isInstanceOf<StadiumBorder>()));
+    expect(lerpANull75.shape, isA<StadiumBorder>());
     expect(lerpANull75.labelStyle.color, equals(Colors.black.withAlpha(0xa7)));
     expect(lerpANull75.secondaryLabelStyle.color, equals(Colors.white.withAlpha(0xa7)));
     expect(lerpANull75.brightness, equals(Brightness.light));
@@ -319,7 +319,7 @@
     expect(lerpBNull25.selectedShadowColor, equals(Colors.black.withAlpha(0xbf)));
     expect(lerpBNull25.labelPadding, equals(const EdgeInsets.only(left: 6.0, top: 0.0, right: 6.0, bottom: 0.0)));
     expect(lerpBNull25.padding, equals(const EdgeInsets.all(3.0)));
-    expect(lerpBNull25.shape, equals(isInstanceOf<StadiumBorder>()));
+    expect(lerpBNull25.shape, isA<StadiumBorder>());
     expect(lerpBNull25.labelStyle.color, equals(Colors.white.withAlpha(0xa7)));
     expect(lerpBNull25.secondaryLabelStyle.color, equals(Colors.black.withAlpha(0xa7)));
     expect(lerpBNull25.brightness, equals(Brightness.dark));
@@ -337,7 +337,7 @@
     expect(lerpBNull75.selectedShadowColor, equals(Colors.black.withAlpha(0x40)));
     expect(lerpBNull75.labelPadding, equals(const EdgeInsets.only(left: 2.0, top: 0.0, right: 2.0, bottom: 0.0)));
     expect(lerpBNull75.padding, equals(const EdgeInsets.all(1.0)));
-    expect(lerpBNull75.shape, equals(isInstanceOf<StadiumBorder>()));
+    expect(lerpBNull75.shape, isA<StadiumBorder>());
     expect(lerpBNull75.labelStyle.color, equals(Colors.white.withAlpha(0x38)));
     expect(lerpBNull75.secondaryLabelStyle.color, equals(Colors.black.withAlpha(0x38)));
     expect(lerpBNull75.brightness, equals(Brightness.light));
diff --git a/packages/flutter/test/material/debug_test.dart b/packages/flutter/test/material/debug_test.dart
index 0874371..23d507b 100644
--- a/packages/flutter/test/material/debug_test.dart
+++ b/packages/flutter/test/material/debug_test.dart
@@ -22,8 +22,8 @@
         'Card, Dialog, Drawer, or Scaffold.\n',
       ),
     );
-    expect(error.diagnostics[3], isInstanceOf<DiagnosticsProperty<Element>>());
-    expect(error.diagnostics[4], isInstanceOf<DiagnosticsBlock>());
+    expect(error.diagnostics[3], isA<DiagnosticsProperty<Element>>());
+    expect(error.diagnostics[4], isA<DiagnosticsBlock>());
     expect(error.toStringDeep(),
       'FlutterError\n'
       '   No Material widget found.\n'
@@ -60,8 +60,8 @@
         'add a Localization widget with a MaterialLocalizations delegate.\n',
       ),
     );
-    expect(error.diagnostics[4], isInstanceOf<DiagnosticsProperty<Element>>());
-    expect(error.diagnostics[5], isInstanceOf<DiagnosticsBlock>());
+    expect(error.diagnostics[4], isA<DiagnosticsProperty<Element>>());
+    expect(error.diagnostics[5], isA<DiagnosticsBlock>());
     expect(error.toStringDeep(),
       'FlutterError\n'
       '   No MaterialLocalizations found.\n'
@@ -97,8 +97,8 @@
     expect(exception, isFlutterError);
     final FlutterError error = exception as FlutterError;
     expect(error.diagnostics.length, 5);
-    expect(error.diagnostics[2], isInstanceOf<DiagnosticsProperty<Element>>());
-    expect(error.diagnostics[3], isInstanceOf<DiagnosticsBlock>());
+    expect(error.diagnostics[2], isA<DiagnosticsProperty<Element>>());
+    expect(error.diagnostics[3], isA<DiagnosticsBlock>());
     expect(error.diagnostics[4].level, DiagnosticLevel.hint);
     expect(
       error.diagnostics[4].toStringDeep(),
diff --git a/packages/flutter/test/material/drawer_test.dart b/packages/flutter/test/material/drawer_test.dart
index 131291b..765373e 100644
--- a/packages/flutter/test/material/drawer_test.dart
+++ b/packages/flutter/test/material/drawer_test.dart
@@ -57,9 +57,8 @@
     expect(find.text('header'), findsOneWidget);
   });
 
-  testWidgets('Drawer dismiss barrier has label on iOS', (WidgetTester tester) async {
+  testWidgets('Drawer dismiss barrier has label', (WidgetTester tester) async {
     final SemanticsTester semantics = SemanticsTester(tester);
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     await tester.pumpWidget(
       const MaterialApp(
         home: Scaffold(
@@ -80,10 +79,9 @@
     ));
 
     semantics.dispose();
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('Drawer dismiss barrier has no label on Android', (WidgetTester tester) async {
+  testWidgets('Drawer dismiss barrier has no label', (WidgetTester tester) async {
     final SemanticsTester semantics = SemanticsTester(tester);
     await tester.pumpWidget(
       const MaterialApp(
@@ -105,7 +103,7 @@
     )));
 
     semantics.dispose();
-  });
+  }, variant: TargetPlatformVariant.only(TargetPlatform.android));
 
   testWidgets('Scaffold drawerScrimColor', (WidgetTester tester) async {
     // The scrim is a Container within a Semantics node labeled "Dismiss",
diff --git a/packages/flutter/test/material/expansion_tile_test.dart b/packages/flutter/test/material/expansion_tile_test.dart
index bd4f8b0..90e9347 100644
--- a/packages/flutter/test/material/expansion_tile_test.dart
+++ b/packages/flutter/test/material/expansion_tile_test.dart
@@ -58,7 +58,6 @@
 
     await tester.pumpWidget(MaterialApp(
       theme: ThemeData(
-        platform: TargetPlatform.iOS,
         dividerColor: _dividerColor,
       ),
       home: Material(
@@ -154,7 +153,7 @@
     expect(collapsedContainerDecoration.color, Colors.transparent);
     expect(collapsedContainerDecoration.border.top.color, _dividerColor);
     expect(collapsedContainerDecoration.border.bottom.color, _dividerColor);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('ListTileTheme', (WidgetTester tester) async {
     final Key expandedTitleKey = UniqueKey();
@@ -165,7 +164,6 @@
     await tester.pumpWidget(
       MaterialApp(
         theme: ThemeData(
-          platform: TargetPlatform.iOS,
           accentColor: _accentColor,
           unselectedWidgetColor: _unselectedWidgetColor,
           textTheme: const TextTheme(subtitle1: TextStyle(color: _headerColor)),
@@ -214,7 +212,7 @@
     expect(textColor(collapsedTitleKey), _accentColor);
     expect(iconColor(expandedIconKey), _unselectedWidgetColor);
     expect(iconColor(collapsedIconKey), _accentColor);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('ExpansionTile subtitle', (WidgetTester tester) async {
     await tester.pumpWidget(
diff --git a/packages/flutter/test/material/flexible_space_bar_collapse_mode_test.dart b/packages/flutter/test/material/flexible_space_bar_collapse_mode_test.dart
index 029e191..d31086d 100644
--- a/packages/flutter/test/material/flexible_space_bar_collapse_mode_test.dart
+++ b/packages/flutter/test/material/flexible_space_bar_collapse_mode_test.dart
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 
@@ -10,10 +11,10 @@
 final Key appbarContainerKey = UniqueKey();
 
 void main() {
-  testWidgets('FlexibleSpaceBar collapse mode none on Android', (WidgetTester tester) async {
+  testWidgets('FlexibleSpaceBar collapse mode none', (WidgetTester tester) async {
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.android),
+        theme: ThemeData(platform: debugDefaultTargetPlatformOverride),
         home: Scaffold(
           body: CustomScrollView(
             key: blockKey,
@@ -46,50 +47,12 @@
 
     expect(topBeforeScroll.dy, equals(0.0));
     expect(topAfterScroll.dy, equals(0.0));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('FlexibleSpaceBar collapse mode none on IOS', (WidgetTester tester) async {
+  testWidgets('FlexibleSpaceBar collapse mode pin', (WidgetTester tester) async {
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: Scaffold(
-          body: CustomScrollView(
-            key: blockKey,
-            slivers: <Widget>[
-              SliverAppBar(
-                expandedHeight: expandedAppbarHeight,
-                pinned: true,
-                flexibleSpace: FlexibleSpaceBar(
-                  background: Container(
-                    key: appbarContainerKey,
-                  ),
-                  collapseMode: CollapseMode.none,
-                ),
-              ),
-              SliverToBoxAdapter(
-                child: Container(
-                  height: 10000.0,
-                ),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-
-    final Finder appbarContainer = find.byKey(appbarContainerKey);
-    final Offset topBeforeScroll = tester.getTopLeft(appbarContainer);
-    await slowDrag(tester, blockKey, const Offset(0.0, -100.0));
-    final Offset topAfterScroll = tester.getTopLeft(appbarContainer);
-
-    expect(topBeforeScroll.dy, equals(0.0));
-    expect(topAfterScroll.dy, equals(0.0));
-  });
-
-  testWidgets('FlexibleSpaceBar collapse mode pin on Android', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.android),
+        theme: ThemeData(platform: debugDefaultTargetPlatformOverride),
         home: Scaffold(
           body: CustomScrollView(
             key: blockKey,
@@ -122,52 +85,12 @@
 
     expect(topBeforeScroll.dy, equals(0.0));
     expect(topAfterScroll.dy, equals(-100.0));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('FlexibleSpaceBar collapse mode pin on IOS', (WidgetTester tester) async {
+  testWidgets('FlexibleSpaceBar collapse mode parallax', (WidgetTester tester) async {
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: Scaffold(
-          body: CustomScrollView(
-            key: blockKey,
-            slivers: <Widget>[
-              SliverAppBar(
-                expandedHeight: expandedAppbarHeight,
-                pinned: true,
-                flexibleSpace: FlexibleSpaceBar(
-                  background: Container(
-                    key: appbarContainerKey,
-                  ),
-                  collapseMode: CollapseMode.pin,
-                ),
-              ),
-              SliverToBoxAdapter(
-                child: Container(
-                  height: 10000.0,
-                ),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-
-    final Finder appbarContainer = find.byKey(appbarContainerKey);
-    final Offset topBeforeScroll = tester.getTopLeft(appbarContainer);
-    await slowDrag(tester, blockKey, const Offset(0.0, -100.0));
-    final Offset topAfterScroll = tester.getTopLeft(appbarContainer);
-
-    expect(topBeforeScroll.dy, equals(0.0));
-    expect(topAfterScroll.dy, equals(-100.0));
-  });
-
-
-
-  testWidgets('FlexibleSpaceBar collapse mode parallax on Android', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.android),
+        theme: ThemeData(platform: debugDefaultTargetPlatformOverride),
         home: Scaffold(
           body: CustomScrollView(
             key: blockKey,
@@ -201,46 +124,7 @@
     expect(topBeforeScroll.dy, equals(0.0));
     expect(topAfterScroll.dy, lessThan(10.0));
     expect(topAfterScroll.dy, greaterThan(-50.0));
-  });
-
-  testWidgets('FlexibleSpaceBar collapse mode parallax on IOS', (WidgetTester tester) async {
-    await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: Scaffold(
-          body: CustomScrollView(
-            key: blockKey,
-            slivers: <Widget>[
-              SliverAppBar(
-                expandedHeight: expandedAppbarHeight,
-                pinned: true,
-                flexibleSpace: FlexibleSpaceBar(
-                  background: Container(
-                    key: appbarContainerKey,
-                  ),
-                  collapseMode: CollapseMode.parallax,
-                ),
-              ),
-              SliverToBoxAdapter(
-                child: Container(
-                  height: 10000.0,
-                ),
-              ),
-            ],
-          ),
-        ),
-      ),
-    );
-
-    final Finder appbarContainer = find.byKey(appbarContainerKey);
-    final Offset topBeforeScroll = tester.getTopLeft(appbarContainer);
-    await slowDrag(tester, blockKey, const Offset(0.0, -100.0));
-    final Offset topAfterScroll = tester.getTopLeft(appbarContainer);
-
-    expect(topBeforeScroll.dy, equals(0.0));
-    expect(topAfterScroll.dy, lessThan(10.0));
-    expect(topAfterScroll.dy, greaterThan(-50.0));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.iOS,  TargetPlatform.macOS }));
 }
 
 Future<void> slowDrag(WidgetTester tester, Key widget, Offset offset) async {
diff --git a/packages/flutter/test/material/flexible_space_bar_test.dart b/packages/flutter/test/material/flexible_space_bar_test.dart
index 83bff20..c8ac872 100644
--- a/packages/flutter/test/material/flexible_space_bar_test.dart
+++ b/packages/flutter/test/material/flexible_space_bar_test.dart
@@ -25,26 +25,28 @@
     Size size = tester.getSize(title);
     expect(center.dx, lessThan(400.0 - size.width / 2.0));
 
-    // Clear the widget tree to avoid animating between Android and iOS.
-    await tester.pumpWidget(Container(key: UniqueKey()));
+    for (final TargetPlatform platform in <TargetPlatform>[ TargetPlatform.iOS, TargetPlatform.macOS ]) {
+      // Clear the widget tree to avoid animating between platforms.
+      await tester.pumpWidget(Container(key: UniqueKey()));
 
-    await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: Scaffold(
-          appBar: AppBar(
-            flexibleSpace: const FlexibleSpaceBar(
-              title: Text('X'),
+      await tester.pumpWidget(
+        MaterialApp(
+          theme: ThemeData(platform: platform),
+          home: Scaffold(
+            appBar: AppBar(
+              flexibleSpace: const FlexibleSpaceBar(
+                title: Text('X'),
+              ),
             ),
           ),
         ),
-      ),
-    );
+      );
 
-    center = tester.getCenter(title);
-    size = tester.getSize(title);
-    expect(center.dx, greaterThan(400.0 - size.width / 2.0));
-    expect(center.dx, lessThan(400.0 + size.width / 2.0));
+      center = tester.getCenter(title);
+      size = tester.getSize(title);
+      expect(center.dx, greaterThan(400.0 - size.width / 2.0));
+      expect(center.dx, lessThan(400.0 + size.width / 2.0));
+    }
   });
 
   testWidgets('FlexibleSpaceBarSettings provides settings to a FlexibleSpaceBar', (WidgetTester tester) async {
@@ -154,6 +156,15 @@
     await tester.pumpWidget(buildFrame(TargetPlatform.iOS, false));
     expect(getTitleBottomLeft(), const Offset(72.0, 16.0));
 
+    // Clear the widget tree to avoid animating between iOS and macOS.
+    await tester.pumpWidget(Container(key: UniqueKey()));
+
+    await tester.pumpWidget(buildFrame(TargetPlatform.macOS, null));
+    expect(getTitleBottomLeft(), const Offset(390.0, 16.0));
+
+    await tester.pumpWidget(buildFrame(TargetPlatform.macOS, false));
+    expect(getTitleBottomLeft(), const Offset(72.0, 16.0));
+
   }, skip: isBrowser);
 
   testWidgets('FlexibleSpaceBar test titlePadding override', (WidgetTester tester) async {
@@ -195,6 +206,15 @@
 
     await tester.pumpWidget(buildFrame(TargetPlatform.iOS, false));
     expect(getTitleBottomLeft(), Offset.zero);
+
+    // Clear the widget tree to avoid animating between iOS and macOS.
+    await tester.pumpWidget(Container(key: UniqueKey()));
+
+    await tester.pumpWidget(buildFrame(TargetPlatform.macOS, null));
+    expect(getTitleBottomLeft(), const Offset(390.0, 0.0));
+
+    await tester.pumpWidget(buildFrame(TargetPlatform.macOS, false));
+    expect(getTitleBottomLeft(), Offset.zero);
   }, skip: isBrowser);
 }
 
diff --git a/packages/flutter/test/material/outline_button_test.dart b/packages/flutter/test/material/outline_button_test.dart
index e6debab..a61baf9 100644
--- a/packages/flutter/test/material/outline_button_test.dart
+++ b/packages/flutter/test/material/outline_button_test.dart
@@ -1047,7 +1047,7 @@
     object = object.parent as RenderObject;
   }
   expect(object.debugLayer, isNotNull);
-  expect(object.debugLayer.firstChild, isInstanceOf<PhysicalModelLayer>());
+  expect(object.debugLayer.firstChild, isA<PhysicalModelLayer>());
   final PhysicalModelLayer layer = object.debugLayer.firstChild as PhysicalModelLayer;
   final Layer child = layer.firstChild;
   return child is PhysicalModelLayer ? child : layer;
diff --git a/packages/flutter/test/material/page_test.dart b/packages/flutter/test/material/page_test.dart
index 47fbded..9f342ee 100644
--- a/packages/flutter/test/material/page_test.dart
+++ b/packages/flutter/test/material/page_test.dart
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/cupertino.dart' show CupertinoPageRoute;
 import 'package:flutter/rendering.dart';
@@ -10,10 +11,9 @@
 import '../rendering/mock_canvas.dart';
 
 void main() {
-  testWidgets('test Android page transition', (WidgetTester tester) async {
+  testWidgets('test page transition', (WidgetTester tester) async {
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.android),
         home: const Material(child: Text('Page 1')),
         routes: <String, WidgetBuilder>{
           '/next': (BuildContext context) {
@@ -66,13 +66,12 @@
 
     expect(find.text('Page 1'), isOnstage);
     expect(find.text('Page 2'), findsNothing);
-  });
+  }, variant: TargetPlatformVariant.only(TargetPlatform.android));
 
-  testWidgets('test iOS page transition', (WidgetTester tester) async {
+  testWidgets('test page transition', (WidgetTester tester) async {
     final Key page2Key = UniqueKey();
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         home: const Material(child: Text('Page 1')),
         routes: <String, WidgetBuilder>{
           '/next': (BuildContext context) {
@@ -145,13 +144,12 @@
 
     // Page 1 is back where it started.
     expect(widget1InitialTopLeft == widget1TransientTopLeft, true);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
 
-  testWidgets('test iOS fullscreen dialog transition', (WidgetTester tester) async {
+  testWidgets('test fullscreen dialog transition', (WidgetTester tester) async {
     await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: const Material(child: Text('Page 1')),
+      const MaterialApp(
+        home: Material(child: Text('Page 1')),
       ),
     );
 
@@ -206,12 +204,11 @@
 
     // Page 1 is back where it started.
     expect(widget1InitialTopLeft == widget1TransientTopLeft, true);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
 
   testWidgets('test no back gesture on Android', (WidgetTester tester) async {
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.android),
         home: const Scaffold(body: Text('Page 1')),
         routes: <String, WidgetBuilder>{
           '/next': (BuildContext context) {
@@ -237,12 +234,11 @@
 
     // Page 2 didn't move
     expect(tester.getTopLeft(find.text('Page 2')), Offset.zero);
-  });
+  }, variant: TargetPlatformVariant.only(TargetPlatform.android));
 
-  testWidgets('test back gesture on iOS', (WidgetTester tester) async {
+  testWidgets('test back gesture', (WidgetTester tester) async {
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         home: const Scaffold(body: Text('Page 1')),
         routes: <String, WidgetBuilder>{
           '/next': (BuildContext context) {
@@ -279,7 +275,7 @@
     await tester.pump();
 
     expect(tester.getTopLeft(find.text('Page 2')), const Offset(100.0, 0.0));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
 
   testWidgets('back gesture while OS changes', (WidgetTester tester) async {
     final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
@@ -346,13 +342,36 @@
     expect(await tester.pumpAndSettle(const Duration(minutes: 1)), 3);
     expect(find.text('PUSH'), findsOneWidget);
     expect(find.text('HELLO'), findsNothing);
-  });
 
-  testWidgets('test no back gesture on iOS fullscreen dialogs', (WidgetTester tester) async {
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: const Scaffold(body: Text('Page 1')),
+        theme: ThemeData(platform: TargetPlatform.macOS),
+        routes: routes,
+      ),
+    );
+    await tester.tap(find.text('PUSH'));
+    expect(await tester.pumpAndSettle(const Duration(minutes: 1)), 2);
+    expect(find.text('PUSH'), findsNothing);
+    expect(find.text('HELLO'), findsOneWidget);
+    final Offset helloPosition5 = tester.getCenter(find.text('HELLO'));
+    await gesture.down(const Offset(2.5, 300.0));
+    await tester.pump(const Duration(milliseconds: 20));
+    await gesture.moveBy(const Offset(100.0, 0.0));
+    expect(find.text('PUSH'), findsNothing);
+    expect(find.text('HELLO'), findsOneWidget);
+    await tester.pump(const Duration(milliseconds: 20));
+    expect(find.text('PUSH'), findsOneWidget);
+    expect(find.text('HELLO'), findsOneWidget);
+    final Offset helloPosition6 = tester.getCenter(find.text('HELLO'));
+    expect(helloPosition5.dx, lessThan(helloPosition6.dx));
+    expect(helloPosition5.dy, helloPosition6.dy);
+    expect(Theme.of(tester.element(find.text('HELLO'))).platform, TargetPlatform.macOS);
+  });
+
+  testWidgets('test no back gesture on fullscreen dialogs', (WidgetTester tester) async {
+    await tester.pumpWidget(
+      const MaterialApp(
+        home: Scaffold(body: Text('Page 1')),
       ),
     );
 
@@ -377,7 +396,7 @@
 
     // Page 2 didn't move
     expect(tester.getTopLeft(find.text('Page 2')), Offset.zero);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('test adaptable transitions switch during execution', (WidgetTester tester) async {
     await tester.pumpWidget(
@@ -417,7 +436,6 @@
     // Re-pump the same app but with iOS instead of Android.
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         home: const Material(child: Text('Page 1')),
         routes: <String, WidgetBuilder>{
           '/next': (BuildContext context) {
@@ -452,7 +470,7 @@
 
     // Page 1 is back where it started.
     expect(widget1InitialTopLeft == widget1TransientTopLeft, true);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('throws when builder returns null', (WidgetTester tester) async {
     await tester.pumpWidget(const MaterialApp(
@@ -470,7 +488,7 @@
     await tester.pumpAndSettle();
     // An exception should've been thrown because the `builder` returned null.
     final dynamic exception = tester.takeException();
-    expect(exception, isInstanceOf<FlutterError>());
+    expect(exception, isFlutterError);
     expect(exception.toStringDeep(), equalsIgnoringHashCodes(
       'FlutterError\n'
       '   The builder for route "broken" returned null.\n'
@@ -478,10 +496,9 @@
     ));
   });
 
-  testWidgets('test iOS edge swipe then drop back at starting point works', (WidgetTester tester) async {
+  testWidgets('test edge swipe then drop back at starting point works', (WidgetTester tester) async {
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         onGenerateRoute: (RouteSettings settings) {
           return MaterialPageRoute<void>(
             settings: settings,
@@ -512,12 +529,11 @@
 
     expect(find.text('Page 1'), findsNothing);
     expect(find.text('Page 2'), isOnstage);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('test iOS edge swipe then drop back at ending point works', (WidgetTester tester) async {
+  testWidgets('test edge swipe then drop back at ending point works', (WidgetTester tester) async {
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         onGenerateRoute: (RouteSettings settings) {
           return MaterialPageRoute<void>(
             settings: settings,
@@ -546,7 +562,7 @@
 
     expect(find.text('Page 1'), isOnstage);
     expect(find.text('Page 2'), findsNothing);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Back swipe dismiss interrupted by route push', (WidgetTester tester) async {
     // Regression test for https://github.com/flutter/flutter/issues/28728
@@ -554,7 +570,6 @@
 
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         home: Scaffold(
           key: scaffoldKey,
           body: Center(
@@ -642,7 +657,7 @@
     await tester.pumpAndSettle();
     expect(find.text('route'), findsOneWidget);
     expect(find.text('push'), findsNothing);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('During back swipe the route ignores input', (WidgetTester tester) async {
     // Regression test for https://github.com/flutter/flutter/issues/39989
@@ -654,7 +669,6 @@
 
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         home: Scaffold(
           key: homeScaffoldKey,
           body: GestureDetector(
@@ -713,7 +727,7 @@
     await tester.pumpAndSettle();
     expect(tester.getTopLeft(find.byKey(pageScaffoldKey)), const Offset(400, 0));
     expect(tester.getTopLeft(find.byKey(homeScaffoldKey)).dx, lessThan(0));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('After a pop caused by a back-swipe, input reaches the exposed route', (WidgetTester tester) async {
     // Regression test for https://github.com/flutter/flutter/issues/41024
@@ -725,7 +739,6 @@
 
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         home: Scaffold(
           key: homeScaffoldKey,
           body: GestureDetector(
@@ -785,9 +798,9 @@
     await tester.tap(find.byKey(homeScaffoldKey));
     expect(homeTapCount, 2);
     expect(pageTapCount, 1);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('On iOS, a MaterialPageRoute should slide out with CupertinoPageTransition when a compatible PageRoute is pushed on top of it', (WidgetTester tester) async {
+  testWidgets('A MaterialPageRoute should slide out with CupertinoPageTransition when a compatible PageRoute is pushed on top of it', (WidgetTester tester) async {
     // Regression test for https://github.com/flutter/flutter/issues/44864.
 
     await tester.pumpWidget(
@@ -813,5 +826,5 @@
     // Title of the first route slides to the left.
     expect(titleInitialTopLeft.dy, equals(titleTransientTopLeft.dy));
     expect(titleInitialTopLeft.dx, greaterThan(titleTransientTopLeft.dx));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 }
diff --git a/packages/flutter/test/material/page_transitions_theme_test.dart b/packages/flutter/test/material/page_transitions_theme_test.dart
index d1a4c49..920ea1a 100644
--- a/packages/flutter/test/material/page_transitions_theme_test.dart
+++ b/packages/flutter/test/material/page_transitions_theme_test.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter/cupertino.dart';
+import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 
@@ -11,11 +12,16 @@
     await tester.pumpWidget(const MaterialApp(home: Text('home')));
     final PageTransitionsTheme theme = Theme.of(tester.element(find.text('home'))).pageTransitionsTheme;
     expect(theme.builders, isNotNull);
-    expect(theme.builders[TargetPlatform.android], isNotNull);
-    expect(theme.builders[TargetPlatform.iOS], isNotNull);
+    for (final TargetPlatform platform in TargetPlatform.values) {
+      if (platform == TargetPlatform.fuchsia) {
+        // No builder on Fuchsia.
+        continue;
+      }
+      expect(theme.builders[platform], isNotNull, reason: 'theme builder for $platform is null');
+    }
   });
 
-  testWidgets('Default PageTranstionsTheme builds a CupertionPageTransition for iOS', (WidgetTester tester) async {
+  testWidgets('Default PageTranstionsTheme builds a CupertionPageTransition', (WidgetTester tester) async {
     final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
       '/': (BuildContext context) => Material(
         child: FlatButton(
@@ -28,19 +34,18 @@
 
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         routes: routes,
       ),
     );
 
-    expect(Theme.of(tester.element(find.text('push'))).platform, TargetPlatform.iOS);
+    expect(Theme.of(tester.element(find.text('push'))).platform, debugDefaultTargetPlatformOverride);
     expect(find.byType(CupertinoPageTransition), findsOneWidget);
 
     await tester.tap(find.text('push'));
     await tester.pumpAndSettle();
     expect(find.text('page b'), findsOneWidget);
     expect(find.byType(CupertinoPageTransition), findsOneWidget);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Default PageTranstionsTheme builds a _FadeUpwardsPageTransition for android', (WidgetTester tester) async {
     final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
@@ -55,7 +60,6 @@
 
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.android),
         routes: routes,
       ),
     );
@@ -67,16 +71,16 @@
       );
     }
 
-    expect(Theme.of(tester.element(find.text('push'))).platform, TargetPlatform.android);
+    expect(Theme.of(tester.element(find.text('push'))).platform, debugDefaultTargetPlatformOverride);
     expect(findFadeUpwardsPageTransition(), findsOneWidget);
 
     await tester.tap(find.text('push'));
     await tester.pumpAndSettle();
     expect(find.text('page b'), findsOneWidget);
     expect(findFadeUpwardsPageTransition(), findsOneWidget);
-  });
+  }, variant: TargetPlatformVariant.only(TargetPlatform.android));
 
-  testWidgets('pageTranstionsTheme override builds a _OpenUpwardsPageTransition for android', (WidgetTester tester) async {
+  testWidgets('pageTranstionsTheme override builds a _OpenUpwardsPageTransition', (WidgetTester tester) async {
     final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
       '/': (BuildContext context) => Material(
         child: FlatButton(
@@ -90,7 +94,6 @@
     await tester.pumpWidget(
       MaterialApp(
         theme: ThemeData(
-          platform: TargetPlatform.android,
           pageTransitionsTheme: const PageTransitionsTheme(
             builders: <TargetPlatform, PageTransitionsBuilder>{
               TargetPlatform.android: OpenUpwardsPageTransitionsBuilder(), // creates a _OpenUpwardsPageTransition
@@ -108,16 +111,16 @@
       );
     }
 
-    expect(Theme.of(tester.element(find.text('push'))).platform, TargetPlatform.android);
+    expect(Theme.of(tester.element(find.text('push'))).platform, debugDefaultTargetPlatformOverride);
     expect(findOpenUpwardsPageTransition(), findsOneWidget);
 
     await tester.tap(find.text('push'));
     await tester.pumpAndSettle();
     expect(find.text('page b'), findsOneWidget);
     expect(findOpenUpwardsPageTransition(), findsOneWidget);
-  });
+  }, variant: TargetPlatformVariant.only(TargetPlatform.android));
 
-  testWidgets('pageTranstionsTheme override builds a _ZoomPageTransition for android', (WidgetTester tester) async {
+  testWidgets('pageTranstionsTheme override builds a _ZoomPageTransition', (WidgetTester tester) async {
     final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
       '/': (BuildContext context) => Material(
         child: FlatButton(
@@ -131,7 +134,6 @@
     await tester.pumpWidget(
       MaterialApp(
         theme: ThemeData(
-          platform: TargetPlatform.android,
           pageTransitionsTheme: const PageTransitionsTheme(
             builders: <TargetPlatform, PageTransitionsBuilder>{
               TargetPlatform.android: ZoomPageTransitionsBuilder(), // creates a _ZoomPageTransition
@@ -149,12 +151,12 @@
       );
     }
 
-    expect(Theme.of(tester.element(find.text('push'))).platform, TargetPlatform.android);
+    expect(Theme.of(tester.element(find.text('push'))).platform, debugDefaultTargetPlatformOverride);
     expect(findZoomPageTransition(), findsOneWidget);
 
     await tester.tap(find.text('push'));
     await tester.pumpAndSettle();
     expect(find.text('page b'), findsOneWidget);
     expect(findZoomPageTransition(), findsOneWidget);
-  });
+  }, variant: TargetPlatformVariant.only(TargetPlatform.android));
 }
diff --git a/packages/flutter/test/material/paginated_data_table_test.dart b/packages/flutter/test/material/paginated_data_table_test.dart
index 546ce35..d6a6ecd 100644
--- a/packages/flutter/test/material/paginated_data_table_test.dart
+++ b/packages/flutter/test/material/paginated_data_table_test.dart
@@ -164,7 +164,7 @@
 
     // the column overflows because we're forcing it to 600 pixels high
     final dynamic exception = tester.takeException();
-    expect(exception, isInstanceOf<FlutterError>());
+    expect(exception, isFlutterError);
     expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
     expect(exception.diagnostics.first.toString(), startsWith('A RenderFlex overflowed by '));
 
@@ -252,7 +252,7 @@
     ));
     // the column overflows because we're forcing it to 600 pixels high
     final dynamic exception = tester.takeException();
-    expect(exception, isInstanceOf<FlutterError>());
+    expect(exception, isFlutterError);
     expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
     expect(exception.diagnostics.first.toString(), contains('A RenderFlex overflowed by'));
 
diff --git a/packages/flutter/test/material/popup_menu_test.dart b/packages/flutter/test/material/popup_menu_test.dart
index 6a1609f..86cf63d 100644
--- a/packages/flutter/test/material/popup_menu_test.dart
+++ b/packages/flutter/test/material/popup_menu_test.dart
@@ -325,6 +325,12 @@
 
     expect(find.byIcon(Icons.more_vert), findsNothing);
     expect(find.byIcon(Icons.more_horiz), findsOneWidget);
+
+    await tester.pumpWidget(build(TargetPlatform.macOS));
+    await tester.pumpAndSettle(); // Run theme change animation.
+
+    expect(find.byIcon(Icons.more_vert), findsNothing);
+    expect(find.byIcon(Icons.more_horiz), findsOneWidget);
   });
 
   group('PopupMenuButton with Icon', () {
@@ -345,7 +351,7 @@
             icon: const Icon(Icons.view_carousel),
             itemBuilder: simplePopupMenuItemBuilder,
         );
-      }, throwsA(isInstanceOf<AssertionError>()));
+      }, throwsAssertionError);
     });
 
     testWidgets('PopupMenuButton creates IconButton when given an icon', (WidgetTester tester) async {
diff --git a/packages/flutter/test/material/refresh_indicator_test.dart b/packages/flutter/test/material/refresh_indicator_test.dart
index 965c60d..b24097e 100644
--- a/packages/flutter/test/material/refresh_indicator_test.dart
+++ b/packages/flutter/test/material/refresh_indicator_test.dart
@@ -387,8 +387,7 @@
     expect(tester.takeException(), isFlutterError);
   });
 
-  testWidgets('Refresh starts while scroll view moves back to 0.0 after overscroll on iOS', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
+  testWidgets('Refresh starts while scroll view moves back to 0.0 after overscroll', (WidgetTester tester) async {
     refreshCalled = false;
     double lastScrollOffset;
     final ScrollController controller = ScrollController();
@@ -420,7 +419,5 @@
     expect(controller.offset, greaterThan(lastScrollOffset));
     expect(controller.offset, lessThan(0.0));
     expect(refreshCalled, isTrue);
-
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 }
diff --git a/packages/flutter/test/material/scaffold_test.dart b/packages/flutter/test/material/scaffold_test.dart
index a101715..59170ef 100644
--- a/packages/flutter/test/material/scaffold_test.dart
+++ b/packages/flutter/test/material/scaffold_test.dart
@@ -320,17 +320,17 @@
     );
   }
 
-  testWidgets('Tapping the status bar scrolls to top on iOS', (WidgetTester tester) async {
-    await tester.pumpWidget(_buildStatusBarTestApp(TargetPlatform.iOS));
+  testWidgets('Tapping the status bar scrolls to top', (WidgetTester tester) async {
+    await tester.pumpWidget(_buildStatusBarTestApp(debugDefaultTargetPlatformOverride));
     final ScrollableState scrollable = tester.state(find.byType(Scrollable));
     scrollable.position.jumpTo(500.0);
     expect(scrollable.position.pixels, equals(500.0));
     await tester.tapAt(const Offset(100.0, 10.0));
     await tester.pumpAndSettle();
     expect(scrollable.position.pixels, equals(0.0));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('Tapping the status bar does not scroll to top on Android', (WidgetTester tester) async {
+  testWidgets('Tapping the status bar does not scroll to top', (WidgetTester tester) async {
     await tester.pumpWidget(_buildStatusBarTestApp(TargetPlatform.android));
     final ScrollableState scrollable = tester.state(find.byType(Scrollable));
     scrollable.position.jumpTo(500.0);
@@ -339,7 +339,7 @@
     await tester.pump();
     await tester.pump(const Duration(seconds: 1));
     expect(scrollable.position.pixels, equals(500.0));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }));
 
   testWidgets('Bottom sheet cannot overlap app bar', (WidgetTester tester) async {
     final Key sheetKey = UniqueKey();
@@ -506,7 +506,7 @@
   });
 
   group('back arrow', () {
-    Future<void> expectBackIcon(WidgetTester tester, TargetPlatform platform, IconData expectedIcon) async {
+    Future<void> expectBackIcon(WidgetTester tester, IconData expectedIcon) async {
       final GlobalKey rootKey = GlobalKey();
       final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
         '/': (_) => Container(key: rootKey, child: const Text('Home')),
@@ -515,9 +515,7 @@
             body: const Text('Scaffold'),
         ),
       };
-      await tester.pumpWidget(
-        MaterialApp(theme: ThemeData(platform: platform), routes: routes)
-      );
+      await tester.pumpWidget(MaterialApp(routes: routes));
 
       Navigator.pushNamed(rootKey.currentContext, '/scaffold');
       await tester.pump();
@@ -527,24 +525,20 @@
       expect(icon.icon, expectedIcon);
     }
 
-    testWidgets('Back arrow uses correct default on Android', (WidgetTester tester) async {
-      await expectBackIcon(tester, TargetPlatform.android, Icons.arrow_back);
-    });
+    testWidgets('Back arrow uses correct default', (WidgetTester tester) async {
+      await expectBackIcon(tester, Icons.arrow_back);
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android, TargetPlatform.fuchsia }));
 
-    testWidgets('Back arrow uses correct default on Fuchsia', (WidgetTester tester) async {
-      await expectBackIcon(tester, TargetPlatform.fuchsia, Icons.arrow_back);
-    });
-
-    testWidgets('Back arrow uses correct default on iOS', (WidgetTester tester) async {
-      await expectBackIcon(tester, TargetPlatform.iOS, Icons.arrow_back_ios);
-    });
+    testWidgets('Back arrow uses correct default', (WidgetTester tester) async {
+      await expectBackIcon(tester, Icons.arrow_back_ios);
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
   });
 
   group('close button', () {
-    Future<void> expectCloseIcon(WidgetTester tester, TargetPlatform platform, IconData expectedIcon, PageRoute<void> routeBuilder()) async {
+    Future<void> expectCloseIcon(WidgetTester tester, PageRoute<void> routeBuilder(), String type) async {
+      const IconData expectedIcon = Icons.close;
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: platform),
           home: Scaffold(appBar: AppBar(), body: const Text('Page 1')),
         ),
       );
@@ -555,8 +549,8 @@
       await tester.pump(const Duration(seconds: 1));
 
       final Icon icon = tester.widget(find.byType(Icon));
-      expect(icon.icon, expectedIcon);
-      expect(find.byType(CloseButton), findsOneWidget);
+      expect(icon.icon, expectedIcon, reason: "didn't find close icon for $type");
+      expect(find.byType(CloseButton), findsOneWidget, reason: "didn't find close button for $type");
     }
 
     PageRoute<void> materialRouteBuilder() {
@@ -586,41 +580,17 @@
       );
     }
 
-    testWidgets('Close button shows correctly on Android', (WidgetTester tester) async {
-      await expectCloseIcon(tester, TargetPlatform.android, Icons.close, materialRouteBuilder);
-    });
+    testWidgets('Close button shows correctly', (WidgetTester tester) async {
+      await expectCloseIcon(tester, materialRouteBuilder, 'materialRouteBuilder');
+    }, variant: TargetPlatformVariant.all());
 
-    testWidgets('Close button shows correctly on Fuchsia', (WidgetTester tester) async {
-      await expectCloseIcon(tester, TargetPlatform.fuchsia, Icons.close, materialRouteBuilder);
-    });
+    testWidgets('Close button shows correctly with PageRouteBuilder', (WidgetTester tester) async {
+      await expectCloseIcon(tester, pageRouteBuilder, 'pageRouteBuilder');
+    }, variant: TargetPlatformVariant.all());
 
-    testWidgets('Close button shows correctly on iOS', (WidgetTester tester) async {
-      await expectCloseIcon(tester, TargetPlatform.iOS, Icons.close, materialRouteBuilder);
-    });
-
-    testWidgets('Close button shows correctly with PageRouteBuilder on Android', (WidgetTester tester) async {
-      await expectCloseIcon(tester, TargetPlatform.android, Icons.close, pageRouteBuilder);
-    });
-
-    testWidgets('Close button shows correctly with PageRouteBuilder on Fuchsia', (WidgetTester tester) async {
-      await expectCloseIcon(tester, TargetPlatform.fuchsia, Icons.close, pageRouteBuilder);
-    });
-
-    testWidgets('Close button shows correctly with PageRouteBuilder on iOS', (WidgetTester tester) async {
-      await expectCloseIcon(tester, TargetPlatform.iOS, Icons.close, pageRouteBuilder);
-    });
-
-    testWidgets('Close button shows correctly with custom page route on Android', (WidgetTester tester) async {
-      await expectCloseIcon(tester, TargetPlatform.android, Icons.close, customPageRouteBuilder);
-    });
-
-    testWidgets('Close button shows correctly with custom page route on Fuchsia', (WidgetTester tester) async {
-      await expectCloseIcon(tester, TargetPlatform.fuchsia, Icons.close, customPageRouteBuilder);
-    });
-
-    testWidgets('Close button shows correctly with custom page route on iOS', (WidgetTester tester) async {
-      await expectCloseIcon(tester, TargetPlatform.iOS, Icons.close, customPageRouteBuilder);
-    });
+    testWidgets('Close button shows correctly with custom page route', (WidgetTester tester) async {
+      await expectCloseIcon(tester, customPageRouteBuilder, 'customPageRouteBuilder');
+    }, variant: TargetPlatformVariant.all());
   });
 
   group('body size', () {
@@ -1824,7 +1794,7 @@
           'the ScaffoldState rather than using the Scaffold.of() function.\n',
         ),
       );
-      expect(error.diagnostics[4], isInstanceOf<DiagnosticsProperty<Element>>());
+      expect(error.diagnostics[4], isA<DiagnosticsProperty<Element>>());
       expect(error.toStringDeep(),
         'FlutterError\n'
         '   Scaffold.of() called with a context that does not contain a\n'
@@ -1893,7 +1863,7 @@
           'Scaffold.geometryOf().\n',
         ),
       );
-      expect(error.diagnostics[4], isInstanceOf<DiagnosticsProperty<Element>>());
+      expect(error.diagnostics[4], isA<DiagnosticsProperty<Element>>());
       expect(error.toStringDeep(),
         'FlutterError\n'
         '   Scaffold.geometryOf() called with a context that does not contain\n'
diff --git a/packages/flutter/test/material/scrollbar_test.dart b/packages/flutter/test/material/scrollbar_test.dart
index 1d1edd8..ad92f0d 100644
--- a/packages/flutter/test/material/scrollbar_test.dart
+++ b/packages/flutter/test/material/scrollbar_test.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter/cupertino.dart';
+import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/scheduler.dart';
 import 'package:flutter_test/flutter_test.dart';
@@ -152,6 +153,20 @@
     await tester.drag(find.byType(SingleChildScrollView), const Offset(0.0, -10.0));
     await tester.pump();
     await tester.pump(const Duration(milliseconds: 200));
+    expect(find.byType(Scrollbar), paints..rrect());
+    expect(find.byType(CupertinoScrollbar), paints..rrect());
+    await gesture.up();
+    await tester.pumpAndSettle();
+
+    await tester.pumpWidget(viewWithScroll(TargetPlatform.macOS));
+    await gesture.down(
+      tester.getCenter(find.byType(SingleChildScrollView)),
+    );
+    await gesture.moveBy(const Offset(0.0, -10.0));
+    await tester.drag(find.byType(SingleChildScrollView), const Offset(0.0, -10.0));
+    await tester.pump();
+    await tester.pump(const Duration(milliseconds: 200));
+    expect(find.byType(Scrollbar), paints..rrect());
     expect(find.byType(CupertinoScrollbar), paints..rrect());
   });
 
@@ -173,7 +188,7 @@
       );
     }
 
-    await tester.pumpWidget(viewWithScroll(TargetPlatform.iOS));
+    await tester.pumpWidget(viewWithScroll(debugDefaultTargetPlatformOverride));
     final TestGesture gesture = await tester.startGesture(
       tester.getCenter(find.byType(SingleChildScrollView))
     );
@@ -184,6 +199,6 @@
     expect(find.byType(CupertinoScrollbar), paints..rrect());
     final CupertinoScrollbar scrollbar = find.byType(CupertinoScrollbar).evaluate().first.widget as CupertinoScrollbar;
     expect(scrollbar.controller, isNotNull);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
 }
diff --git a/packages/flutter/test/material/search_test.dart b/packages/flutter/test/material/search_test.dart
index 2c4b705..239db29 100644
--- a/packages/flutter/test/material/search_test.dart
+++ b/packages/flutter/test/material/search_test.dart
@@ -573,7 +573,8 @@
                           SemanticsFlag.isTextField,
                           SemanticsFlag.isFocused,
                           SemanticsFlag.isHeader,
-                          if (debugDefaultTargetPlatformOverride != TargetPlatform.iOS) SemanticsFlag.namesRoute,
+                          if (debugDefaultTargetPlatformOverride != TargetPlatform.iOS &&
+                              debugDefaultTargetPlatformOverride != TargetPlatform.macOS) SemanticsFlag.namesRoute,
                         ],
                         actions: <SemanticsAction>[
                           SemanticsAction.tap,
@@ -622,8 +623,7 @@
       semantics.dispose();
     });
 
-    testWidgets('does not include routeName on iOS', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
+    testWidgets('does not include routeName', (WidgetTester tester) async {
       final SemanticsTester semantics = SemanticsTester(tester);
       final _TestSearchDelegate delegate = _TestSearchDelegate();
       await tester.pumpWidget(TestHomePage(
@@ -636,9 +636,8 @@
       expect(semantics, hasSemantics(buildExpected(routeName: ''),
           ignoreId: true, ignoreRect: true, ignoreTransform: true));
 
-      debugDefaultTargetPlatformOverride = null;
       semantics.dispose();
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
   });
 }
 
diff --git a/packages/flutter/test/material/slider_test.dart b/packages/flutter/test/material/slider_test.dart
index e3f0b4b..96451b0 100644
--- a/packages/flutter/test/material/slider_test.dart
+++ b/packages/flutter/test/material/slider_test.dart
@@ -1250,16 +1250,14 @@
         ));
 
     semantics.dispose();
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia }));
 
-  testWidgets('Slider Semantics - iOS', (WidgetTester tester) async {
+  testWidgets('Slider Semantics', (WidgetTester tester) async {
     final SemanticsTester semantics = SemanticsTester(tester);
 
     await tester.pumpWidget(
       Theme(
-        data: ThemeData.light().copyWith(
-          platform: TargetPlatform.iOS,
-        ),
+        data: ThemeData.light(),
         child: Directionality(
           textDirection: TextDirection.ltr,
           child: MediaQuery(
@@ -1294,7 +1292,7 @@
         ignoreTransform: true,
       ));
     semantics.dispose();
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Slider semantics with custom formatter', (WidgetTester tester) async {
     final SemanticsTester semantics = SemanticsTester(tester);
@@ -1485,27 +1483,34 @@
       );
     }
 
-    await tester.pumpWidget(buildFrame(TargetPlatform.iOS));
-    expect(find.byType(Slider), findsOneWidget);
-    expect(find.byType(CupertinoSlider), findsOneWidget);
+    for (final TargetPlatform platform in <TargetPlatform>[TargetPlatform.iOS, TargetPlatform.macOS]) {
+      value = 0.5;
+      await tester.pumpWidget(buildFrame(platform));
+      expect(find.byType(Slider), findsOneWidget);
+      expect(find.byType(CupertinoSlider), findsOneWidget);
 
-    expect(value, 0.5);
-    TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(CupertinoSlider)));
-    // Drag to the right end of the track.
-    await gesture.moveBy(const Offset(600.0, 0.0));
-    expect(value, 1.0);
+      expect(value, 0.5, reason: 'on ${describeEnum(platform)}');
+      final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(CupertinoSlider)));
+      // Drag to the right end of the track.
+      await gesture.moveBy(const Offset(600.0, 0.0));
+      expect(value, 1.0, reason: 'on ${describeEnum(platform)}');
+      await gesture.up();
+    }
 
-    value = 0.5;
-    await tester.pumpWidget(buildFrame(TargetPlatform.android));
-    await tester.pumpAndSettle(); // Finish the theme change animation.
-    expect(find.byType(Slider), findsOneWidget);
-    expect(find.byType(CupertinoSlider), findsNothing);
+    for (final TargetPlatform platform in <TargetPlatform>[TargetPlatform.android, TargetPlatform.fuchsia]) {
+      value = 0.5;
+      await tester.pumpWidget(buildFrame(platform));
+      await tester.pumpAndSettle(); // Finish the theme change animation.
+      expect(find.byType(Slider), findsOneWidget);
+      expect(find.byType(CupertinoSlider), findsNothing);
 
-    expect(value, 0.5);
-    gesture = await tester.startGesture(tester.getCenter(find.byType(Slider)));
-    // Drag to the right end of the track.
-    await gesture.moveBy(const Offset(600.0, 0.0));
-    expect(value, 1.0);
+      expect(value, 0.5, reason: 'on ${describeEnum(platform)}');
+      final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Slider)));
+      // Drag to the right end of the track.
+      await gesture.moveBy(const Offset(600.0, 0.0));
+      expect(value, 1.0, reason: 'on ${describeEnum(platform)}');
+      await gesture.up();
+    }
   });
 
   testWidgets('Slider respects height from theme', (WidgetTester tester) async {
diff --git a/packages/flutter/test/material/switch_list_tile_test.dart b/packages/flutter/test/material/switch_list_tile_test.dart
index 6a21366..11c1f81 100644
--- a/packages/flutter/test/material/switch_list_tile_test.dart
+++ b/packages/flutter/test/material/switch_list_tile_test.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter/cupertino.dart';
+import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 import '../rendering/mock_canvas.dart';
@@ -85,20 +86,26 @@
       );
     }
 
-    await tester.pumpWidget(buildFrame(TargetPlatform.iOS));
-    expect(find.byType(CupertinoSwitch), findsOneWidget);
-    expect(value, isFalse);
+    for (final TargetPlatform platform in <TargetPlatform>[ TargetPlatform.iOS, TargetPlatform.macOS ]) {
+      value = false;
+      await tester.pumpWidget(buildFrame(platform));
+      expect(find.byType(CupertinoSwitch), findsOneWidget);
+      expect(value, isFalse, reason: 'on ${describeEnum(platform)}');
 
-    await tester.tap(find.byType(SwitchListTile));
-    expect(value, isTrue);
+      await tester.tap(find.byType(SwitchListTile));
+      expect(value, isTrue, reason: 'on ${describeEnum(platform)}');
+    }
 
-    await tester.pumpWidget(buildFrame(TargetPlatform.android));
-    await tester.pumpAndSettle(); // Finish the theme change animation.
+    for (final TargetPlatform platform in <TargetPlatform>[ TargetPlatform.android, TargetPlatform.fuchsia ]) {
+      value = false;
+      await tester.pumpWidget(buildFrame(platform));
+      await tester.pumpAndSettle(); // Finish the theme change animation.
 
-    expect(find.byType(CupertinoSwitch), findsNothing);
-    expect(value, isTrue);
-    await tester.tap(find.byType(SwitchListTile));
-    expect(value, isFalse);
+      expect(find.byType(CupertinoSwitch), findsNothing);
+      expect(value, isFalse, reason: 'on ${describeEnum(platform)}');
+      await tester.tap(find.byType(SwitchListTile));
+      expect(value, isTrue, reason: 'on ${describeEnum(platform)}');
+    }
   });
 
   testWidgets('SwitchListTile contentPadding', (WidgetTester tester) async {
diff --git a/packages/flutter/test/material/switch_test.dart b/packages/flutter/test/material/switch_test.dart
index 6aa8e9b..222ab59 100644
--- a/packages/flutter/test/material/switch_test.dart
+++ b/packages/flutter/test/material/switch_test.dart
@@ -610,23 +610,28 @@
       );
     }
 
-    await tester.pumpWidget(buildFrame(TargetPlatform.iOS));
-    expect(find.byType(CupertinoSwitch), findsOneWidget);
+    for (final TargetPlatform platform in <TargetPlatform>[ TargetPlatform.iOS, TargetPlatform.macOS ]) {
+      value = false;
+      await tester.pumpWidget(buildFrame(platform));
+      expect(find.byType(CupertinoSwitch), findsOneWidget, reason: 'on ${describeEnum(platform)}');
 
-    final CupertinoSwitch adaptiveSwitch = tester.widget(find.byType(CupertinoSwitch));
-    expect(adaptiveSwitch.trackColor, inactiveTrackColor);
+      final CupertinoSwitch adaptiveSwitch = tester.widget(find.byType(CupertinoSwitch));
+      expect(adaptiveSwitch.trackColor, inactiveTrackColor, reason: 'on ${describeEnum(platform)}');
 
-    expect(value, isFalse);
-    await tester.tap(find.byType(Switch));
-    expect(value, isTrue);
+      expect(value, isFalse, reason: 'on ${describeEnum(platform)}');
+      await tester.tap(find.byType(Switch));
+      expect(value, isTrue, reason: 'on ${describeEnum(platform)}');
+    }
 
-    await tester.pumpWidget(buildFrame(TargetPlatform.android));
-    await tester.pumpAndSettle(); // Finish the theme change animation.
-    expect(find.byType(CupertinoSwitch), findsNothing);
-    expect(value, isTrue);
-    await tester.tap(find.byType(Switch));
-    expect(value, isFalse);
-
+    for (final TargetPlatform platform in <TargetPlatform>[ TargetPlatform.android, TargetPlatform.fuchsia ]) {
+      value = false;
+      await tester.pumpWidget(buildFrame(platform));
+      await tester.pumpAndSettle(); // Finish the theme change animation.
+      expect(find.byType(CupertinoSwitch), findsNothing);
+      expect(value, isFalse, reason: 'on ${describeEnum(platform)}');
+      await tester.tap(find.byType(Switch));
+      expect(value, isTrue, reason: 'on ${describeEnum(platform)}');
+    }
   });
 
   testWidgets('Switch is focusable and has correct focus color', (WidgetTester tester) async {
diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart
index 4bc122c..48263a9 100644
--- a/packages/flutter/test/material/text_field_test.dart
+++ b/packages/flutter/test/material/text_field_test.dart
@@ -304,9 +304,7 @@
     await checkCursorToggle();
   });
 
-  testWidgets('Cursor animates on iOS', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
+  testWidgets('Cursor animates', (WidgetTester tester) async {
     await tester.pumpWidget(
       const MaterialApp(
         home: Material(
@@ -340,13 +338,9 @@
     await tester.pump(const Duration(milliseconds: 50));
 
     expect(renderEditable.cursorColor.alpha, 0);
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-    debugDefaultTargetPlatformOverride = null;
-  });
-
-  testWidgets('Cursor radius is 2.0 on iOS', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
+  testWidgets('Cursor radius is 2.0', (WidgetTester tester) async {
     await tester.pumpWidget(
       const MaterialApp(
         home: Material(
@@ -359,9 +353,7 @@
     final RenderEditable renderEditable = editableTextState.renderEditable;
 
     expect(renderEditable.cursorRadius, const Radius.circular(2.0));
-
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('cursor has expected defaults', (WidgetTester tester) async {
     await tester.pumpWidget(
@@ -416,9 +408,7 @@
     );
   });
 
-  testWidgets('Material cursor iOS golden', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
+  testWidgets('Material cursor golden', (WidgetTester tester) async {
     final Widget widget = overlay(
       child: const RepaintBoundary(
         key: ValueKey<int>(1),
@@ -438,12 +428,13 @@
     await tester.tapAt(textOffsetToPosition(tester, testValue.length));
     await tester.pump();
 
-    debugDefaultTargetPlatformOverride = null;
     await expectLater(
       find.byKey(const ValueKey<int>(1)),
-      matchesGoldenFile('text_field_cursor_test.material.1.png'),
+      matchesGoldenFile(
+        'text_field_cursor_test_${describeEnum(debugDefaultTargetPlatformOverride).toLowerCase()}.material.1.png',
+      ),
     );
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('text field selection toolbar renders correctly inside opacity', (WidgetTester tester) async {
     await tester.pumpWidget(
@@ -496,14 +487,13 @@
     );
   }, skip: isBrowser);
 
-  testWidgets('text field toolbar options correctly changes options (iOS)',
+  testWidgets('text field toolbar options correctly changes options',
       (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -544,9 +534,9 @@
     expect(find.text('Copy'), findsOneWidget);
     expect(find.text('Cut'), findsNothing);
     expect(find.text('Select All'), findsNothing);
-  }, skip: isBrowser);
+  }, skip: isBrowser, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('text field toolbar options correctly changes options (Android)',
+  testWidgets('text field toolbar options correctly changes options',
       (WidgetTester tester) async {
     final TextEditingController controller = TextEditingController(
       text: 'Atwater Peel Sherbrooke Bonaventure',
@@ -577,10 +567,8 @@
     expect(find.text('COPY'), findsOneWidget);
     expect(find.text('CUT'), findsNothing);
     expect(find.text('SELECT ALL'), findsNothing);
-  }, skip: isBrowser);
+  }, skip: isBrowser, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia }));
 
-  // TODO(hansmuller): restore these tests after the fix for #24876 has landed.
-  /*
   testWidgets('cursor layout has correct width', (WidgetTester tester) async {
     EditableText.debugDeterministicCursor = true;
     await tester.pumpWidget(
@@ -597,10 +585,10 @@
 
     await expectLater(
       find.byType(TextField),
-      matchesGoldenFile('text_field_test.0.0.png'),
+      matchesGoldenFile('text_field_cursor_width_test.0.0.png', version: 0),
     );
     EditableText.debugDeterministicCursor = false;
-  }, skip: !Platform.isLinux);
+  }, skip: !isLinux);
 
   testWidgets('cursor layout has correct radius', (WidgetTester tester) async {
     EditableText.debugDeterministicCursor = true;
@@ -619,11 +607,10 @@
 
     await expectLater(
       find.byType(TextField),
-      matchesGoldenFile('text_field_test.1.0.png'),
+      matchesGoldenFile('text_field_cursor_width_test.1.0.png', version: 0),
     );
     EditableText.debugDeterministicCursor = false;
-  }, skip: !Platform.isLinux);
-  */
+  }, skip: !isLinux);
 
   testWidgets('Overflowing a line with spaces stops the cursor at the end', (WidgetTester tester) async {
     final TextEditingController controller = TextEditingController();
@@ -870,6 +857,27 @@
     expect(handle.opacity.value, equals(1.0));
   });
 
+
+  testWidgets('Long pressing a field with selection 0,0 shows the selection menu', (WidgetTester tester) async {
+    await tester.pumpWidget(overlay(
+      child: TextField(
+        controller: TextEditingController.fromValue(
+          const TextEditingValue(
+            selection: TextSelection(baseOffset: 0, extentOffset: 0),
+          ),
+        ),
+      ),
+    ));
+
+    expect(find.text('PASTE'), findsNothing);
+
+    final Offset emptyPos = textOffsetToPosition(tester, 0);
+    await tester.longPressAt(emptyPos, pointer: 7);
+    await tester.pumpAndSettle();
+
+    expect(find.text('PASTE'), findsOneWidget);
+  });
+
   testWidgets('Entering text hides selection handle caret', (WidgetTester tester) async {
     final TextEditingController controller = TextEditingController();
 
@@ -978,11 +986,10 @@
     expect(find.text('CUT'), findsNothing);
   });
 
-  testWidgets('does not paint toolbar when no options available on ios', (WidgetTester tester) async {
+  testWidgets('does not paint toolbar when no options available', (WidgetTester tester) async {
     await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: TextField(
               readOnly: true,
             ),
@@ -998,9 +1005,9 @@
     await tester.pumpAndSettle();
 
     expect(find.byType(CupertinoTextSelectionToolbar), paintsNothing);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('text field build empty toolbar when no options available android', (WidgetTester tester) async {
+  testWidgets('text field build empty toolbar when no options available', (WidgetTester tester) async {
     await tester.pumpWidget(
         const MaterialApp(
           home: Material(
@@ -1022,7 +1029,7 @@
       matching: find.byType(Container),
     ));
     expect(container.size, Size.zero);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia }));
 
   testWidgets('Sawping controllers should update selection', (WidgetTester tester) async {
     TextEditingController controller = TextEditingController(text: 'readonly');
@@ -5500,14 +5507,13 @@
   });
 
   testWidgets(
-    'tap moves cursor to the edge of the word it tapped on (iOS)',
+    'tap moves cursor to the edge of the word it tapped',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -5531,12 +5537,9 @@
 
       // But don't trigger the toolbar.
       expect(find.byType(CupertinoButton), findsNothing);
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets(
-    'tap moves cursor to the position tapped (Android)',
-    (WidgetTester tester) async {
+  testWidgets('tap moves cursor to the position tapped', (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
@@ -5565,18 +5568,16 @@
 
       // But don't trigger the toolbar.
       expect(find.byType(FlatButton), findsNothing);
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia }));
 
   testWidgets(
-    'two slow taps do not trigger a word selection (iOS)',
+    'two slow taps do not trigger a word selection',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -5602,18 +5603,16 @@
 
       // No toolbar.
       expect(find.byType(CupertinoButton), findsNothing);
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'double tap selects word and first tap of double tap moves cursor (iOS)',
+    'double tap selects word and first tap of double tap moves cursor',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -5649,11 +5648,10 @@
 
       // Selected text shows 3 toolbar buttons.
       expect(find.byType(CupertinoButton), findsNWidgets(3));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'double tap selects word and first tap of double tap moves cursor and shows toolbar (Android)',
+    'double tap selects word and first tap of double tap moves cursor and shows toolbar',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
@@ -5695,11 +5693,10 @@
 
       // Selected text shows 4 toolbar buttons: cut, copy, paste, select all
       expect(find.byType(FlatButton), findsNWidgets(4));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia }));
 
   testWidgets(
-    'double tap on top of cursor also selects word (Android)',
+    'double tap on top of cursor also selects word',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
@@ -5745,8 +5742,7 @@
 
       // Selected text shows 4 toolbar buttons: cut, copy, paste, select all
       expect(find.byType(FlatButton), findsNWidgets(4));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia }));
 
   testWidgets(
     'double double tap just shows the selection menu',
@@ -5873,14 +5869,13 @@
   );
 
   testWidgets(
-    'double tap hold selects word (iOS)',
+    'double tap hold selects word',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -5918,18 +5913,16 @@
       );
       // The toolbar is still showing.
       expect(find.byType(CupertinoButton), findsNWidgets(3));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'tap after a double tap select is not affected (iOS)',
+    'tap after a double tap select is not affected',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -5966,18 +5959,16 @@
 
       // No toolbar.
       expect(find.byType(CupertinoButton), findsNothing);
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'long press moves cursor to the exact long press position and shows toolbar (iOS)',
+    'long press moves cursor to the exact long press position and shows toolbar',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -6001,11 +5992,10 @@
 
       // Collapsed toolbar shows 2 buttons.
       expect(find.byType(CupertinoButton), findsNWidgets(2));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'long press selects word and shows toolbar (Android)',
+    'long press selects word and shows toolbar',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
@@ -6034,18 +6024,16 @@
 
       // Collapsed toolbar shows 4 buttons: cut, copy, paste, select all
       expect(find.byType(FlatButton), findsNWidgets(4));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia }));
 
   testWidgets(
-    'long press tap cannot initiate a double tap (iOS)',
+    'long press tap cannot initiate a double tap',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -6073,18 +6061,16 @@
 
       // Collapsed toolbar shows 2 buttons.
       expect(find.byType(CupertinoButton), findsNothing);
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'long press drag moves the cursor under the drag and shows toolbar on lift (iOS)',
+    'long press drag moves the cursor under the drag and shows toolbar on lift',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -6141,16 +6127,14 @@
       );
       // The toolbar now shows up.
       expect(find.byType(CupertinoButton), findsNWidgets(2));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('long press drag can edge scroll (iOS)', (WidgetTester tester) async {
+  testWidgets('long press drag can edge scroll', (WidgetTester tester) async {
     final TextEditingController controller = TextEditingController(
       text: 'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
     );
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         home: Material(
           child: Center(
             child: TextField(
@@ -6232,17 +6216,16 @@
     expect(firstCharEndpoint.length, 1);
     // The first character is now offscreen to the left.
     expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-257, epsilon: 1));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'long tap after a double tap select is not affected (iOS)',
+    'long tap after a double tap select is not affected',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -6276,18 +6259,16 @@
 
       // Long press toolbar.
       expect(find.byType(CupertinoButton), findsNWidgets(2));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'double tap after a long tap is not affected (iOS)',
+    'double tap after a long tap is not affected',
     (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -6319,18 +6300,14 @@
         const TextSelection(baseOffset: 8, extentOffset: 12),
       );
       expect(find.byType(CupertinoButton), findsNWidgets(3));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets(
-    'double tap chains work (iOS)',
-    (WidgetTester tester) async {
+  testWidgets('double tap chains work', (WidgetTester tester) async {
       final TextEditingController controller = TextEditingController(
         text: 'Atwater Peel Sherbrooke Bonaventure',
       );
       await tester.pumpWidget(
         MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
           home: Material(
             child: Center(
               child: TextField(
@@ -6387,10 +6364,9 @@
         const TextSelection(baseOffset: 8, extentOffset: 12),
       );
       expect(find.byType(CupertinoButton), findsNWidgets(3));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('force press does not select a word on (android)', (WidgetTester tester) async {
+  testWidgets('force press does not select a word', (WidgetTester tester) async {
     final TextEditingController controller = TextEditingController(
       text: 'Atwater Peel Sherbrooke Bonaventure',
     );
@@ -6418,7 +6394,7 @@
           pressureMin: 0.0,
       ),
     );
-    await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: offset + const Offset(150.0, 9.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
+    await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: offset + const Offset(150.0, 9.0), pressure: 0.5, pressureMin: 0, pressureMax: 1,),);
 
     // We don't want this gesture to select any word on Android.
     expect(controller.selection, const TextSelection.collapsed(offset: -1));
@@ -6426,15 +6402,14 @@
     await gesture.up();
     await tester.pump();
     expect(find.byType(FlatButton), findsNothing);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android,  TargetPlatform.fuchsia }));
 
-  testWidgets('force press selects word (iOS)', (WidgetTester tester) async {
+  testWidgets('force press selects word', (WidgetTester tester) async {
     final TextEditingController controller = TextEditingController(
       text: 'Atwater Peel Sherbrooke Bonaventure',
     );
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         home: Material(
           child: TextField(
             controller: controller,
@@ -6459,7 +6434,15 @@
       ),
     );
 
-    await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: textfieldStart + const Offset(150.0, 9.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
+    await gesture.updateWithCustomEvent(
+      PointerMoveEvent(
+        pointer: pointerValue,
+        position: textfieldStart + const Offset(150.0, 9.0),
+        pressure: 0.5,
+        pressureMin: 0,
+        pressureMax: 1,
+      ),
+    );
     // We expect the force press to select a word at the given location.
     expect(
       controller.selection,
@@ -6469,15 +6452,15 @@
     await gesture.up();
     await tester.pump();
     expect(find.byType(CupertinoButton), findsNWidgets(3));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('tap on non-force-press-supported devices work (iOS)', (WidgetTester tester) async {
+  testWidgets('tap on non-force-press-supported devices work', (WidgetTester tester) async {
     final TextEditingController controller = TextEditingController(
       text: 'Atwater Peel Sherbrooke Bonaventure',
     );
+    await tester.pumpWidget(Container(key: GlobalKey()));
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         home: Material(
           child: TextField(
             controller: controller,
@@ -6503,7 +6486,15 @@
       ),
     );
 
-    await gesture.updateWithCustomEvent(PointerMoveEvent(pointer: pointerValue, position: textfieldStart + const Offset(150.0, 9.0), pressure: 0.5, pressureMin: 0, pressureMax: 1));
+    await gesture.updateWithCustomEvent(
+      PointerMoveEvent(
+        pointer: pointerValue,
+        position: textfieldStart + const Offset(150.0, 9.0),
+        pressure: 0.5,
+        pressureMin: 0,
+        pressureMax: 1,
+      ),
+    );
     await gesture.up();
     // The event should fallback to a normal tap and move the cursor.
     // Single taps selects the edge of the word.
@@ -6515,7 +6506,10 @@
     await tester.pump();
     // Single taps shouldn't trigger the toolbar.
     expect(find.byType(CupertinoButton), findsNothing);
-  });
+
+    // TODO(gspencergoog): Add in TargetPlatform.macOS in the line below when we figure out what global state is leaking.
+    // https://github.com/flutter/flutter/issues/43445
+  }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
 
   testWidgets('default TextField debugFillProperties', (WidgetTester tester) async {
     final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
@@ -6922,7 +6916,6 @@
   });
 
   testWidgets('iOS selection handles are rendered and not faded away', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     const String testText = 'lorem ipsum';
     final TextEditingController controller = TextEditingController(text: testText);
 
@@ -6951,9 +6944,7 @@
 
     expect(left.opacity.value, equals(1.0));
     expect(right.opacity.value, equals(1.0));
-
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Tap shows handles but not toolbar', (WidgetTester tester) async {
     final TextEditingController controller = TextEditingController(
diff --git a/packages/flutter/test/material/theme_data_test.dart b/packages/flutter/test/material/theme_data_test.dart
index 0f075ff..02b59d3 100644
--- a/packages/flutter/test/material/theme_data_test.dart
+++ b/packages/flutter/test/material/theme_data_test.dart
@@ -196,6 +196,7 @@
     const PageTransitionsTheme pageTransitionTheme = PageTransitionsTheme(
       builders: <TargetPlatform, PageTransitionsBuilder>{
         TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
+        TargetPlatform.macOS: CupertinoPageTransitionsBuilder(),
       },
     );
 
diff --git a/packages/flutter/test/material/typography_test.dart b/packages/flutter/test/material/typography_test.dart
index f83dcf4..5a13588 100644
--- a/packages/flutter/test/material/typography_test.dart
+++ b/packages/flutter/test/material/typography_test.dart
@@ -21,16 +21,16 @@
     expect(Typography.material2018(platform: TargetPlatform.fuchsia).black.headline6.fontFamily, 'Roboto');
   });
 
+  // Ref: https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography/
+  final Matcher isDisplayFont = predicate((TextStyle s) {
+    return s.fontFamily == '.SF UI Display';
+  }, 'Uses SF Display font');
+
+  final Matcher isTextFont = predicate((TextStyle s) {
+    return s.fontFamily == '.SF UI Text';
+  }, 'Uses SF Text font');
+
   test('Typography on iOS defaults to the correct SF font family based on size', () {
-    // Ref: https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography/
-    final Matcher isDisplayFont = predicate((TextStyle s) {
-      return s.fontFamily == '.SF UI Display';
-    }, 'Uses SF Display font');
-
-    final Matcher isTextFont = predicate((TextStyle s) {
-      return s.fontFamily == '.SF UI Text';
-    }, 'Uses SF Text font');
-
     final Typography typography = Typography.material2018(platform: TargetPlatform.iOS);
     for (final TextTheme textTheme in <TextTheme>[typography.black, typography.white]) {
       expect(textTheme.headline1, isDisplayFont);
@@ -49,6 +49,25 @@
     }
   });
 
+  test('Typography on macOS defaults to the correct SF font family based on size', () {
+    final Typography typography = Typography.material2018(platform: TargetPlatform.macOS);
+    for (final TextTheme textTheme in <TextTheme>[typography.black, typography.white]) {
+      expect(textTheme.headline1, isDisplayFont);
+      expect(textTheme.headline2, isDisplayFont);
+      expect(textTheme.headline3, isDisplayFont);
+      expect(textTheme.headline4, isDisplayFont);
+      expect(textTheme.headline5, isDisplayFont);
+      expect(textTheme.headline6, isDisplayFont);
+      expect(textTheme.subtitle1, isTextFont);
+      expect(textTheme.bodyText1, isTextFont);
+      expect(textTheme.bodyText2, isTextFont);
+      expect(textTheme.caption, isTextFont);
+      expect(textTheme.button, isTextFont);
+      expect(textTheme.subtitle2, isTextFont);
+      expect(textTheme.overline, isTextFont);
+    }
+  });
+
   testWidgets('Typography implements debugFillProperties', (WidgetTester tester) async {
     final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
     Typography.material2014(
diff --git a/packages/flutter/test/painting/border_rtl_test.dart b/packages/flutter/test/painting/border_rtl_test.dart
index d238b08..035a5cc 100644
--- a/packages/flutter/test/painting/border_rtl_test.dart
+++ b/packages/flutter/test/painting/border_rtl_test.dart
@@ -502,7 +502,7 @@
     );
     expect(
       const BorderDirectional(start: magenta3) + const BorderDirectional(start: yellow2),
-      isNot(isInstanceOf<BorderDirectional>()), // see shape_border_test.dart for better tests of this case
+      isNot(isA<BorderDirectional>()), // see shape_border_test.dart for better tests of this case
     );
     const BorderDirectional b3 = BorderDirectional(top: magenta3);
     const BorderDirectional b6 = BorderDirectional(top: magenta6);
diff --git a/packages/flutter/test/painting/border_test.dart b/packages/flutter/test/painting/border_test.dart
index e82095e..e25a10f 100644
--- a/packages/flutter/test/painting/border_test.dart
+++ b/packages/flutter/test/painting/border_test.dart
@@ -97,7 +97,7 @@
     );
     expect(
       const Border(left: magenta3) + const Border(left: yellow2),
-      isNot(isInstanceOf<Border>()), // see shape_border_test.dart for better tests of this case
+      isNot(isA<Border>()), // see shape_border_test.dart for better tests of this case
     );
     const Border b3 = Border(top: magenta3);
     const Border b6 = Border(top: magenta6);
diff --git a/packages/flutter/test/painting/decoration_test.dart b/packages/flutter/test/painting/decoration_test.dart
index 1e1b661..5747b4e 100644
--- a/packages/flutter/test/painting/decoration_test.dart
+++ b/packages/flutter/test/painting/decoration_test.dart
@@ -223,10 +223,10 @@
     final Invocation call = canvas.invocations.singleWhere((Invocation call) => call.memberName == #drawImageNine);
     expect(call.isMethod, isTrue);
     expect(call.positionalArguments, hasLength(4));
-    expect(call.positionalArguments[0], isInstanceOf<TestImage>());
+    expect(call.positionalArguments[0], isA<TestImage>());
     expect(call.positionalArguments[1], const Rect.fromLTRB(10.0, 20.0, 40.0, 60.0));
     expect(call.positionalArguments[2], const Rect.fromLTRB(0.0, 0.0, 100.0, 100.0));
-    expect(call.positionalArguments[3], isInstanceOf<Paint>());
+    expect(call.positionalArguments[3], isA<Paint>());
     expect(call.positionalArguments[3].isAntiAlias, false);
     expect(call.positionalArguments[3].colorFilter, colorFilter);
     expect(call.positionalArguments[3].filterQuality, FilterQuality.low);
@@ -253,8 +253,8 @@
     }
     expect(error, isNotNull);
     expect(error.diagnostics.length, 4);
-    expect(error.diagnostics[2], isInstanceOf<DiagnosticsProperty<DecorationImage>>());
-    expect(error.diagnostics[3], isInstanceOf<DiagnosticsProperty<ImageConfiguration>>());
+    expect(error.diagnostics[2], isA<DiagnosticsProperty<DecorationImage>>());
+    expect(error.diagnostics[3], isA<DiagnosticsProperty<ImageConfiguration>>());
     expect(error.toStringDeep(),
       'FlutterError\n'
       '   DecorationImage.matchTextDirection can only be used when a\n'
@@ -375,10 +375,10 @@
   });
 
   test('Decoration.lerp with unrelated decorations', () {
-    expect(Decoration.lerp(const FlutterLogoDecoration(), const BoxDecoration(), 0.0), isInstanceOf<FlutterLogoDecoration>()); // ignore: CONST_EVAL_THROWS_EXCEPTION
-    expect(Decoration.lerp(const FlutterLogoDecoration(), const BoxDecoration(), 0.25), isInstanceOf<FlutterLogoDecoration>()); // ignore: CONST_EVAL_THROWS_EXCEPTION
-    expect(Decoration.lerp(const FlutterLogoDecoration(), const BoxDecoration(), 0.75), isInstanceOf<BoxDecoration>()); // ignore: CONST_EVAL_THROWS_EXCEPTION
-    expect(Decoration.lerp(const FlutterLogoDecoration(), const BoxDecoration(), 1.0), isInstanceOf<BoxDecoration>()); // ignore: CONST_EVAL_THROWS_EXCEPTION
+    expect(Decoration.lerp(const FlutterLogoDecoration(), const BoxDecoration(), 0.0), isA<FlutterLogoDecoration>()); // ignore: CONST_EVAL_THROWS_EXCEPTION
+    expect(Decoration.lerp(const FlutterLogoDecoration(), const BoxDecoration(), 0.25), isA<FlutterLogoDecoration>()); // ignore: CONST_EVAL_THROWS_EXCEPTION
+    expect(Decoration.lerp(const FlutterLogoDecoration(), const BoxDecoration(), 0.75), isA<BoxDecoration>()); // ignore: CONST_EVAL_THROWS_EXCEPTION
+    expect(Decoration.lerp(const FlutterLogoDecoration(), const BoxDecoration(), 1.0), isA<BoxDecoration>()); // ignore: CONST_EVAL_THROWS_EXCEPTION
   });
 
   test('paintImage BoxFit.none scale test', () {
@@ -406,7 +406,7 @@
       expect(call.isMethod, isTrue);
       expect(call.positionalArguments, hasLength(4));
 
-      expect(call.positionalArguments[0], isInstanceOf<TestImage>());
+      expect(call.positionalArguments[0], isA<TestImage>());
 
       // sourceRect should contain all pixels of the source image
       expect(call.positionalArguments[1], Offset.zero & imageSize);
@@ -420,7 +420,7 @@
       );
       expect(call.positionalArguments[2], expectedTileRect);
 
-      expect(call.positionalArguments[3], isInstanceOf<Paint>());
+      expect(call.positionalArguments[3], isA<Paint>());
     }
   });
 
@@ -450,7 +450,7 @@
       expect(call.isMethod, isTrue);
       expect(call.positionalArguments, hasLength(4));
 
-      expect(call.positionalArguments[0], isInstanceOf<TestImage>());
+      expect(call.positionalArguments[0], isA<TestImage>());
 
       // sourceRect should contain all pixels of the source image
       expect(call.positionalArguments[1], Offset.zero & imageSize);
@@ -464,7 +464,7 @@
       );
       expect(call.positionalArguments[2], expectedTileRect);
 
-      expect(call.positionalArguments[3], isInstanceOf<Paint>());
+      expect(call.positionalArguments[3], isA<Paint>());
     }
   });
 
@@ -493,7 +493,7 @@
     expect(call.isMethod, isTrue);
     expect(call.positionalArguments, hasLength(4));
 
-    expect(call.positionalArguments[0], isInstanceOf<TestImage>());
+    expect(call.positionalArguments[0], isA<TestImage>());
 
     // sourceRect should contain all pixels of the source image
     expect(call.positionalArguments[1], Offset.zero & imageSize);
@@ -507,7 +507,7 @@
     );
     expect(call.positionalArguments[2], expectedTileRect);
 
-    expect(call.positionalArguments[3], isInstanceOf<Paint>());
+    expect(call.positionalArguments[3], isA<Paint>());
   });
 
   test('paintImage boxFit, scale and alignment test', () {
diff --git a/packages/flutter/test/painting/edge_insets_test.dart b/packages/flutter/test/painting/edge_insets_test.dart
index fdd5c52..74d4ba4 100644
--- a/packages/flutter/test/painting/edge_insets_test.dart
+++ b/packages/flutter/test/painting/edge_insets_test.dart
@@ -175,7 +175,7 @@
 
   test('EdgeInsetsGeometry operators', () {
     final EdgeInsetsGeometry a = const EdgeInsetsDirectional.fromSTEB(1.0, 2.0, 3.0, 5.0).add(EdgeInsets.zero);
-    expect(a, isNot(isInstanceOf<EdgeInsetsDirectional>()));
+    expect(a, isNot(isA<EdgeInsetsDirectional>()));
     expect(a * 2.0, const EdgeInsetsDirectional.fromSTEB(2.0, 4.0, 6.0, 10.0));
     expect(a / 2.0, const EdgeInsetsDirectional.fromSTEB(0.5, 1.0, 1.5, 2.5));
     expect(a % 2.0, const EdgeInsetsDirectional.fromSTEB(1.0, 0.0, 1.0, 1.0));
diff --git a/packages/flutter/test/painting/image_cache_test.dart b/packages/flutter/test/painting/image_cache_test.dart
index aa1da21..376da65 100644
--- a/packages/flutter/test/painting/image_cache_test.dart
+++ b/packages/flutter/test/painting/image_cache_test.dart
@@ -133,7 +133,7 @@
 
     test('Returns null if an error is caught resolving an image', () {
       final ErrorImageProvider errorImage = ErrorImageProvider();
-      expect(() => imageCache.putIfAbsent(errorImage, () => errorImage.load(errorImage, null)), throwsA(isInstanceOf<Error>()));
+      expect(() => imageCache.putIfAbsent(errorImage, () => errorImage.load(errorImage, null)), throwsA(isA<Error>()));
       bool caughtError = false;
       final ImageStreamCompleter result = imageCache.putIfAbsent(errorImage, () => errorImage.load(errorImage, null), onError: (dynamic error, StackTrace stackTrace) {
         caughtError = true;
diff --git a/packages/flutter/test/painting/image_provider_test.dart b/packages/flutter/test/painting/image_provider_test.dart
index 87e37b5..3379818 100644
--- a/packages/flutter/test/painting/image_provider_test.dart
+++ b/packages/flutter/test/painting/image_provider_test.dart
@@ -11,7 +11,6 @@
 import 'package:flutter/painting.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:mockito/mockito.dart';
-import 'package:test_api/test_api.dart' show TypeMatcher; // ignore: deprecated_member_use
 
 import '../rendering/rendering_tester.dart';
 import 'image_data.dart';
@@ -182,7 +181,7 @@
         final dynamic err = await caughtError.future;
         expect(
           err,
-          const TypeMatcher<NetworkImageLoadException>()
+          isA<NetworkImageLoadException>()
             .having((NetworkImageLoadException e) => e.statusCode, 'statusCode', errorStatusCode)
             .having((NetworkImageLoadException e) => e.uri, 'uri', Uri.base.resolve(requestUrl)),
         );
diff --git a/packages/flutter/test/rendering/aspect_ratio_test.dart b/packages/flutter/test/rendering/aspect_ratio_test.dart
index 69815b5..9e8633f 100644
--- a/packages/flutter/test/rendering/aspect_ratio_test.dart
+++ b/packages/flutter/test/rendering/aspect_ratio_test.dart
@@ -4,7 +4,8 @@
 
 import 'package:flutter/foundation.dart';
 import 'package:flutter/rendering.dart';
-import '../flutter_test_alternative.dart';
+import 'package:flutter_test/flutter_test.dart';
+
 import 'rendering_tester.dart';
 
 void main() {
@@ -113,7 +114,7 @@
       errors.addAll(renderer.takeAllFlutterErrorDetails());
     });
     expect(errors, hasLength(2));
-    expect(errors.first.exception, isA<FlutterError>());
+    expect(errors.first.exception, isFlutterError);
     expect(errors.first.exception.toStringDeep(),
       'FlutterError\n'
       '   RenderAspectRatio has unbounded constraints.\n'
diff --git a/packages/flutter/test/rendering/box_constraints_test.dart b/packages/flutter/test/rendering/box_constraints_test.dart
index d9a8f7a..a71107e 100644
--- a/packages/flutter/test/rendering/box_constraints_test.dart
+++ b/packages/flutter/test/rendering/box_constraints_test.dart
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter/rendering.dart';
-import '../flutter_test_alternative.dart';
+import 'package:flutter_test/flutter_test.dart';
 
 void main() {
   test('BoxConstraints toString', () {
@@ -153,9 +153,9 @@
       minHeight: 20.0,
       maxHeight: 30.0,
     );
-    expect(() => BoxConstraints.lerp(constraints1, constraints2, 0.5), throwsA(isInstanceOf<AssertionError>()));
-    expect(() => BoxConstraints.lerp(constraints1, constraints3, 0.5), throwsA(isInstanceOf<AssertionError>()));
-    expect(() => BoxConstraints.lerp(constraints2, constraints3, 0.5), throwsA(isInstanceOf<AssertionError>()));
+    expect(() => BoxConstraints.lerp(constraints1, constraints2, 0.5), throwsAssertionError);
+    expect(() => BoxConstraints.lerp(constraints1, constraints3, 0.5), throwsAssertionError);
+    expect(() => BoxConstraints.lerp(constraints2, constraints3, 0.5), throwsAssertionError);
   });
 
   test('BoxConstraints normalize', () {
diff --git a/packages/flutter/test/rendering/debug_overflow_indicator_test.dart b/packages/flutter/test/rendering/debug_overflow_indicator_test.dart
index f0fd349..ef63120 100644
--- a/packages/flutter/test/rendering/debug_overflow_indicator_test.dart
+++ b/packages/flutter/test/rendering/debug_overflow_indicator_test.dart
@@ -34,7 +34,7 @@
     );
 
     final dynamic exception = tester.takeException();
-    expect(exception, isInstanceOf<FlutterError>());
+    expect(exception, isFlutterError);
     expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
     expect(exception.diagnostics.first.toString(), startsWith('A RenderUnconstrainedBox overflowed by '));
     expect(find.byType(UnconstrainedBox), paints..rect());
diff --git a/packages/flutter/test/rendering/flex_test.dart b/packages/flutter/test/rendering/flex_test.dart
index ad5aba6..824aff1 100644
--- a/packages/flutter/test/rendering/flex_test.dart
+++ b/packages/flutter/test/rendering/flex_test.dart
@@ -388,7 +388,7 @@
       exceptions.addAll(renderer.takeAllFlutterExceptions());
     });
     expect(exceptions, isNotEmpty);
-    expect(exceptions.first, isInstanceOf<FlutterError>());
+    expect(exceptions.first, isFlutterError);
   });
 
   test('MainAxisSize.min inside unconstrained', () {
@@ -416,7 +416,7 @@
       exceptions.addAll(renderer.takeAllFlutterExceptions());
     });
     expect(exceptions, isNotEmpty);
-    expect(exceptions.first, isInstanceOf<FlutterError>());
+    expect(exceptions.first, isFlutterError);
   });
 
   test('MainAxisSize.min inside tightly constrained', () {
diff --git a/packages/flutter/test/rendering/object_test.dart b/packages/flutter/test/rendering/object_test.dart
index 4ea24dc..214884d 100644
--- a/packages/flutter/test/rendering/object_test.dart
+++ b/packages/flutter/test/rendering/object_test.dart
@@ -148,7 +148,7 @@
   box.markNeedsPaint();
   pumpFrame(phase: EnginePhase.paint);
   expect(box.paintedLayers, hasLength(2));
-  expect(box.paintedLayers[0], isInstanceOf<L>());
+  expect(box.paintedLayers[0], isA<L>());
   expect(box.paintedLayers[0], same(box.paintedLayers[1]));
 }
 
diff --git a/packages/flutter/test/rendering/proxy_box_test.dart b/packages/flutter/test/rendering/proxy_box_test.dart
index ee06a85..94a078c 100644
--- a/packages/flutter/test/rendering/proxy_box_test.dart
+++ b/packages/flutter/test/rendering/proxy_box_test.dart
@@ -81,21 +81,25 @@
   });
 
   test('RenderPhysicalModel compositing on non-Fuchsia', () {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
+    for (final TargetPlatform platform in TargetPlatform.values) {
+      if (platform == TargetPlatform.fuchsia) {
+        continue;
+      }
+      debugDefaultTargetPlatformOverride = platform;
 
-    final RenderPhysicalModel root = RenderPhysicalModel(color: const Color(0xffff00ff));
-    layout(root, phase: EnginePhase.composite);
-    expect(root.needsCompositing, isTrue);
+      final RenderPhysicalModel root = RenderPhysicalModel(color: const Color(0xffff00ff));
+      layout(root, phase: EnginePhase.composite);
+      expect(root.needsCompositing, isTrue);
 
-    // Flutter now composites physical shapes on all platforms.
-    root.elevation = 1.0;
-    pumpFrame(phase: EnginePhase.composite);
-    expect(root.needsCompositing, isTrue);
+      // Flutter now composites physical shapes on all platforms.
+      root.elevation = 1.0;
+      pumpFrame(phase: EnginePhase.composite);
+      expect(root.needsCompositing, isTrue);
 
-    root.elevation = 0.0;
-    pumpFrame(phase: EnginePhase.composite);
-    expect(root.needsCompositing, isTrue);
-
+      root.elevation = 0.0;
+      pumpFrame(phase: EnginePhase.composite);
+      expect(root.needsCompositing, isTrue);
+    }
     debugDefaultTargetPlatformOverride = null;
   });
 
@@ -121,44 +125,53 @@
   });
 
   group('RenderPhysicalShape', () {
-    setUp(() {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-    });
-
     test('shape change triggers repaint', () {
-      final RenderPhysicalShape root = RenderPhysicalShape(
-        color: const Color(0xffff00ff),
-        clipper: const ShapeBorderClipper(shape: CircleBorder()),
-      );
-      layout(root, phase: EnginePhase.composite);
-      expect(root.debugNeedsPaint, isFalse);
+      for (final TargetPlatform platform in TargetPlatform.values) {
+        if (platform == TargetPlatform.fuchsia) {
+          continue;
+        }
+        debugDefaultTargetPlatformOverride = platform;
 
-      // Same shape, no repaint.
-      root.clipper = const ShapeBorderClipper(shape: CircleBorder());
-      expect(root.debugNeedsPaint, isFalse);
+        final RenderPhysicalShape root = RenderPhysicalShape(
+          color: const Color(0xffff00ff),
+          clipper: const ShapeBorderClipper(shape: CircleBorder()),
+        );
+        layout(root, phase: EnginePhase.composite);
+        expect(root.debugNeedsPaint, isFalse);
 
-      // Different shape triggers repaint.
-      root.clipper = const ShapeBorderClipper(shape: StadiumBorder());
-      expect(root.debugNeedsPaint, isTrue);
+        // Same shape, no repaint.
+        root.clipper = const ShapeBorderClipper(shape: CircleBorder());
+        expect(root.debugNeedsPaint, isFalse);
+
+        // Different shape triggers repaint.
+        root.clipper = const ShapeBorderClipper(shape: StadiumBorder());
+        expect(root.debugNeedsPaint, isTrue);
+      }
+      debugDefaultTargetPlatformOverride = null;
     });
 
     test('compositing on non-Fuchsia', () {
-      final RenderPhysicalShape root = RenderPhysicalShape(
-        color: const Color(0xffff00ff),
-        clipper: const ShapeBorderClipper(shape: CircleBorder()),
-      );
-      layout(root, phase: EnginePhase.composite);
-      expect(root.needsCompositing, isTrue);
+      for (final TargetPlatform platform in TargetPlatform.values) {
+        if (platform == TargetPlatform.fuchsia) {
+          continue;
+        }
+        debugDefaultTargetPlatformOverride = platform;
+        final RenderPhysicalShape root = RenderPhysicalShape(
+          color: const Color(0xffff00ff),
+          clipper: const ShapeBorderClipper(shape: CircleBorder()),
+        );
+        layout(root, phase: EnginePhase.composite);
+        expect(root.needsCompositing, isTrue);
 
-      // On non-Fuchsia platforms, we composite physical shape layers
-      root.elevation = 1.0;
-      pumpFrame(phase: EnginePhase.composite);
-      expect(root.needsCompositing, isTrue);
+        // On non-Fuchsia platforms, we composite physical shape layers
+        root.elevation = 1.0;
+        pumpFrame(phase: EnginePhase.composite);
+        expect(root.needsCompositing, isTrue);
 
-      root.elevation = 0.0;
-      pumpFrame(phase: EnginePhase.composite);
-      expect(root.needsCompositing, isTrue);
-
+        root.elevation = 0.0;
+        pumpFrame(phase: EnginePhase.composite);
+        expect(root.needsCompositing, isTrue);
+      }
       debugDefaultTargetPlatformOverride = null;
     });
   });
@@ -454,18 +467,6 @@
     // transform -> clip
     _testFittedBoxWithClipRectLayer();
   });
-
-  test('RenderFractionalTranslation updates its semantics after its translation value is set', () {
-    final _TestSemanticsUpdateRenderFractionalTranslation box = _TestSemanticsUpdateRenderFractionalTranslation(
-      translation: const Offset(0.5, 0.5),
-    );
-    layout(box, constraints: BoxConstraints.tight(const Size(200.0, 200.0)));
-    expect(box.markNeedsSemanticsUpdateCallCount, 1);
-    box.translation = const Offset(0.4, 0.4);
-    expect(box.markNeedsSemanticsUpdateCallCount, 2);
-    box.translation = const Offset(0.3, 0.3);
-    expect(box.markNeedsSemanticsUpdateCallCount, 3);
-  });
 }
 
 class _TestRectClipper extends CustomClipper<Rect> {
@@ -502,7 +503,7 @@
   expect(renderObject.debugLayer, null);
   layout(renderObject, phase: EnginePhase.paint, constraints: BoxConstraints.tight(const Size(10, 10)));
   final Layer layer = renderObject.debugLayer;
-  expect(layer, isInstanceOf<L>());
+  expect(layer, isA<L>());
   expect(layer, isNotNull);
 
   // Mark for repaint otherwise pumpFrame is a noop.
@@ -522,18 +523,3 @@
   @override
   bool shouldReclip(_TestPathClipper oldClipper) => false;
 }
-
-class _TestSemanticsUpdateRenderFractionalTranslation extends RenderFractionalTranslation {
-  _TestSemanticsUpdateRenderFractionalTranslation({
-    @required Offset translation,
-    RenderBox child,
-  }) : super(translation: translation, child: child);
-
-  int markNeedsSemanticsUpdateCallCount = 0;
-
-  @override
-  void markNeedsSemanticsUpdate() {
-    markNeedsSemanticsUpdateCallCount++;
-    super.markNeedsSemanticsUpdate();
-  }
-}
diff --git a/packages/flutter/test/rendering/repaint_boundary_test.dart b/packages/flutter/test/rendering/repaint_boundary_test.dart
index 6cee7f6..0238172 100644
--- a/packages/flutter/test/rendering/repaint_boundary_test.dart
+++ b/packages/flutter/test/rendering/repaint_boundary_test.dart
@@ -60,7 +60,7 @@
       child: repaintBoundary,
     );
     layout(opacity, phase: EnginePhase.flushSemantics);
-    expect(repaintBoundary.debugLayer, isInstanceOf<OffsetLayer>());
+    expect(repaintBoundary.debugLayer, isA<OffsetLayer>());
   });
 
   test('Framework does not create an OffsetLayer for a non-repaint boundary', () {
@@ -80,7 +80,7 @@
       child: compositedBox,
     );
     layout(opacity, phase: EnginePhase.flushSemantics);
-    expect(compositedBox.debugLayer, isInstanceOf<OpacityLayer>());
+    expect(compositedBox.debugLayer, isA<OpacityLayer>());
   });
 
   test('Framework ensures repaint boundary layer is not overwritten', () {
diff --git a/packages/flutter/test/rendering/viewport_test.dart b/packages/flutter/test/rendering/viewport_test.dart
index 83391b7..c25c6c7 100644
--- a/packages/flutter/test/rendering/viewport_test.dart
+++ b/packages/flutter/test/rendering/viewport_test.dart
@@ -1145,10 +1145,8 @@
     );
   });
 
-  testWidgets('Handles infinite constraints when TargetPlatform is iOS', (WidgetTester tester) async {
+  testWidgets('Handles infinite constraints when TargetPlatform is iOS or macOS', (WidgetTester tester) async {
     // regression test for https://github.com/flutter/flutter/issues/45866
-    final TargetPlatform oldTargetPlatform = debugDefaultTargetPlatformOverride;
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     await tester.pumpWidget(
       Directionality(
         textDirection: TextDirection.ltr,
@@ -1177,6 +1175,5 @@
     expect(find.text('b'), findsOneWidget);
     await tester.drag(find.text('b'), const Offset(0, 200));
     await tester.pumpAndSettle();
-    debugDefaultTargetPlatformOverride = oldTargetPlatform;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
 }
diff --git a/packages/flutter/test/scheduler/ticker_test.dart b/packages/flutter/test/scheduler/ticker_test.dart
index ee07bfb..cf3c9ee 100644
--- a/packages/flutter/test/scheduler/ticker_test.dart
+++ b/packages/flutter/test/scheduler/ticker_test.dart
@@ -33,7 +33,7 @@
     }
     expect(error, isNotNull);
     expect(error.diagnostics.length, 3);
-    expect(error.diagnostics.last, isInstanceOf<DiagnosticsProperty<Ticker>>());
+    expect(error.diagnostics.last, isA<DiagnosticsProperty<Ticker>>());
     expect(
       error.toStringDeep(),
       startsWith(
diff --git a/packages/flutter/test/services/asset_bundle_test.dart b/packages/flutter/test/services/asset_bundle_test.dart
index 0760131..0cc3ddd 100644
--- a/packages/flutter/test/services/asset_bundle_test.dart
+++ b/packages/flutter/test/services/asset_bundle_test.dart
@@ -68,7 +68,7 @@
     }
     expect(error, isNotNull);
     expect(error.diagnostics.length, 2);
-    expect(error.diagnostics.last, isInstanceOf<IntProperty>());
+    expect(error.diagnostics.last, isA<IntProperty>());
     expect(
       error.toStringDeep(),
       'FlutterError\n'
diff --git a/packages/flutter/test/services/platform_channel_test.dart b/packages/flutter/test/services/platform_channel_test.dart
index 85e9382..f318edb 100644
--- a/packages/flutter/test/services/platform_channel_test.dart
+++ b/packages/flutter/test/services/platform_channel_test.dart
@@ -70,7 +70,7 @@
           }
         },
       );
-      expect(channel.invokeMethod<List<String>>('sayHello', 'hello'), throwsA(isInstanceOf<CastError>()));
+      expect(channel.invokeMethod<List<String>>('sayHello', 'hello'), throwsA(isCastError));
       expect(await channel.invokeListMethod<String>('sayHello', 'hello'), <String>['hello', 'world']);
     });
 
@@ -102,7 +102,7 @@
           }
         },
       );
-      expect(channel.invokeMethod<Map<String, String>>('sayHello', 'hello'), throwsA(isInstanceOf<CastError>()));
+      expect(channel.invokeMethod<Map<String, String>>('sayHello', 'hello'), throwsA(isCastError));
       expect(await channel.invokeMapMethod<String, String>('sayHello', 'hello'), <String, String>{'hello': 'world'});
     });
 
@@ -292,7 +292,7 @@
       await Future<void>.delayed(Duration.zero);
       expect(events, isEmpty);
       expect(errors, hasLength(1));
-      expect(errors[0], isInstanceOf<PlatformException>());
+      expect(errors[0], isA<PlatformException>());
       final PlatformException error = errors[0] as PlatformException;
       expect(error.code, '404');
       expect(error.message, 'Not Found.');
diff --git a/packages/flutter/test/services/platform_views_test.dart b/packages/flutter/test/services/platform_views_test.dart
index 33a313d..0adbd46 100644
--- a/packages/flutter/test/services/platform_views_test.dart
+++ b/packages/flutter/test/services/platform_views_test.dart
@@ -27,7 +27,7 @@
             layoutDirection: TextDirection.ltr,
           ).setSize(const Size(100.0, 100.0));
         },
-        throwsA(isInstanceOf<PlatformException>()),
+        throwsA(isA<PlatformException>()),
       );
     });
 
@@ -55,7 +55,7 @@
       expect(
           () => PlatformViewsService.initAndroidView(
               id: 0, viewType: 'web', layoutDirection: TextDirection.ltr).setSize(const Size(100.0, 100.0)),
-          throwsA(isInstanceOf<PlatformException>()));
+          throwsA(isA<PlatformException>()));
     });
 
     test('dispose Android view', () async {
@@ -170,7 +170,7 @@
             layoutDirection: TextDirection.ltr,
           );
         },
-        throwsA(isInstanceOf<PlatformException>()),
+        throwsA(isA<PlatformException>()),
       );
     });
 
@@ -199,7 +199,7 @@
       expect(
             () => PlatformViewsService.initUiKitView(
             id: 0, viewType: 'web', layoutDirection: TextDirection.ltr),
-        throwsA(isInstanceOf<PlatformException>()),
+        throwsA(isA<PlatformException>()),
       );
     });
 
@@ -228,7 +228,7 @@
           () async {
             await viewController.dispose();
           },
-          throwsA(isInstanceOf<PlatformException>()),
+          throwsA(isA<PlatformException>()),
       );
     });
   });
diff --git a/packages/flutter/test/widgets/animated_list_test.dart b/packages/flutter/test/widgets/animated_list_test.dart
index 479412d..30e68f8 100644
--- a/packages/flutter/test/widgets/animated_list_test.dart
+++ b/packages/flutter/test/widgets/animated_list_test.dart
@@ -344,7 +344,7 @@
         'https://api.flutter.dev/flutter/widgets/AnimatedListState-class.html\n'
       ),
     );
-    expect(error.diagnostics[3], isInstanceOf<DiagnosticsProperty<Element>>());
+    expect(error.diagnostics[3], isA<DiagnosticsProperty<Element>>());
     expect(
       error.toStringDeep(),
       equalsIgnoringHashCodes(
diff --git a/packages/flutter/test/widgets/animated_switcher_test.dart b/packages/flutter/test/widgets/animated_switcher_test.dart
index 3864852..ea67750 100644
--- a/packages/flutter/test/widgets/animated_switcher_test.dart
+++ b/packages/flutter/test/widgets/animated_switcher_test.dart
@@ -262,7 +262,7 @@
 
     expect(find.byType(Column), findsOneWidget);
     for (final Widget child in foundChildren) {
-      expect(child, isInstanceOf<KeyedSubtree>());
+      expect(child, isA<KeyedSubtree>());
     }
 
     await tester.pumpWidget(
@@ -280,7 +280,7 @@
     await tester.pump(const Duration(milliseconds: 50));
 
     for (final Widget child in foundChildren) {
-      expect(child, isInstanceOf<KeyedSubtree>());
+      expect(child, isA<KeyedSubtree>());
       expect(
         find.descendant(of: find.byWidget(child), matching: find.byType(SizeTransition)),
         findsOneWidget,
@@ -430,7 +430,7 @@
 
     expect(foundChildren.length, equals(3));
     for (final Widget child in foundChildren) {
-      expect(child, isInstanceOf<KeyedSubtree>());
+      expect(child, isA<KeyedSubtree>());
       expect(
         find.descendant(of: find.byWidget(child), matching: find.byType(FadeTransition)),
         findsOneWidget,
@@ -460,7 +460,7 @@
 
     expect(foundChildren.length, equals(3));
     for (final Widget child in foundChildren) {
-      expect(child, isInstanceOf<KeyedSubtree>());
+      expect(child, isA<KeyedSubtree>());
       expect(
         find.descendant(of: find.byWidget(child), matching: find.byType(ScaleTransition)),
         findsOneWidget,
diff --git a/packages/flutter/test/widgets/app_navigator_key_test.dart b/packages/flutter/test/widgets/app_navigator_key_test.dart
index 575b5ce..cb4a10f 100644
--- a/packages/flutter/test/widgets/app_navigator_key_test.dart
+++ b/packages/flutter/test/widgets/app_navigator_key_test.dart
@@ -20,7 +20,7 @@
       color: const Color(0xFF112233),
       onGenerateRoute: generateRoute,
     ));
-    expect(key.currentState, isInstanceOf<NavigatorState>());
+    expect(key.currentState, isA<NavigatorState>());
     await tester.pumpWidget(WidgetsApp(
       color: const Color(0xFF112233),
       onGenerateRoute: generateRoute,
@@ -31,6 +31,6 @@
       color: const Color(0xFF112233),
       onGenerateRoute: generateRoute,
     ));
-    expect(key.currentState, isInstanceOf<NavigatorState>());
+    expect(key.currentState, isA<NavigatorState>());
   });
 }
diff --git a/packages/flutter/test/widgets/basic_test.dart b/packages/flutter/test/widgets/basic_test.dart
index abbb4e2..2b2a287 100644
--- a/packages/flutter/test/widgets/basic_test.dart
+++ b/packages/flutter/test/widgets/basic_test.dart
@@ -145,69 +145,6 @@
       await tester.tap(find.byKey(key1));
       expect(_pointerDown, isTrue);
     });
-
-    testWidgets('semantics bounds are updated', (WidgetTester tester) async {
-      final GlobalKey fractionalTranslationKey = GlobalKey();
-      final GlobalKey textKey = GlobalKey();
-      Offset offset = const Offset(0.4, 0.4);
-
-      await tester.pumpWidget(
-        StatefulBuilder(
-          builder: (BuildContext context, StateSetter setState) {
-            return Directionality(
-              textDirection: TextDirection.ltr,
-              child: Center(
-                child: Semantics(
-                  explicitChildNodes: true,
-                  child: FractionalTranslation(
-                    key: fractionalTranslationKey,
-                    translation: offset,
-                    transformHitTests: true,
-                    child: GestureDetector(
-                      onTap: () {
-                        setState(() {
-                          offset = const Offset(0.8, 0.8);
-                        });
-                      },
-                      child: SizedBox(
-                        width: 100.0,
-                        height: 100.0,
-                        child: Text(
-                          'foo',
-                          key: textKey,
-                        ),
-                      ),
-                    ),
-                  ),
-                ),
-              ),
-            );
-          },
-        )
-      );
-
-      expect(
-        tester.getSemantics(find.byKey(textKey)).transform,
-        Matrix4(
-          3.0, 0.0, 0.0, 0.0,
-          0.0, 3.0, 0.0, 0.0,
-          0.0, 0.0, 1.0, 0.0,
-          1170.0, 870.0, 0.0, 1.0,
-        ),
-      );
-
-      await tester.tap(find.byKey(fractionalTranslationKey));
-      await tester.pump();
-      expect(
-        tester.getSemantics(find.byKey(textKey)).transform,
-        Matrix4(
-          3.0, 0.0, 0.0, 0.0,
-          0.0, 3.0, 0.0, 0.0,
-          0.0, 0.0, 1.0, 0.0,
-          1290.0, 990.0, 0.0, 1.0,
-        ),
-      );
-    });
   });
 
   group('Row', () {
diff --git a/packages/flutter/test/widgets/debug_test.dart b/packages/flutter/test/widgets/debug_test.dart
index f374493..ea46c85 100644
--- a/packages/flutter/test/widgets/debug_test.dart
+++ b/packages/flutter/test/widgets/debug_test.dart
@@ -74,7 +74,7 @@
           } finally {
             expect(error, isNotNull);
             expect(error.diagnostics.length, 4);
-            expect(error.diagnostics[2], isInstanceOf<DiagnosticsProperty<Element>>());
+            expect(error.diagnostics[2], isA<DiagnosticsProperty<Element>>());
             expect(
               error.toStringDeep(),
               equalsIgnoringHashCodes(
@@ -106,7 +106,7 @@
           } finally {
             expect(error, isNotNull);
             expect(error.diagnostics.length, 5);
-            expect(error.diagnostics[2], isInstanceOf<DiagnosticsProperty<Element>>());
+            expect(error.diagnostics[2], isA<DiagnosticsProperty<Element>>());
             expect(error.diagnostics.last.level, DiagnosticLevel.hint);
             expect(
               error.diagnostics.last.toStringDeep(),
@@ -147,7 +147,7 @@
     } finally {
       expect(error, isNotNull);
       expect(error.diagnostics.length, 4);
-      expect(error.diagnostics[1], isInstanceOf<DiagnosticsProperty<Widget>>());
+      expect(error.diagnostics[1], isA<DiagnosticsProperty<Widget>>());
       expect(error.diagnostics[1].style, DiagnosticsTreeStyle.errorProperty);
       expect(
         error.diagnostics[1].toStringDeep(),
@@ -190,7 +190,7 @@
     } finally {
       expect(error, isNotNull);
       expect(error.diagnostics.length, 3);
-      expect(error.diagnostics[1], isInstanceOf<DiagnosticsProperty<Widget>>());
+      expect(error.diagnostics[1], isA<DiagnosticsProperty<Widget>>());
       expect(error.diagnostics[1].style, DiagnosticsTreeStyle.errorProperty);
       expect(
         error.diagnostics[1].toStringDeep(),
diff --git a/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart b/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart
index db35bf8..14ad68c 100644
--- a/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart
+++ b/packages/flutter/test/widgets/draggable_scrollable_sheet_test.dart
@@ -105,7 +105,7 @@
         expect(find.text('Item 1'), findsOneWidget);
         expect(find.text('Item 21'), findsOneWidget);
         expect(find.text('Item 31'), findsOneWidget);
-      }, skip: isBrowser);
+      }, skip: isBrowser, variant: TargetPlatformVariant.all());
 
       testWidgets('Can be dragged down when not full height', (WidgetTester tester) async {
         await tester.pumpWidget(_boilerplate(null));
@@ -118,7 +118,7 @@
         expect(find.text('Item 1'), findsOneWidget);
         expect(find.text('Item 21'), findsNothing);
         expect(find.text('Item 36'), findsNothing);
-      }, skip: isBrowser);
+      }, skip: isBrowser, variant: TargetPlatformVariant.all());
 
       testWidgets('Can be dragged down when list is shorter than full height', (WidgetTester tester) async {
         await tester.pumpWidget(_boilerplate(null, itemCount: 30, initialChildSize: .25));
@@ -135,7 +135,7 @@
         await tester.pumpAndSettle();
         expect(find.text('Item 1').hitTestable(), findsOneWidget);
         expect(find.text('Item 29').hitTestable(), findsNothing);
-      }, skip: isBrowser);
+      }, skip: isBrowser, variant: TargetPlatformVariant.all());
 
       testWidgets('Can be dragged up and cover its container and scroll in single motion, and then dragged back down', (WidgetTester tester) async {
         int taps = 0;
@@ -164,7 +164,7 @@
         expect(find.text('Item 1'), findsOneWidget);
         expect(find.text('Item 18'), findsOneWidget);
         expect(find.text('Item 36'), findsNothing);
-      }, skip: isBrowser);
+      }, skip: isBrowser, variant: TargetPlatformVariant.all());
 
       testWidgets('Can be flung up gently', (WidgetTester tester) async {
         int taps = 0;
@@ -187,7 +187,7 @@
         expect(find.text('Item 21'), findsOneWidget);
         expect(find.text('Item 36'), findsOneWidget);
         expect(find.text('Item 70'), findsNothing);
-      }, skip: isBrowser);
+      }, skip: isBrowser, variant: TargetPlatformVariant.all());
 
       testWidgets('Can be flung up', (WidgetTester tester) async {
         int taps = 0;
@@ -208,7 +208,7 @@
         expect(find.text('Item 1'), findsNothing);
         expect(find.text('Item 21'), findsNothing);
         expect(find.text('Item 70'), findsOneWidget);
-      }, skip: isBrowser);
+      }, skip: isBrowser, variant: TargetPlatformVariant.all());
 
       testWidgets('Can be flung down when not full height', (WidgetTester tester) async {
         await tester.pumpWidget(_boilerplate(null));
@@ -221,7 +221,7 @@
         expect(find.text('Item 1'), findsOneWidget);
         expect(find.text('Item 21'), findsNothing);
         expect(find.text('Item 36'), findsNothing);
-      }, skip: isBrowser);
+      }, skip: isBrowser, variant: TargetPlatformVariant.all());
 
       testWidgets('Can be flung up and then back down', (WidgetTester tester) async {
         int taps = 0;
@@ -260,7 +260,7 @@
         expect(find.text('Item 1'), findsOneWidget);
         expect(find.text('Item 21'), findsNothing);
         expect(find.text('Item 70'), findsNothing);
-      }, skip: isBrowser);
+      }, skip: isBrowser, variant: TargetPlatformVariant.all());
 
       debugDefaultTargetPlatformOverride = null;
     });
diff --git a/packages/flutter/test/widgets/drawer_test.dart b/packages/flutter/test/widgets/drawer_test.dart
index 5fe4c4c..70e73fb 100644
--- a/packages/flutter/test/widgets/drawer_test.dart
+++ b/packages/flutter/test/widgets/drawer_test.dart
@@ -304,9 +304,7 @@
     expect(buttonPressed, equals(true));
   });
 
-  testWidgets('Dismissible ModalBarrier includes button in semantic tree on iOS', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
+  testWidgets('Dismissible ModalBarrier includes button in semantic tree', (WidgetTester tester) async {
     final SemanticsTester semantics = SemanticsTester(tester);
     final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
 
@@ -331,9 +329,7 @@
     expect(semantics, includesNodeWith(label: 'Dismiss'));
 
     semantics.dispose();
-
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Dismissible ModalBarrier is hidden on Android (back button is used to dismiss)', (WidgetTester tester) async {
     final SemanticsTester semantics = SemanticsTester(tester);
@@ -361,7 +357,7 @@
     expect(semantics, isNot(includesNodeWith(label: 'Dismiss')));
 
     semantics.dispose();
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.android }));
 
   testWidgets('Drawer contains route semantics flags', (WidgetTester tester) async {
     final SemanticsTester semantics = SemanticsTester(tester);
diff --git a/packages/flutter/test/widgets/editable_text_cursor_test.dart b/packages/flutter/test/widgets/editable_text_cursor_test.dart
index c343917..7844c4c 100644
--- a/packages/flutter/test/widgets/editable_text_cursor_test.dart
+++ b/packages/flutter/test/widgets/editable_text_cursor_test.dart
@@ -145,10 +145,9 @@
     );
   });
 
-  testWidgets('Cursor animates on iOS', (WidgetTester tester) async {
-    final Widget widget = MaterialApp(
-      theme: ThemeData(platform: TargetPlatform.iOS),
-      home: const Material(
+  testWidgets('Cursor animates', (WidgetTester tester) async {
+    const Widget widget = MaterialApp(
+      home: Material(
         child: TextField(
           maxLines: 3,
         ),
@@ -200,7 +199,7 @@
     // Cursor starts coming back.
     expect(renderEditable.cursorColor.alpha, 79);
     expect(renderEditable, paints..rrect(color: const Color(0x4f2196f3)));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Cursor does not animate on Android', (WidgetTester tester) async {
     const Widget widget = MaterialApp(
@@ -241,11 +240,10 @@
     expect(renderEditable, paintsExactlyCountTimes(#drawRect, 0));
   });
 
-  testWidgets('Cursor does not animates on iOS when debugDeterministicCursor is set', (WidgetTester tester) async {
+  testWidgets('Cursor does not animates when debugDeterministicCursor is set', (WidgetTester tester) async {
     EditableText.debugDeterministicCursor = true;
-    final Widget widget = MaterialApp(
-      theme: ThemeData(platform: TargetPlatform.iOS),
-      home: const Material(
+    const Widget widget = MaterialApp(
+      home: Material(
         child: TextField(
           maxLines: 3,
         ),
@@ -277,7 +275,7 @@
     expect(renderEditable, paints..rrect(color: const Color(0xff2196f3)));
 
     EditableText.debugDeterministicCursor = false;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Cursor does not animate on Android when debugDeterministicCursor is set', (WidgetTester tester) async {
     EditableText.debugDeterministicCursor = true;
@@ -346,10 +344,9 @@
     expect(renderEditable, paintsExactlyCountTimes(#drawRect, 0));
   });
 
-  testWidgets('Cursor radius is 2.0 on iOS', (WidgetTester tester) async {
-    final Widget widget = MaterialApp(
-      theme: ThemeData(platform: TargetPlatform.iOS),
-      home: const Material(
+  testWidgets('Cursor radius is 2.0', (WidgetTester tester) async {
+    const Widget widget = MaterialApp(
+      home: Material(
         child: TextField(
           maxLines: 3,
         ),
@@ -361,7 +358,7 @@
     final RenderEditable renderEditable = editableTextState.renderEditable;
 
     expect(renderEditable.cursorRadius, const Radius.circular(2.0));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Cursor gets placed correctly after going out of bounds', (WidgetTester tester) async {
     const String text = 'hello world this is fun and cool and awesome!';
@@ -645,9 +642,7 @@
     expect(controller.selection.baseOffset, text.length);
   }, skip: isBrowser);
 
-  testWidgets('Floating cursor is painted on iOS', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
+  testWidgets('Floating cursor is painted', (WidgetTester tester) async {
     final TextEditingController controller = TextEditingController();
     const TextStyle textStyle = TextStyle();
     const String text = 'hello world this is fun and cool and awesome!';
@@ -656,7 +651,6 @@
 
     await tester.pumpWidget(
       MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
         home: Padding(
           padding: const EdgeInsets.only(top: 0.25),
           child: Material(
@@ -731,16 +725,13 @@
     editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End));
     await tester.pumpAndSettle();
     debugDefaultTargetPlatformOverride = null;
-  }, skip: isBrowser);
+  }, skip: isBrowser, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('cursor layout iOS', (WidgetTester tester) async {
+  testWidgets('cursor layout', (WidgetTester tester) async {
     final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
 
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
     String changedValue;
     final Widget widget = MaterialApp(
-      theme: ThemeData(platform: TargetPlatform.iOS),
       home: RepaintBoundary(
         key: const ValueKey<int>(1),
         child: Column(
@@ -793,6 +784,5 @@
       find.byKey(const ValueKey<int>(1)),
       matchesGoldenFile('editable_text_test.2.png'),
     );
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 }
diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart
index 53c6fe3..40f7b05 100644
--- a/packages/flutter/test/widgets/editable_text_test.dart
+++ b/packages/flutter/test/widgets/editable_text_test.dart
@@ -3757,9 +3757,7 @@
   });
 
   // Regression test for https://github.com/flutter/flutter/issues/31287
-  testWidgets('iOS text selection handle visibility', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
+  testWidgets('text selection handle visibility', (WidgetTester tester) async {
     // Text with two separate words to select.
     const String testText = 'XXXXX          XXXXX';
     final TextEditingController controller = TextEditingController(text: testText);
@@ -3924,9 +3922,7 @@
     // at all. Again, both handles should be invisible.
     scrollable.controller.jumpTo(0);
     await verifyVisibility(HandlePositionInViewport.rightEdge, false, HandlePositionInViewport.rightEdge, false);
-
-    debugDefaultTargetPlatformOverride = null;
-  }, skip: isBrowser);
+  }, skip: isBrowser, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('scrolling doesn\'t bounce', (WidgetTester tester) async {
     // 3 lines of text, where the last line overflows and requires scrolling.
diff --git a/packages/flutter/test/widgets/flow_test.dart b/packages/flutter/test/widgets/flow_test.dart
index df522f1..4386b15 100644
--- a/packages/flutter/test/widgets/flow_test.dart
+++ b/packages/flutter/test/widgets/flow_test.dart
@@ -150,9 +150,9 @@
     ContainerLayer layer = RendererBinding.instance.renderView.debugLayer;
     while (layer != null && layer is! OpacityLayer)
       layer = layer.firstChild as ContainerLayer;
-    expect(layer, isInstanceOf<OpacityLayer>());
+    expect(layer, isA<OpacityLayer>());
     final OpacityLayer opacityLayer = layer as OpacityLayer;
     expect(opacityLayer.alpha, equals(opacity * 255));
-    expect(layer.firstChild, isInstanceOf<TransformLayer>());
+    expect(layer.firstChild, isA<TransformLayer>());
   });
 }
diff --git a/packages/flutter/test/widgets/heroes_test.dart b/packages/flutter/test/widgets/heroes_test.dart
index d150287..acd9f19 100644
--- a/packages/flutter/test/widgets/heroes_test.dart
+++ b/packages/flutter/test/widgets/heroes_test.dart
@@ -543,7 +543,7 @@
     final FlutterError error = exception as FlutterError;
     expect(error.diagnostics.length, 3);
     final DiagnosticsNode last = error.diagnostics.last;
-    expect(last, isInstanceOf<DiagnosticsProperty<StatefulElement>>());
+    expect(last, isA<DiagnosticsProperty<StatefulElement>>());
     expect(
       last.toStringDeep(),
       equalsIgnoringHashCodes(
@@ -1614,10 +1614,7 @@
 
   testWidgets('Heroes do not transition on back gestures by default', (WidgetTester tester) async {
     await tester.pumpWidget(MaterialApp(
-      theme: ThemeData(
-        platform: TargetPlatform.iOS,
-      ),
-      routes: routes,
+     routes: routes,
     ));
 
     expect(find.byKey(firstKey), isOnstage);
@@ -1652,14 +1649,11 @@
     expect(find.byKey(firstKey), isInCard);
     expect(find.byKey(secondKey), isOnstage);
     expect(find.byKey(secondKey), isInCard);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Heroes can transition on gesture in one frame', (WidgetTester tester) async {
     transitionFromUserGestures = true;
     await tester.pumpWidget(MaterialApp(
-      theme: ThemeData(
-        platform: TargetPlatform.iOS,
-      ),
       routes: routes,
     ));
 
@@ -1698,14 +1692,11 @@
     expect(find.byKey(firstKey), isOnstage);
     expect(find.byKey(firstKey), isInCard);
     expect(find.byKey(secondKey), findsNothing);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Heroes animate should hide destination hero and display original hero in case of dismissed', (WidgetTester tester) async {
     transitionFromUserGestures = true;
     await tester.pumpWidget(MaterialApp(
-      theme: ThemeData(
-        platform: TargetPlatform.iOS,
-      ),
       routes: routes,
     ));
 
@@ -1737,7 +1728,7 @@
     expect(find.byKey(firstKey), findsNothing);
     expect(find.byKey(secondKey), isOnstage);
     expect(find.byKey(secondKey), isInCard);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Handles transitions when a non-default initial route is set', (WidgetTester tester) async {
     await tester.pumpWidget(MaterialApp(
@@ -2298,9 +2289,6 @@
   testWidgets('Remove user gesture driven flights when the gesture is invalid', (WidgetTester tester) async {
     transitionFromUserGestures = true;
     await tester.pumpWidget(MaterialApp(
-      theme: ThemeData(
-        platform: TargetPlatform.iOS,
-      ),
       routes: routes,
     ));
 
@@ -2324,7 +2312,7 @@
     // The simple route should still be on top.
     expect(find.byKey(simpleKey), findsOneWidget);
     expect(tester.takeException(), isNull);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   // Regression test for https://github.com/flutter/flutter/issues/40239.
   testWidgets(
diff --git a/packages/flutter/test/widgets/image_test.dart b/packages/flutter/test/widgets/image_test.dart
index db2d5e7..ff65608 100644
--- a/packages/flutter/test/widgets/image_test.dart
+++ b/packages/flutter/test/widgets/image_test.dart
@@ -1101,14 +1101,14 @@
     expect(find.byType(Center), findsOneWidget);
     expect(find.byType(Padding), findsOneWidget);
     expect(find.byType(RawImage), findsOneWidget);
-    expect(tester.widget<Padding>(find.byType(Padding)).child, isInstanceOf<RawImage>());
+    expect(tester.widget<Padding>(find.byType(Padding)).child, isA<RawImage>());
     streamCompleter.setData(chunkEvent: const ImageChunkEvent(cumulativeBytesLoaded: 10, expectedTotalBytes: 100));
     await tester.pump();
     expect(find.byType(Center), findsOneWidget);
     expect(find.byType(Padding), findsOneWidget);
     expect(find.byType(RawImage), findsOneWidget);
-    expect(tester.widget<Center>(find.byType(Center)).child, isInstanceOf<Padding>());
-    expect(tester.widget<Padding>(find.byType(Padding)).child, isInstanceOf<RawImage>());
+    expect(tester.widget<Center>(find.byType(Center)).child, isA<Padding>());
+    expect(tester.widget<Padding>(find.byType(Padding)).child, isA<RawImage>());
   }, skip: isBrowser);
 
   testWidgets('Image state handles loadingBuilder update from null to non-null', (WidgetTester tester) async {
diff --git a/packages/flutter/test/widgets/list_wheel_scroll_view_test.dart b/packages/flutter/test/widgets/list_wheel_scroll_view_test.dart
index d871f17..0d86ddb 100644
--- a/packages/flutter/test/widgets/list_wheel_scroll_view_test.dart
+++ b/packages/flutter/test/widgets/list_wheel_scroll_view_test.dart
@@ -1203,8 +1203,6 @@
     });
 
     testWidgets('high fling velocities lands exactly on items', (WidgetTester tester) async {
-      debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
       final FixedExtentScrollController controller = FixedExtentScrollController(initialItem: 40);
       final List<double> scrolledPositions = <double>[];
 
@@ -1252,9 +1250,7 @@
       expect(controller.selectedItem, 49);
       // More importantly, lands tightly on 49.
       expect(scrolledPositions.last, moreOrLessEquals(49 * 100.0, epsilon: 0.3));
-
-      debugDefaultTargetPlatformOverride = null;
-    });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
   });
 
   testWidgets('ListWheelScrollView getOffsetToReveal', (WidgetTester tester) async {
diff --git a/packages/flutter/test/widgets/media_query_test.dart b/packages/flutter/test/widgets/media_query_test.dart
index ebc09fe..966fa90 100644
--- a/packages/flutter/test/widgets/media_query_test.dart
+++ b/packages/flutter/test/widgets/media_query_test.dart
@@ -25,7 +25,7 @@
     expect(exception ,isFlutterError);
     final FlutterError error = exception as FlutterError;
     expect(error.diagnostics.length, 3);
-    expect(error.diagnostics.last, isInstanceOf<DiagnosticsProperty<Element>>());
+    expect(error.diagnostics.last, isA<DiagnosticsProperty<Element>>());
     expect(
       error.toStringDeep(),
       equalsIgnoringHashCodes(
diff --git a/packages/flutter/test/widgets/modal_barrier_test.dart b/packages/flutter/test/widgets/modal_barrier_test.dart
index 1a29f7e..c501933 100644
--- a/packages/flutter/test/widgets/modal_barrier_test.dart
+++ b/packages/flutter/test/widgets/modal_barrier_test.dart
@@ -340,8 +340,6 @@
   });
 
   testWidgets('Dismissible ModalBarrier includes button in semantic tree on iOS', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
-
     final SemanticsTester semantics = SemanticsTester(tester);
     await tester.pumpWidget(const Directionality(
       textDirection: TextDirection.ltr,
@@ -364,8 +362,7 @@
     expect(semantics, hasSemantics(expectedSemantics, ignoreId: true));
 
     semantics.dispose();
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Dismissible ModalBarrier is hidden on Android (back button is used to dismiss)', (WidgetTester tester) async {
     final SemanticsTester semantics = SemanticsTester(tester);
diff --git a/packages/flutter/test/widgets/multichild_test.dart b/packages/flutter/test/widgets/multichild_test.dart
index fe6242a..c51429f 100644
--- a/packages/flutter/test/widgets/multichild_test.dart
+++ b/packages/flutter/test/widgets/multichild_test.dart
@@ -13,12 +13,12 @@
     (Element element) => element is MultiChildRenderObjectElement
   ));
   expect(element, isNotNull);
-  expect(element.renderObject is RenderStack, isTrue);
+  expect(element.renderObject, isA<RenderStack>());
   final RenderStack renderObject = element.renderObject as RenderStack;
   try {
     RenderObject child = renderObject.firstChild;
     for (final BoxDecoration decoration in expectedDecorations) {
-      expect(child is RenderDecoratedBox, isTrue);
+      expect(child, isA<RenderDecoratedBox>());
       final RenderDecoratedBox decoratedBox = child as RenderDecoratedBox;
       expect(decoratedBox.decoration, equals(decoration));
       final StackParentData decoratedBoxParentData = decoratedBox.parentData as StackParentData;
diff --git a/packages/flutter/test/widgets/navigator_test.dart b/packages/flutter/test/widgets/navigator_test.dart
index 031040c..b520cfd 100644
--- a/packages/flutter/test/widgets/navigator_test.dart
+++ b/packages/flutter/test/widgets/navigator_test.dart
@@ -180,7 +180,7 @@
     );
     await tester.pumpWidget(widget);
     await tester.tap(find.byKey(targetKey));
-    expect(exception, isInstanceOf<FlutterError>());
+    expect(exception, isFlutterError);
     expect('$exception', startsWith('Navigator operation requested with a context'));
   });
 
@@ -1258,7 +1258,7 @@
     );
 
     final dynamic exception = tester.takeException();
-    expect(exception is String, isTrue);
+    expect(exception, isA<String>());
     expect(exception.startsWith('Could not navigate to initial route.'), isTrue);
 
     // Only the root route should've been pushed.
@@ -1327,7 +1327,7 @@
       expect(exception, isFlutterError);
       final FlutterError error = exception as FlutterError;
       expect(error, isNotNull);
-      expect(error.diagnostics.last, isInstanceOf<DiagnosticsProperty<NavigatorState>>());
+      expect(error.diagnostics.last, isA<DiagnosticsProperty<NavigatorState>>());
       expect(
         error.toStringDeep(),
         equalsIgnoringHashCodes(
@@ -1354,7 +1354,7 @@
       expect(exception, isFlutterError);
       final FlutterError error = exception as FlutterError;
       expect(error, isNotNull);
-      expect(error.diagnostics.last, isInstanceOf<DiagnosticsProperty<NavigatorState>>());
+      expect(error.diagnostics.last, isA<DiagnosticsProperty<NavigatorState>>());
       expect(
         error.toStringDeep(),
         equalsIgnoringHashCodes(
diff --git a/packages/flutter/test/widgets/nested_scroll_view_test.dart b/packages/flutter/test/widgets/nested_scroll_view_test.dart
index dd9c865..fa7ed6c 100644
--- a/packages/flutter/test/widgets/nested_scroll_view_test.dart
+++ b/packages/flutter/test/widgets/nested_scroll_view_test.dart
@@ -113,7 +113,6 @@
 
 void main() {
   testWidgets('NestedScrollView overscroll and release and hold', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     await tester.pumpWidget(buildTest());
     expect(find.text('aaa2'), findsOneWidget);
     await tester.pump(const Duration(milliseconds: 250));
@@ -128,10 +127,8 @@
     // TODO(ianh): Once we improve how we handle scrolling down from overscroll,
     // the following expectation should switch to 200.0.
     expect(tester.renderObject<RenderBox>(find.byType(AppBar)).size.height, 120.0);
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
   testWidgets('NestedScrollView overscroll and release and hold', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     await tester.pumpWidget(buildTest());
     expect(find.text('aaa2'), findsOneWidget);
     await tester.pump(const Duration(milliseconds: 250));
@@ -149,10 +146,8 @@
     await tester.pump(const Duration(milliseconds: 10));
     expect(find.text('aaa2'), findsNothing);
     await tester.pump(const Duration(milliseconds: 1000));
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
   testWidgets('NestedScrollView overscroll and release', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     await tester.pumpWidget(buildTest());
     expect(find.text('aaa2'), findsOneWidget);
     await tester.pump(const Duration(milliseconds: 500));
@@ -164,8 +159,10 @@
     await gesture1.up();
     await tester.pumpAndSettle();
     expect(find.text('aaa2'), findsOneWidget);
-    debugDefaultTargetPlatformOverride = null;
-  }, skip: true); // https://github.com/flutter/flutter/issues/9040
+  },
+  skip: true,  // https://github.com/flutter/flutter/issues/9040
+  variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
+
   testWidgets('NestedScrollView', (WidgetTester tester) async {
     await tester.pumpWidget(buildTest());
     expect(find.text('aaa2'), findsOneWidget);
@@ -610,12 +607,11 @@
     debugDisableShadows = true;
   });
 
-  testWidgets('NestedScrollView and iOS bouncing', (WidgetTester tester) async {
+  testWidgets('NestedScrollView and bouncing', (WidgetTester tester) async {
     // This verifies that overscroll bouncing works correctly on iOS. For
     // example, this checks that if you pull to overscroll, friction is applied;
     // it also makes sure that if you scroll back the other way, the scroll
     // positions of the inner and outer list don't have a discontinuity.
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     const Key key1 = ValueKey<int>(1);
     const Key key2 = ValueKey<int>(2);
     await tester.pumpWidget(
@@ -675,7 +671,7 @@
     expect(tester.getRect(find.byKey(key1)), const Rect.fromLTWH(0.0, 0.0, 800.0, 100.0));
     await gesture.up();
     debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   // Regression test for https://github.com/flutter/flutter/issues/39963.
   testWidgets('NestedScrollView with SliverOverlapAbsorber in or out of the first screen', (WidgetTester tester) async {
diff --git a/packages/flutter/test/widgets/overlay_test.dart b/packages/flutter/test/widgets/overlay_test.dart
index 0453fcd..afa01f4 100644
--- a/packages/flutter/test/widgets/overlay_test.dart
+++ b/packages/flutter/test/widgets/overlay_test.dart
@@ -634,9 +634,9 @@
                 'The most common way to add an Overlay to an application is to\n'
                 'include a MaterialApp or Navigator widget in the runApp() call.\n',
               ));
-              expect(error.diagnostics[3], isInstanceOf<DiagnosticsProperty<Widget>>());
+              expect(error.diagnostics[3], isA<DiagnosticsProperty<Widget>>());
               expect(error.diagnostics[3].value, debugRequiredFor);
-              expect(error.diagnostics[4], isInstanceOf<DiagnosticsProperty<Element>>());
+              expect(error.diagnostics[4], isA<DiagnosticsProperty<Element>>());
               expect(error.toStringDeep(), equalsIgnoringHashCodes(
                 'FlutterError\n'
                 '   No Overlay widget found.\n'
diff --git a/packages/flutter/test/widgets/page_transitions_test.dart b/packages/flutter/test/widgets/page_transitions_test.dart
index 1120c6e..290ed08 100644
--- a/packages/flutter/test/widgets/page_transitions_test.dart
+++ b/packages/flutter/test/widgets/page_transitions_test.dart
@@ -157,10 +157,7 @@
       ),
     };
 
-    await tester.pumpWidget(MaterialApp(
-      routes: routes,
-      theme: ThemeData(platform: TargetPlatform.iOS),
-    ));
+    await tester.pumpWidget(MaterialApp(routes: routes));
 
     Navigator.pushNamed(containerKey1.currentContext, '/settings');
 
@@ -199,7 +196,7 @@
     settingsOffset = tester.getTopLeft(find.text('Settings'));
     expect(settingsOffset.dx, greaterThan(100.0));
     expect(settingsOffset.dy, 100.0);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Check back gesture doesn\'t start during transitions', (WidgetTester tester) async {
     final GlobalKey containerKey1 = GlobalKey();
@@ -209,10 +206,7 @@
       '/settings': (_) => Scaffold(key: containerKey2, body: const Text('Settings')),
     };
 
-    await tester.pumpWidget(MaterialApp(
-      routes: routes,
-      theme: ThemeData(platform: TargetPlatform.iOS),
-    ));
+    await tester.pumpWidget(MaterialApp(routes: routes));
 
     Navigator.pushNamed(containerKey1.currentContext, '/settings');
 
@@ -245,7 +239,7 @@
 
     expect(find.text('Home'), isOnstage);
     expect(find.text('Settings'), findsNothing);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   // Tests bug https://github.com/flutter/flutter/issues/6451
   testWidgets('Check back gesture with a persistent bottom sheet showing', (WidgetTester tester) async {
@@ -256,10 +250,7 @@
       '/sheet': (_) => PersistentBottomSheetTest(key: containerKey2),
     };
 
-    await tester.pumpWidget(MaterialApp(
-      routes: routes,
-      theme: ThemeData(platform: TargetPlatform.iOS),
-    ));
+    await tester.pumpWidget(MaterialApp(routes: routes));
 
     Navigator.pushNamed(containerKey1.currentContext, '/sheet');
 
@@ -302,7 +293,7 @@
 
     // Sheet did not call setState (since the gesture did nothing).
     expect(sheet.setStateCalled, isFalse);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Test completed future', (WidgetTester tester) async {
     final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
diff --git a/packages/flutter/test/widgets/page_view_test.dart b/packages/flutter/test/widgets/page_view_test.dart
index f48c62c..b2ba936 100644
--- a/packages/flutter/test/widgets/page_view_test.dart
+++ b/packages/flutter/test/widgets/page_view_test.dart
@@ -83,7 +83,6 @@
 
   testWidgets('PageView does not squish when overscrolled', (WidgetTester tester) async {
     await tester.pumpWidget(MaterialApp(
-      theme: ThemeData(platform: TargetPlatform.iOS),
       home: PageView(
         children: List<Widget>.generate(10, (int i) {
           return Container(
@@ -113,7 +112,7 @@
 
     expect(leftOf(0), lessThan(0.0));
     expect(sizeOf(0), equals(const Size(800.0, 600.0)));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('PageController control test', (WidgetTester tester) async {
     final PageController controller = PageController(initialPage: 4);
diff --git a/packages/flutter/test/widgets/parent_data_test.dart b/packages/flutter/test/widgets/parent_data_test.dart
index e7ba8de..52390c1 100644
--- a/packages/flutter/test/widgets/parent_data_test.dart
+++ b/packages/flutter/test/widgets/parent_data_test.dart
@@ -22,14 +22,14 @@
     find.byElementPredicate((Element element) => element is MultiChildRenderObjectElement)
   );
   expect(element, isNotNull);
-  expect(element.renderObject is RenderStack, isTrue);
+  expect(element.renderObject, isA<RenderStack>());
   final RenderStack renderObject = element.renderObject as RenderStack;
   try {
     RenderObject child = renderObject.firstChild;
     for (final TestParentData expected in expectedParentData) {
-      expect(child is RenderDecoratedBox, isTrue);
+      expect(child, isA<RenderDecoratedBox>());
       final RenderDecoratedBox decoratedBox = child as RenderDecoratedBox;
-      expect(decoratedBox.parentData is StackParentData, isTrue);
+      expect(decoratedBox.parentData, isA<StackParentData>());
       final StackParentData parentData = decoratedBox.parentData as StackParentData;
       expect(parentData.top, equals(expected.top));
       expect(parentData.right, equals(expected.right));
diff --git a/packages/flutter/test/widgets/physical_model_test.dart b/packages/flutter/test/widgets/physical_model_test.dart
index dd495ee..0780f5a 100644
--- a/packages/flutter/test/widgets/physical_model_test.dart
+++ b/packages/flutter/test/widgets/physical_model_test.dart
@@ -105,7 +105,7 @@
     );
 
     final dynamic exception = tester.takeException();
-    expect(exception, isInstanceOf<FlutterError>());
+    expect(exception, isFlutterError);
     expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
     expect(exception.diagnostics.first.toString(), startsWith('A RenderFlex overflowed by '));
     await expectLater(
diff --git a/packages/flutter/test/widgets/platform_view_test.dart b/packages/flutter/test/widgets/platform_view_test.dart
index 2db80b5..b37ef08 100644
--- a/packages/flutter/test/widgets/platform_view_test.dart
+++ b/packages/flutter/test/widgets/platform_view_test.dart
@@ -128,7 +128,7 @@
       );
 
       final Layer textureParentLayer = tester.layers[tester.layers.length - 2];
-      expect(textureParentLayer, isInstanceOf<ClipRectLayer>());
+      expect(textureParentLayer, isA<ClipRectLayer>());
       final ClipRectLayer clipRect = textureParentLayer as ClipRectLayer;
       expect(clipRect.clipRect, const Rect.fromLTWH(0.0, 0.0, 100.0, 50.0));
       expect(
diff --git a/packages/flutter/test/widgets/render_object_widget_test.dart b/packages/flutter/test/widgets/render_object_widget_test.dart
index d122290..6b781cd 100644
--- a/packages/flutter/test/widgets/render_object_widget_test.dart
+++ b/packages/flutter/test/widgets/render_object_widget_test.dart
@@ -52,7 +52,7 @@
     SingleChildRenderObjectElement element =
         tester.element(find.byElementType(SingleChildRenderObjectElement));
     expect(element, isNotNull);
-    expect(element.renderObject is RenderDecoratedBox, isTrue);
+    expect(element.renderObject, isA<RenderDecoratedBox>());
     RenderDecoratedBox renderObject = element.renderObject as RenderDecoratedBox;
     expect(renderObject.decoration, equals(kBoxDecorationA));
     expect(renderObject.position, equals(DecorationPosition.background));
@@ -60,7 +60,7 @@
     await tester.pumpWidget(DecoratedBox(decoration: kBoxDecorationB));
     element = tester.element(find.byElementType(SingleChildRenderObjectElement));
     expect(element, isNotNull);
-    expect(element.renderObject is RenderDecoratedBox, isTrue);
+    expect(element.renderObject, isA<RenderDecoratedBox>());
     renderObject = element.renderObject as RenderDecoratedBox;
     expect(renderObject.decoration, equals(kBoxDecorationB));
     expect(renderObject.position, equals(DecorationPosition.background));
@@ -72,12 +72,12 @@
       final SingleChildRenderObjectElement element =
           tester.firstElement(find.byElementType(SingleChildRenderObjectElement));
       expect(element, isNotNull);
-      expect(element.renderObject is RenderDecoratedBox, isTrue);
+      expect(element.renderObject, isA<RenderDecoratedBox>());
       final RenderDecoratedBox renderObject = element.renderObject as RenderDecoratedBox;
       expect(renderObject.decoration, equals(kBoxDecorationA));
       expect(renderObject.position, equals(DecorationPosition.background));
       expect(renderObject.child, isNotNull);
-      expect(renderObject.child is RenderDecoratedBox, isTrue);
+      expect(renderObject.child, isA<RenderDecoratedBox>());
       final RenderDecoratedBox child = renderObject.child as RenderDecoratedBox;
       expect(child.decoration, equals(kBoxDecorationB));
       expect(child.position, equals(DecorationPosition.background));
@@ -88,7 +88,7 @@
       final SingleChildRenderObjectElement element =
           tester.element(find.byElementType(SingleChildRenderObjectElement));
       expect(element, isNotNull);
-      expect(element.renderObject is RenderDecoratedBox, isTrue);
+      expect(element.renderObject, isA<RenderDecoratedBox>());
       final RenderDecoratedBox renderObject = element.renderObject as RenderDecoratedBox;
       expect(renderObject.decoration, equals(kBoxDecorationA));
       expect(renderObject.position, equals(DecorationPosition.background));
@@ -164,12 +164,12 @@
 
     SingleChildRenderObjectElement element =
         tester.firstElement(find.byElementType(SingleChildRenderObjectElement));
-    expect(element.renderObject is RenderDecoratedBox, isTrue);
+    expect(element.renderObject, isA<RenderDecoratedBox>());
     final RenderDecoratedBox parent = element.renderObject as RenderDecoratedBox;
-    expect(parent.child is RenderDecoratedBox, isTrue);
+    expect(parent.child, isA<RenderDecoratedBox>());
     final RenderDecoratedBox child = parent.child as RenderDecoratedBox;
     expect(child.decoration, equals(kBoxDecorationB));
-    expect(child.child is RenderDecoratedBox, isTrue);
+    expect(child.child, isA<RenderDecoratedBox>());
     final RenderDecoratedBox grandChild = child.child as RenderDecoratedBox;
     expect(grandChild.decoration, equals(kBoxDecorationC));
     expect(grandChild.child, isNull);
@@ -180,7 +180,7 @@
 
     element =
         tester.element(find.byElementType(SingleChildRenderObjectElement));
-    expect(element.renderObject is RenderDecoratedBox, isTrue);
+    expect(element.renderObject, isA<RenderDecoratedBox>());
     expect(element.renderObject, equals(parent));
     expect(parent.child, isNull);
 
diff --git a/packages/flutter/test/widgets/routes_test.dart b/packages/flutter/test/widgets/routes_test.dart
index 8db268c..17c04ef0 100644
--- a/packages/flutter/test/widgets/routes_test.dart
+++ b/packages/flutter/test/widgets/routes_test.dart
@@ -48,7 +48,7 @@
 
   @override
   void didReplace(Route<dynamic> oldRoute) {
-    expect(oldRoute, isInstanceOf<TestRoute>());
+    expect(oldRoute, isA<TestRoute>());
     final TestRoute castRoute = oldRoute as TestRoute;
     log('didReplace ${castRoute.name}');
     super.didReplace(castRoute);
@@ -65,7 +65,7 @@
 
   @override
   void didPopNext(Route<dynamic> nextRoute) {
-    expect(nextRoute, isInstanceOf<TestRoute>());
+    expect(nextRoute, isA<TestRoute>());
     final TestRoute castRoute = nextRoute as TestRoute;
     log('didPopNext ${castRoute.name}');
     super.didPopNext(castRoute);
@@ -73,7 +73,7 @@
 
   @override
   void didChangeNext(Route<dynamic> nextRoute) {
-    expect(nextRoute, anyOf(isNull, isInstanceOf<TestRoute>()));
+    expect(nextRoute, anyOf(isNull, isA<TestRoute>()));
     final TestRoute castRoute = nextRoute as TestRoute;
     log('didChangeNext ${castRoute?.name}');
     super.didChangeNext(castRoute);
diff --git a/packages/flutter/test/widgets/scroll_behavior_test.dart b/packages/flutter/test/widgets/scroll_behavior_test.dart
index 83d5865..2b5d130 100644
--- a/packages/flutter/test/widgets/scroll_behavior_test.dart
+++ b/packages/flutter/test/widgets/scroll_behavior_test.dart
@@ -47,7 +47,7 @@
 
     expect(behavior, isNotNull);
     expect(behavior.flag, isTrue);
-    expect(position.physics, isInstanceOf<ClampingScrollPhysics>());
+    expect(position.physics, isA<ClampingScrollPhysics>());
     ScrollMetrics metrics = position.copyWith();
     expect(metrics.extentAfter, equals(400.0));
     expect(metrics.viewportDimension, equals(600.0));
@@ -62,7 +62,7 @@
 
     expect(behavior, isNotNull);
     expect(behavior.flag, isFalse);
-    expect(position.physics, isInstanceOf<BouncingScrollPhysics>());
+    expect(position.physics, isA<BouncingScrollPhysics>());
     // Regression test for https://github.com/flutter/flutter/issues/5856
     metrics = position.copyWith();
     expect(metrics.extentAfter, equals(400.0));
diff --git a/packages/flutter/test/widgets/scroll_notification_test.dart b/packages/flutter/test/widgets/scroll_notification_test.dart
index 0801b7e..adb0598 100644
--- a/packages/flutter/test/widgets/scroll_notification_test.dart
+++ b/packages/flutter/test/widgets/scroll_notification_test.dart
@@ -24,7 +24,7 @@
 
     final TestGesture gesture = await tester.startGesture(const Offset(100.0, 100.0));
     await tester.pump(const Duration(seconds: 1));
-    expect(notification, isInstanceOf<ScrollStartNotification>());
+    expect(notification, isA<ScrollStartNotification>());
     expect(notification.depth, equals(0));
     final ScrollStartNotification start = notification as ScrollStartNotification;
     expect(start.dragDetails, isNotNull);
@@ -32,7 +32,7 @@
 
     await gesture.moveBy(const Offset(-10.0, -10.0));
     await tester.pump(const Duration(seconds: 1));
-    expect(notification, isInstanceOf<ScrollUpdateNotification>());
+    expect(notification, isA<ScrollUpdateNotification>());
     expect(notification.depth, equals(0));
     final ScrollUpdateNotification update = notification as ScrollUpdateNotification;
     expect(update.dragDetails, isNotNull);
@@ -41,7 +41,7 @@
 
     await gesture.up();
     await tester.pump(const Duration(seconds: 1));
-    expect(notification, isInstanceOf<ScrollEndNotification>());
+    expect(notification, isA<ScrollEndNotification>());
     expect(notification.depth, equals(0));
     final ScrollEndNotification end = notification as ScrollEndNotification;
     expect(end.dragDetails, isNotNull);
diff --git a/packages/flutter/test/widgets/scroll_physics_test.dart b/packages/flutter/test/widgets/scroll_physics_test.dart
index 6c1dc3b..6d830c2 100644
--- a/packages/flutter/test/widgets/scroll_physics_test.dart
+++ b/packages/flutter/test/widgets/scroll_physics_test.dart
@@ -239,10 +239,10 @@
     } finally {
       expect(error, isNotNull);
       expect(error.diagnostics.length, 4);
-      expect(error.diagnostics[2], isInstanceOf<DiagnosticsProperty<ScrollPhysics>>());
+      expect(error.diagnostics[2], isA<DiagnosticsProperty<ScrollPhysics>>());
       expect(error.diagnostics[2].style, DiagnosticsTreeStyle.errorProperty);
       expect(error.diagnostics[2].value, physics);
-      expect(error.diagnostics[3], isInstanceOf<DiagnosticsProperty<ScrollMetrics>>());
+      expect(error.diagnostics[3], isA<DiagnosticsProperty<ScrollMetrics>>());
       expect(error.diagnostics[3].style, DiagnosticsTreeStyle.errorProperty);
       expect(error.diagnostics[3].value, position);
       // RegExp matcher is required here due to flutter web and flutter mobile generating
diff --git a/packages/flutter/test/widgets/scroll_view_test.dart b/packages/flutter/test/widgets/scroll_view_test.dart
index a7879ce..ec6d8ab 100644
--- a/packages/flutter/test/widgets/scroll_view_test.dart
+++ b/packages/flutter/test/widgets/scroll_view_test.dart
@@ -326,22 +326,22 @@
 
   testWidgets('Primary ListViews are always scrollable', (WidgetTester tester) async {
     final ListView view = ListView(primary: true);
-    expect(view.physics, isInstanceOf<AlwaysScrollableScrollPhysics>());
+    expect(view.physics, isA<AlwaysScrollableScrollPhysics>());
   });
 
   testWidgets('Non-primary ListViews are not always scrollable', (WidgetTester tester) async {
     final ListView view = ListView(primary: false);
-    expect(view.physics, isNot(isInstanceOf<AlwaysScrollableScrollPhysics>()));
+    expect(view.physics, isNot(isA<AlwaysScrollableScrollPhysics>()));
   });
 
   testWidgets('Defaulting-to-primary ListViews are always scrollable', (WidgetTester tester) async {
     final ListView view = ListView(scrollDirection: Axis.vertical);
-    expect(view.physics, isInstanceOf<AlwaysScrollableScrollPhysics>());
+    expect(view.physics, isA<AlwaysScrollableScrollPhysics>());
   });
 
   testWidgets('Defaulting-to-not-primary ListViews are not always scrollable', (WidgetTester tester) async {
     final ListView view = ListView(scrollDirection: Axis.horizontal);
-    expect(view.physics, isNot(isInstanceOf<AlwaysScrollableScrollPhysics>()));
+    expect(view.physics, isNot(isA<AlwaysScrollableScrollPhysics>()));
   });
 
   testWidgets('primary:true leads to scrolling', (WidgetTester tester) async {
@@ -459,7 +459,7 @@
 
     // A separatorBuilder that returns null throws a FlutterError
     await tester.pumpWidget(buildFrame(null));
-    expect(tester.takeException(), isInstanceOf<FlutterError>());
+    expect(tester.takeException(), isFlutterError);
     expect(find.byType(ErrorWidget), findsOneWidget);
   });
 
@@ -520,7 +520,7 @@
 
     // When it does throw, one error widget is rendered in the item's place
     await tester.pumpWidget(buildFrame(true));
-    expect(tester.takeException(), isInstanceOf<Exception>());
+    expect(tester.takeException(), isA<Exception>());
     expect(finder, findsOneWidget);
   });
 
@@ -556,7 +556,7 @@
 
     // When it does throw, one error widget is rendered in the separator's place
     await tester.pumpWidget(buildFrame(true));
-    expect(tester.takeException(), isInstanceOf<Exception>());
+    expect(tester.takeException(), isA<Exception>());
     expect(finder, findsOneWidget);
   });
 
@@ -566,7 +566,7 @@
         return const SizedBox();
       },
       itemCount: -1,
-    ), throwsA(isInstanceOf<AssertionError>()));
+    ), throwsAssertionError);
   });
 
   testWidgets('ListView.builder asserts on negative semanticChildCount', (WidgetTester tester) async {
@@ -576,7 +576,7 @@
       },
       itemCount: 1,
       semanticChildCount: -1,
-    ), throwsA(isInstanceOf<AssertionError>()));
+    ), throwsAssertionError);
   });
 
   testWidgets('ListView.builder asserts on nonsensical childCount/semanticChildCount', (WidgetTester tester) async {
@@ -586,6 +586,6 @@
       },
       itemCount: 1,
       semanticChildCount: 4,
-    ), throwsA(isInstanceOf<AssertionError>()));
+    ), throwsAssertionError);
   });
 }
diff --git a/packages/flutter/test/widgets/scrollable_dispose_test.dart b/packages/flutter/test/widgets/scrollable_dispose_test.dart
index edaee2f..1a970f4 100644
--- a/packages/flutter/test/widgets/scrollable_dispose_test.dart
+++ b/packages/flutter/test/widgets/scrollable_dispose_test.dart
@@ -28,10 +28,9 @@
     await tester.pump(const Duration(hours: 5));
   });
 
-  testWidgets('Disposing a (nested) Scrollable while holding in overscroll (iOS) does not crash', (WidgetTester tester) async {
+  testWidgets('Disposing a (nested) Scrollable while holding in overscroll does not crash', (WidgetTester tester) async {
     // Regression test for https://github.com/flutter/flutter/issues/27707.
 
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     final ScrollController controller = ScrollController();
     final Key outterContainer = GlobalKey();
 
@@ -88,7 +87,5 @@
     );
     await tester.pumpAndSettle();
     expect(controller.hasClients, isFalse);
-
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 }
diff --git a/packages/flutter/test/widgets/scrollable_fling_test.dart b/packages/flutter/test/widgets/scrollable_fling_test.dart
index 16f6a16..b4e3470 100644
--- a/packages/flutter/test/widgets/scrollable_fling_test.dart
+++ b/packages/flutter/test/widgets/scrollable_fling_test.dart
@@ -43,7 +43,7 @@
     await tester.pump(); // trigger fling
     expect(getCurrentOffset(), dragOffset);
     await tester.pump(const Duration(seconds: 5));
-    final double result1 = getCurrentOffset();
+    final double androidResult = getCurrentOffset();
 
     await pumpTest(tester, TargetPlatform.iOS);
     await tester.fling(find.byType(ListView), const Offset(0.0, -dragOffset), 1000.0);
@@ -52,9 +52,19 @@
     await tester.pump(); // trigger fling
     expect(getCurrentOffset(), moreOrLessEquals(210.71026666666666));
     await tester.pump(const Duration(seconds: 5));
-    final double result2 = getCurrentOffset();
+    final double iOSResult = getCurrentOffset();
 
-    expect(result1, lessThan(result2)); // iOS (result2) is slipperier than Android (result1)
+    await pumpTest(tester, TargetPlatform.macOS);
+    await tester.fling(find.byType(ListView), const Offset(0.0, -dragOffset), 1000.0);
+    // Scroll starts ease into the scroll on iOS.
+    expect(getCurrentOffset(), moreOrLessEquals(210.71026666666666));
+    await tester.pump(); // trigger fling
+    expect(getCurrentOffset(), moreOrLessEquals(210.71026666666666));
+    await tester.pump(const Duration(seconds: 5));
+    final double macOSResult = getCurrentOffset();
+
+    expect(androidResult, lessThan(iOSResult)); // iOS is slipperier than Android
+    expect(androidResult, lessThan(macOSResult)); // macOS is slipperier than Android
   });
 
   testWidgets('fling and tap to stop', (WidgetTester tester) async {
diff --git a/packages/flutter/test/widgets/scrollable_test.dart b/packages/flutter/test/widgets/scrollable_test.dart
index 0a90ffb..e2b2420 100644
--- a/packages/flutter/test/widgets/scrollable_test.dart
+++ b/packages/flutter/test/widgets/scrollable_test.dart
@@ -97,7 +97,7 @@
     await tester.pump(); // trigger fling
     expect(getScrollOffset(tester), dragOffset);
     await tester.pump(const Duration(seconds: 5));
-    final double result1 = getScrollOffset(tester);
+    final double androidResult = getScrollOffset(tester);
 
     resetScrollOffset(tester);
 
@@ -108,13 +108,25 @@
     await tester.pump(); // trigger fling
     expect(getScrollOffset(tester), moreOrLessEquals(197.16666666666669));
     await tester.pump(const Duration(seconds: 5));
-    final double result2 = getScrollOffset(tester);
+    final double iOSResult = getScrollOffset(tester);
 
-    expect(result1, lessThan(result2)); // iOS (result2) is slipperier than Android (result1)
+    resetScrollOffset(tester);
+
+    await pumpTest(tester, TargetPlatform.macOS);
+    await tester.fling(find.byType(Viewport), const Offset(0.0, -dragOffset), 1000.0);
+    // Scroll starts ease into the scroll on iOS.
+    expect(getScrollOffset(tester), moreOrLessEquals(197.16666666666669));
+    await tester.pump(); // trigger fling
+    expect(getScrollOffset(tester), moreOrLessEquals(197.16666666666669));
+    await tester.pump(const Duration(seconds: 5));
+    final double macOSResult = getScrollOffset(tester);
+
+    expect(androidResult, lessThan(iOSResult)); // iOS is slipperier than Android
+    expect(androidResult, lessThan(macOSResult)); // macOS is slipperier than Android
   });
 
   testWidgets('Holding scroll', (WidgetTester tester) async {
-    await pumpTest(tester, TargetPlatform.iOS);
+    await pumpTest(tester, debugDefaultTargetPlatformOverride);
     await tester.drag(find.byType(Viewport), const Offset(0.0, 200.0), touchSlopY: 0.0);
     expect(getScrollOffset(tester), -200.0);
     await tester.pump(); // trigger ballistic
@@ -130,10 +142,10 @@
     // Once the hold is let go, it should still snap back to origin.
     expect(await tester.pumpAndSettle(const Duration(minutes: 1)), 2);
     expect(getScrollOffset(tester), 0.0);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('Repeated flings builds momentum on iOS', (WidgetTester tester) async {
-    await pumpTest(tester, TargetPlatform.iOS);
+  testWidgets('Repeated flings builds momentum', (WidgetTester tester) async {
+    await pumpTest(tester, debugDefaultTargetPlatformOverride);
     await tester.fling(find.byType(Viewport), const Offset(0.0, -dragOffset), 1000.0);
     await tester.pump(); // trigger fling
     await tester.pump(const Duration(milliseconds: 10));
@@ -143,9 +155,9 @@
     // On iOS, the velocity will be larger than the velocity of the last fling by a
     // non-trivial amount.
     expect(getScrollVelocity(tester), greaterThan(1100.0));
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-    resetScrollOffset(tester);
-
+  testWidgets('Repeated flings do not build momentum on Android', (WidgetTester tester) async {
     await pumpTest(tester, TargetPlatform.android);
     await tester.fling(find.byType(Viewport), const Offset(0.0, -dragOffset), 1000.0);
     await tester.pump(); // trigger fling
@@ -158,8 +170,8 @@
     expect(getScrollVelocity(tester), moreOrLessEquals(1000.0));
   });
 
-  testWidgets('No iOS momentum build with flings in opposite directions', (WidgetTester tester) async {
-    await pumpTest(tester, TargetPlatform.iOS);
+  testWidgets('No iOS/macOS momentum build with flings in opposite directions', (WidgetTester tester) async {
+    await pumpTest(tester, debugDefaultTargetPlatformOverride);
     await tester.fling(find.byType(Viewport), const Offset(0.0, -dragOffset), 1000.0);
     await tester.pump(); // trigger fling
     await tester.pump(const Duration(milliseconds: 10));
@@ -170,10 +182,10 @@
     // opposite direction.
     expect(getScrollVelocity(tester), greaterThan(-1000.0));
     expect(getScrollVelocity(tester), lessThan(0.0));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('No iOS momentum kept on hold gestures', (WidgetTester tester) async {
-    await pumpTest(tester, TargetPlatform.iOS);
+  testWidgets('No iOS/macOS momentum kept on hold gestures', (WidgetTester tester) async {
+    await pumpTest(tester, debugDefaultTargetPlatformOverride);
     await tester.fling(find.byType(Viewport), const Offset(0.0, -dragOffset), 1000.0);
     await tester.pump(); // trigger fling
     await tester.pump(const Duration(milliseconds: 10));
@@ -183,7 +195,7 @@
     await gesture.up();
     // After a hold longer than 2 frames, previous velocity is lost.
     expect(getScrollVelocity(tester), 0.0);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Drags creeping unaffected on Android', (WidgetTester tester) async {
     await pumpTest(tester, TargetPlatform.android);
@@ -196,8 +208,8 @@
     expect(getScrollOffset(tester), 1.5);
   });
 
-  testWidgets('Drags creeping must break threshold on iOS', (WidgetTester tester) async {
-    await pumpTest(tester, TargetPlatform.iOS);
+  testWidgets('Drags creeping must break threshold on iOS/macOS', (WidgetTester tester) async {
+    await pumpTest(tester, debugDefaultTargetPlatformOverride);
     final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Viewport)));
     await gesture.moveBy(const Offset(0.0, -0.5));
     expect(getScrollOffset(tester), 0.0);
@@ -214,18 +226,18 @@
     await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 50));
     // -0.5 over threshold transferred.
     expect(getScrollOffset(tester), 0.5);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('Big drag over threshold magnitude preserved on iOS', (WidgetTester tester) async {
-    await pumpTest(tester, TargetPlatform.iOS);
+  testWidgets('Big drag over threshold magnitude preserved on iOS/macOS', (WidgetTester tester) async {
+    await pumpTest(tester, debugDefaultTargetPlatformOverride);
     final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Viewport)));
     await gesture.moveBy(const Offset(0.0, -30.0));
     // No offset lost from threshold.
     expect(getScrollOffset(tester), 30.0);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('Slow threshold breaks are attenuated on iOS', (WidgetTester tester) async {
-    await pumpTest(tester, TargetPlatform.iOS);
+  testWidgets('Slow threshold breaks are attenuated on iOS/macOS', (WidgetTester tester) async {
+    await pumpTest(tester, debugDefaultTargetPlatformOverride);
     final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Viewport)));
     // This is a typical 'hesitant' iOS scroll start.
     await gesture.moveBy(const Offset(0.0, -10.0));
@@ -233,10 +245,10 @@
     await gesture.moveBy(const Offset(0.0, -10.0), timeStamp: const Duration(milliseconds: 20));
     // Subsequent motions unaffected.
     expect(getScrollOffset(tester), moreOrLessEquals(11.16666666666666673));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('Small continuing motion preserved on iOS', (WidgetTester tester) async {
-    await pumpTest(tester, TargetPlatform.iOS);
+  testWidgets('Small continuing motion preserved on iOS/macOS', (WidgetTester tester) async {
+    await pumpTest(tester, debugDefaultTargetPlatformOverride);
     final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Viewport)));
     await gesture.moveBy(const Offset(0.0, -30.0)); // Break threshold.
     expect(getScrollOffset(tester), 30.0);
@@ -246,10 +258,10 @@
     expect(getScrollOffset(tester), 31.0);
     await gesture.moveBy(const Offset(0.0, -0.5), timeStamp: const Duration(milliseconds: 60));
     expect(getScrollOffset(tester), 31.5);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('Motion stop resets threshold on iOS', (WidgetTester tester) async {
-    await pumpTest(tester, TargetPlatform.iOS);
+  testWidgets('Motion stop resets threshold on iOS/macOS', (WidgetTester tester) async {
+    await pumpTest(tester, debugDefaultTargetPlatformOverride);
     final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(Viewport)));
     await gesture.moveBy(const Offset(0.0, -30.0)); // Break threshold.
     expect(getScrollOffset(tester), 30.0);
@@ -269,9 +281,9 @@
     expect(getScrollOffset(tester), 31.5);
     await gesture.moveBy(const Offset(0.0, -1.0), timeStamp: const Duration(milliseconds: 180));
     expect(getScrollOffset(tester), 32.5);
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('Scroll pointer signals are handled', (WidgetTester tester) async {
+  testWidgets('Scroll pointer signals are handled on Fuchsia', (WidgetTester tester) async {
     await pumpTest(tester, TargetPlatform.fuchsia);
     final Offset scrollEventLocation = tester.getCenter(find.byType(Viewport));
     final TestPointer testPointer = TestPointer(1, ui.PointerDeviceKind.mouse);
diff --git a/packages/flutter/test/widgets/selectable_text_test.dart b/packages/flutter/test/widgets/selectable_text_test.dart
index 20d991c..9db1663 100644
--- a/packages/flutter/test/widgets/selectable_text_test.dart
+++ b/packages/flutter/test/widgets/selectable_text_test.dart
@@ -2321,12 +2321,11 @@
   });
 
   testWidgets(
-    'tap moves cursor to the edge of the word it tapped on (iOS)',
+    'tap moves cursor to the edge of the word it tapped',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -2349,8 +2348,7 @@
 
       // But don't trigger the toolbar.
       expect(find.byType(CupertinoButton), findsNothing);
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
     'tap moves cursor to the position tapped (Android)',
@@ -2385,12 +2383,11 @@
   );
 
   testWidgets(
-    'two slow taps do not trigger a word selection (iOS)',
+    'two slow taps do not trigger a word selection',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -2416,16 +2413,14 @@
 
       // No toolbar.
       expect(find.byType(CupertinoButton), findsNothing);
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'double tap selects word and first tap of double tap moves cursor (iOS)',
+    'double tap selects word and first tap of double tap moves cursor',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -2462,8 +2457,7 @@
 
       // Selected text shows 1 toolbar buttons.
       expect(find.byType(CupertinoButton), findsNWidgets(1));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
     'double tap selects word and first tap of double tap moves cursor and shows toolbar (Android)',
@@ -2560,12 +2554,11 @@
   );
 
   testWidgets(
-    'double tap hold selects word (iOS)',
+    'double tap hold selects word',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -2603,16 +2596,14 @@
       );
       // The toolbar is still showing.
       expect(find.byType(CupertinoButton), findsNWidgets(1));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
     'tap after a double tap select is not affected (iOS)',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -2650,16 +2641,14 @@
 
       // No toolbar.
       expect(find.byType(CupertinoButton), findsNothing);
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'long press moves cursor to the exact long press position and shows toolbar (iOS)',
+    'long press moves cursor to the exact long press position and shows toolbar',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -2683,8 +2672,7 @@
 
       // Collapsed toolbar shows 2 buttons.
       expect(find.byType(CupertinoButton), findsNWidgets(1));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
     'long press selects word and shows toolbar (Android)',
@@ -2719,12 +2707,11 @@
   );
 
   testWidgets(
-    'long press tap cannot initiate a double tap (iOS)',
+    'long press tap cannot initiate a double tap',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -2751,16 +2738,14 @@
       );
 
       expect(find.byType(CupertinoButton), findsNothing);
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
     'long press drag moves the cursor under the drag and shows toolbar on lift (iOS)',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -2817,14 +2802,12 @@
       );
       // The toolbar now shows up.
       expect(find.byType(CupertinoButton), findsNWidgets(1));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('long press drag can edge scroll (iOS)', (WidgetTester tester) async {
+  testWidgets('long press drag can edge scroll', (WidgetTester tester) async {
     await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: const Material(
+      const MaterialApp(
+        home: Material(
           child: Center(
             child: SelectableText(
               'Atwater Peel Sherbrooke Bonaventure Angrignon Peel Côte-des-Neiges',
@@ -2908,15 +2891,14 @@
     expect(firstCharEndpoint.length, 1);
     // The first character is now offscreen to the left.
     expect(firstCharEndpoint[0].point.dx, moreOrLessEquals(-125, epsilon: 1));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'long tap after a double tap select is not affected (iOS)',
+    'long tap after a double tap select is not affected',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -2951,16 +2933,14 @@
 
       // Long press toolbar.
       expect(find.byType(CupertinoButton), findsNWidgets(1));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 //convert
   testWidgets(
-    'double tap after a long tap is not affected (iOS)',
+    'double tap after a long tap is not affected',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -2993,16 +2973,14 @@
         const TextSelection(baseOffset: 8, extentOffset: 12),
       );
       expect(find.byType(CupertinoButton), findsNWidgets(1));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets(
-    'double tap chains work (iOS)',
+    'double tap chains work',
     (WidgetTester tester) async {
       await tester.pumpWidget(
-        MaterialApp(
-          theme: ThemeData(platform: TargetPlatform.iOS),
-          home: const Material(
+        const MaterialApp(
+          home: Material(
             child: Center(
               child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
             ),
@@ -3060,8 +3038,7 @@
         const TextSelection(baseOffset: 8, extentOffset: 12),
       );
       expect(find.byType(CupertinoButton), findsNWidgets(1));
-    },
-  );
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('force press does not select a word on (android)', (WidgetTester tester) async {
     await tester.pumpWidget(
@@ -3099,11 +3076,10 @@
     expect(find.byType(FlatButton), findsNothing);
   });
 
-  testWidgets('force press selects word (iOS)', (WidgetTester tester) async {
+  testWidgets('force press selects word', (WidgetTester tester) async {
     await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: const Material(
+      const MaterialApp(
+        home: Material(
           child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
         ),
       ),
@@ -3139,13 +3115,12 @@
     await gesture.up();
     await tester.pump();
     expect(find.byType(CupertinoButton), findsNWidgets(1));
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
-  testWidgets('tap on non-force-press-supported devices work (iOS)', (WidgetTester tester) async {
+  testWidgets('tap on non-force-press-supported devices work', (WidgetTester tester) async {
     await tester.pumpWidget(
-      MaterialApp(
-        theme: ThemeData(platform: TargetPlatform.iOS),
-        home: const Material(
+      const MaterialApp(
+        home: Material(
           child: SelectableText('Atwater Peel Sherbrooke Bonaventure'),
         ),
       ),
@@ -3184,7 +3159,11 @@
     await tester.pump();
     // Single taps shouldn't trigger the toolbar.
     expect(find.byType(CupertinoButton), findsNothing);
-  });
+
+    // TODO(gspencergoog): Add in TargetPlatform.macOS in the line below when we
+    // figure out what global state is leaking.
+    // https://github.com/flutter/flutter/issues/43445
+  }, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
 
   testWidgets('default SelectableText debugFillProperties', (WidgetTester tester) async {
     final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
@@ -3566,8 +3545,7 @@
     expect(right.opacity.value, equals(1.0));
   });
 
-  testWidgets('iOS selection handles are rendered and not faded away', (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
+  testWidgets('selection handles are rendered and not faded away', (WidgetTester tester) async {
     const String testText = 'lorem ipsum';
 
     await tester.pumpWidget(
@@ -3593,9 +3571,7 @@
 
     expect(left.opacity.value, equals(1.0));
     expect(right.opacity.value, equals(1.0));
-
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
   testWidgets('Long press shows handles and toolbar', (WidgetTester tester) async {
     await tester.pumpWidget(
diff --git a/packages/flutter/test/widgets/semantics_clipping_test.dart b/packages/flutter/test/widgets/semantics_clipping_test.dart
index a467a5b..da61456 100644
--- a/packages/flutter/test/widgets/semantics_clipping_test.dart
+++ b/packages/flutter/test/widgets/semantics_clipping_test.dart
@@ -40,7 +40,7 @@
     ));
 
     final dynamic exception = tester.takeException();
-    expect(exception, isInstanceOf<FlutterError>());
+    expect(exception, isFlutterError);
     expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
     expect(exception.diagnostics.first.toString(), contains('overflowed'));
 
@@ -102,7 +102,7 @@
     ));
 
     final dynamic exception = tester.takeException();
-    expect(exception, isInstanceOf<FlutterError>());
+    expect(exception, isFlutterError);
     expect(exception.diagnostics.first.level, DiagnosticLevel.summary);
     expect(exception.diagnostics.first.toString(), contains('overflowed'));
 
diff --git a/packages/flutter/test/widgets/set_state_5_test.dart b/packages/flutter/test/widgets/set_state_5_test.dart
index cec26cc..052032b 100644
--- a/packages/flutter/test/widgets/set_state_5_test.dart
+++ b/packages/flutter/test/widgets/set_state_5_test.dart
@@ -29,6 +29,6 @@
 void main() {
   testWidgets('setState() catches being used inside a constructor', (WidgetTester tester) async {
     await tester.pumpWidget(const BadWidget());
-    expect(tester.takeException(), isInstanceOf<FlutterError>());
+    expect(tester.takeException(), isFlutterError);
   });
 }
diff --git a/packages/flutter/test/widgets/shape_decoration_test.dart b/packages/flutter/test/widgets/shape_decoration_test.dart
index 56671ee..87a9325 100644
--- a/packages/flutter/test/widgets/shape_decoration_test.dart
+++ b/packages/flutter/test/widgets/shape_decoration_test.dart
@@ -66,7 +66,7 @@
       shape: BorderDirectional(start: BorderSide(color: Colors.red, width: 3)),
     );
 
-    expect(decoration.padding, isInstanceOf<EdgeInsetsDirectional>());
+    expect(decoration.padding, isA<EdgeInsetsDirectional>());
   });
 
   testWidgets('TestBorder and Directionality - 1', (WidgetTester tester) async {
diff --git a/packages/flutter/test/widgets/single_child_scroll_view_test.dart b/packages/flutter/test/widgets/single_child_scroll_view_test.dart
index b5e1629..8ba799c 100644
--- a/packages/flutter/test/widgets/single_child_scroll_view_test.dart
+++ b/packages/flutter/test/widgets/single_child_scroll_view_test.dart
@@ -72,7 +72,7 @@
     ));
 
     final ScrollableState scrollable = tester.state(find.byType(Scrollable));
-    expect(scrollable.position, isInstanceOf<TestScrollPosition>());
+    expect(scrollable.position, isA<TestScrollPosition>());
   });
 
   testWidgets('Sets PrimaryScrollController when primary', (WidgetTester tester) async {
diff --git a/packages/flutter/test/widgets/size_changed_layout_notification_test.dart b/packages/flutter/test/widgets/size_changed_layout_notification_test.dart
index ff24f87..6f8c8c8 100644
--- a/packages/flutter/test/widgets/size_changed_layout_notification_test.dart
+++ b/packages/flutter/test/widgets/size_changed_layout_notification_test.dart
@@ -29,7 +29,7 @@
       Center(
         child: NotificationListener<LayoutChangedNotification>(
           onNotification: (LayoutChangedNotification notification) {
-            expect(notification, isInstanceOf<SizeChangedLayoutNotification>());
+            expect(notification, isA<SizeChangedLayoutNotification>());
             notified = true;
             return true;
           },
diff --git a/packages/flutter/test/widgets/sliver_fill_remaining_test.dart b/packages/flutter/test/widgets/sliver_fill_remaining_test.dart
index 44502fd..c7a45b6 100644
--- a/packages/flutter/test/widgets/sliver_fill_remaining_test.dart
+++ b/packages/flutter/test/widgets/sliver_fill_remaining_test.dart
@@ -283,7 +283,6 @@
       });
 
       testWidgets('alignment with a flexible works', (WidgetTester tester) async {
-        debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
         final GlobalKey key = GlobalKey();
         final List<Widget> slivers = <Widget>[
           sliverBox,
@@ -347,13 +346,10 @@
         );
         expect(tester.getBottomLeft(button).dy, lessThan(600.0));
         expect(tester.getCenter(button).dx, equals(400.0));
-
-        debugDefaultTargetPlatformOverride = null;
-      });
+      }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
 
       group('fillOverscroll: true, relevant platforms', () {
         testWidgets('child without size is sized by extent and overscroll', (WidgetTester tester) async {
-          debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
           final List<Widget> slivers = <Widget>[
             sliverBox,
             SliverFillRemaining(
@@ -378,12 +374,9 @@
           await tester.pumpAndSettle();
           final RenderBox box3 = tester.renderObject<RenderBox>(find.byType(Container).last);
           expect(box3.size.height, equals(450));
-
-          debugDefaultTargetPlatformOverride = null;
-        });
+    }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
         testWidgets('child with smaller size is overridden and sized by extent and overscroll', (WidgetTester tester) async {
-          debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
           final GlobalKey key = GlobalKey();
           final List<Widget> slivers = <Widget>[
             sliverBox,
@@ -428,12 +421,9 @@
             tester.renderObject<RenderBox>(find.byKey(key)).size.height,
             equals(450),
           );
-
-          debugDefaultTargetPlatformOverride = null;
-        });
+        }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
         testWidgets('extent is overridden by child size and overscroll if precedingScrollExtent > viewportMainAxisExtent', (WidgetTester tester) async {
-          debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
           final GlobalKey key = GlobalKey();
           final ScrollController controller = ScrollController();
           final List<Widget> slivers = <Widget>[
@@ -473,12 +463,10 @@
             tester.renderObject<RenderBox>(find.byKey(key)).size.height,
             equals(148.0),
           );
-
           // Check that the button alignment is true to expectations
           final Finder button = find.byType(RaisedButton);
           expect(tester.getBottomLeft(button).dy, equals(550.0));
           expect(tester.getCenter(button).dx, equals(400.0));
-          debugDefaultTargetPlatformOverride = null;
 
           // Drag for overscroll
           await tester.drag(find.byType(Scrollable), const Offset(0.0, -50.0));
@@ -498,12 +486,9 @@
             tester.renderObject<RenderBox>(find.byKey(key)).size.height,
             equals(148.0),
           );
-
-          debugDefaultTargetPlatformOverride = null;
-        });
+        }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
         testWidgets('fillOverscroll works when child has no size and precedingScrollExtent > viewportMainAxisExtent', (WidgetTester tester) async {
-          debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
           final GlobalKey key = GlobalKey();
           final ScrollController controller = ScrollController();
           final List<Widget> slivers = <Widget>[
@@ -557,12 +542,9 @@
             tester.widgetList<DecoratedBox>(find.byType(DecoratedBox)).last.decoration,
             amberBox,
           );
-
-          debugDefaultTargetPlatformOverride = null;
-        });
+        }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 
         testWidgets('alignment with a flexible works with fillOverscroll', (WidgetTester tester) async {
-          debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
           final GlobalKey key = GlobalKey();
           final List<Widget> slivers = <Widget>[
             sliverBox,
@@ -648,9 +630,7 @@
           );
           expect(tester.getBottomLeft(button).dy, equals(600.0));
           expect(tester.getCenter(button).dx, equals(400.0));
-
-          debugDefaultTargetPlatformOverride = null;
-        });
+        }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
       });
 
       group('fillOverscroll: true, is ignored on irrevelant platforms', () {
diff --git a/packages/flutter/test/widgets/slivers_appbar_floating_test.dart b/packages/flutter/test/widgets/slivers_appbar_floating_test.dart
index 9563f34..a50e7bb 100644
--- a/packages/flutter/test/widgets/slivers_appbar_floating_test.dart
+++ b/packages/flutter/test/widgets/slivers_appbar_floating_test.dart
@@ -8,7 +8,7 @@
 
 void verifyPaintPosition(GlobalKey key, Offset ideal, bool visible) {
   final RenderSliver target = key.currentContext.findRenderObject() as RenderSliver;
-  expect(target.parent, isInstanceOf<RenderViewport>());
+  expect(target.parent, isA<RenderViewport>());
   final SliverPhysicalParentData parentData = target.parentData as SliverPhysicalParentData;
   final Offset actual = parentData.paintOffset;
   expect(actual, ideal);
diff --git a/packages/flutter/test/widgets/slivers_appbar_pinned_test.dart b/packages/flutter/test/widgets/slivers_appbar_pinned_test.dart
index 4117552..6fe3f4d 100644
--- a/packages/flutter/test/widgets/slivers_appbar_pinned_test.dart
+++ b/packages/flutter/test/widgets/slivers_appbar_pinned_test.dart
@@ -8,7 +8,7 @@
 
 void verifyPaintPosition(GlobalKey key, Offset ideal, bool visible) {
   final RenderSliver target = key.currentContext.findRenderObject() as RenderSliver;
-  expect(target.parent, isInstanceOf<RenderViewport>());
+  expect(target.parent, isA<RenderViewport>());
   final SliverPhysicalParentData parentData = target.parentData as SliverPhysicalParentData;
   final Offset actual = parentData.paintOffset;
   expect(actual, ideal);
diff --git a/packages/flutter/test/widgets/slivers_appbar_scrolling_test.dart b/packages/flutter/test/widgets/slivers_appbar_scrolling_test.dart
index 3c8efea..9728410 100644
--- a/packages/flutter/test/widgets/slivers_appbar_scrolling_test.dart
+++ b/packages/flutter/test/widgets/slivers_appbar_scrolling_test.dart
@@ -8,7 +8,7 @@
 
 void verifyPaintPosition(GlobalKey key, Offset ideal) {
   final RenderObject target = key.currentContext.findRenderObject();
-  expect(target.parent, isInstanceOf<RenderViewport>());
+  expect(target.parent, isA<RenderViewport>());
   final SliverPhysicalParentData parentData = target.parentData as SliverPhysicalParentData;
   final Offset actual = parentData.paintOffset;
   expect(actual, ideal);
diff --git a/packages/flutter/test/widgets/slivers_padding_test.dart b/packages/flutter/test/widgets/slivers_padding_test.dart
index e1b6b3a..305378a 100644
--- a/packages/flutter/test/widgets/slivers_padding_test.dart
+++ b/packages/flutter/test/widgets/slivers_padding_test.dart
@@ -168,11 +168,11 @@
     result = tester.hitTestOnBinding(const Offset(10.0, 10.0));
     expect(result.path.first.target, tester.firstRenderObject<RenderObject>(find.byType(Text)));
     result = tester.hitTestOnBinding(const Offset(10.0, 60.0));
-    expect(result.path.first.target, isInstanceOf<RenderView>());
+    expect(result.path.first.target, isA<RenderView>());
     result = tester.hitTestOnBinding(const Offset(100.0, 100.0));
     expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).skip(1).first);
     result = tester.hitTestOnBinding(const Offset(100.0, 490.0));
-    expect(result.path.first.target, isInstanceOf<RenderView>());
+    expect(result.path.first.target, isA<RenderView>());
     result = tester.hitTestOnBinding(const Offset(10.0, 520.0));
     expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).last);
   });
@@ -190,11 +190,11 @@
     result = tester.hitTestOnBinding(const Offset(10.0, 600.0-10.0));
     expect(result.path.first.target, tester.firstRenderObject<RenderObject>(find.byType(Text)));
     result = tester.hitTestOnBinding(const Offset(10.0, 600.0-60.0));
-    expect(result.path.first.target, isInstanceOf<RenderView>());
+    expect(result.path.first.target, isA<RenderView>());
     result = tester.hitTestOnBinding(const Offset(100.0, 600.0-100.0));
     expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).skip(1).first);
     result = tester.hitTestOnBinding(const Offset(100.0, 600.0-490.0));
-    expect(result.path.first.target, isInstanceOf<RenderView>());
+    expect(result.path.first.target, isA<RenderView>());
     result = tester.hitTestOnBinding(const Offset(10.0, 600.0-520.0));
     expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).last);
   });
@@ -212,11 +212,11 @@
     result = tester.hitTestOnBinding(const Offset(800.0-10.0, 10.0));
     expect(result.path.first.target, tester.firstRenderObject<RenderObject>(find.byType(Text)));
     result = tester.hitTestOnBinding(const Offset(800.0-60.0, 10.0));
-    expect(result.path.first.target, isInstanceOf<RenderView>());
+    expect(result.path.first.target, isA<RenderView>());
     result = tester.hitTestOnBinding(const Offset(800.0-100.0, 100.0));
     expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).skip(1).first);
     result = tester.hitTestOnBinding(const Offset(800.0-490.0, 100.0));
-    expect(result.path.first.target, isInstanceOf<RenderView>());
+    expect(result.path.first.target, isA<RenderView>());
     result = tester.hitTestOnBinding(const Offset(800.0-520.0, 10.0));
     expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).last);
   });
@@ -234,11 +234,11 @@
     result = tester.hitTestOnBinding(const Offset(10.0, 10.0));
     expect(result.path.first.target, tester.firstRenderObject<RenderObject>(find.byType(Text)));
     result = tester.hitTestOnBinding(const Offset(60.0, 10.0));
-    expect(result.path.first.target, isInstanceOf<RenderView>());
+    expect(result.path.first.target, isA<RenderView>());
     result = tester.hitTestOnBinding(const Offset(100.0, 100.0));
     expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).skip(1).first);
     result = tester.hitTestOnBinding(const Offset(490.0, 100.0));
-    expect(result.path.first.target, isInstanceOf<RenderView>());
+    expect(result.path.first.target, isA<RenderView>());
     result = tester.hitTestOnBinding(const Offset(520.0, 10.0));
     expect(result.path.first.target, tester.renderObjectList<RenderObject>(find.byType(Text)).last);
   });
diff --git a/packages/flutter/test/widgets/slivers_protocol_test.dart b/packages/flutter/test/widgets/slivers_protocol_test.dart
index a89369b..deb480d 100644
--- a/packages/flutter/test/widgets/slivers_protocol_test.dart
+++ b/packages/flutter/test/widgets/slivers_protocol_test.dart
@@ -10,7 +10,7 @@
 
 void verifyPaintPosition(GlobalKey key, Offset ideal) {
   final RenderObject target = key.currentContext.findRenderObject();
-  expect(target.parent, isInstanceOf<RenderViewport>());
+  expect(target.parent, isA<RenderViewport>());
   final SliverPhysicalParentData parentData = target.parentData as SliverPhysicalParentData;
   final Offset actual = parentData.paintOffset;
   expect(actual, ideal);
diff --git a/packages/flutter/test/widgets/stateful_component_test.dart b/packages/flutter/test/widgets/stateful_component_test.dart
index 365fc32..4fbe63c 100644
--- a/packages/flutter/test/widgets/stateful_component_test.dart
+++ b/packages/flutter/test/widgets/stateful_component_test.dart
@@ -16,7 +16,7 @@
         find.byElementPredicate((Element element) => element is SingleChildRenderObjectElement)
       );
       expect(element, isNotNull);
-      expect(element.renderObject is RenderDecoratedBox, isTrue);
+      expect(element.renderObject, isA<RenderDecoratedBox>());
       final RenderDecoratedBox renderObject = element.renderObject as RenderDecoratedBox;
       expect(renderObject.decoration, equals(expectedDecoration));
     }
diff --git a/packages/flutter/test/widgets/text_selection_test.dart b/packages/flutter/test/widgets/text_selection_test.dart
index e6db40e..fc2dc86 100644
--- a/packages/flutter/test/widgets/text_selection_test.dart
+++ b/packages/flutter/test/widgets/text_selection_test.dart
@@ -7,7 +7,6 @@
 import 'package:flutter/widgets.dart';
 import 'package:flutter/rendering.dart';
 import 'package:flutter/material.dart';
-import 'package:flutter/foundation.dart' show debugDefaultTargetPlatformOverride;
 
 void main() {
   int tapCount;
@@ -552,7 +551,6 @@
 
   // Regression test for https://github.com/flutter/flutter/issues/37032.
   testWidgets("selection handle's GestureDetector should not cover the entire screen", (WidgetTester tester) async {
-    debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
     final TextEditingController controller = TextEditingController(text: 'a');
 
     await tester.pumpWidget(
@@ -583,9 +581,7 @@
 
     expect(hitRect.size.width, lessThan(textFieldRect.size.width));
     expect(hitRect.size.height, lessThan(textFieldRect.size.height));
-
-    debugDefaultTargetPlatformOverride = null;
-  });
+  }, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS,  TargetPlatform.macOS }));
 }
 
 class FakeTextSelectionGestureDetectorBuilderDelegate implements TextSelectionGestureDetectorBuilderDelegate {
diff --git a/packages/flutter/test/widgets/ticker_provider_test.dart b/packages/flutter/test/widgets/ticker_provider_test.dart
index b4dd6f4..ffc17d9 100644
--- a/packages/flutter/test/widgets/ticker_provider_test.dart
+++ b/packages/flutter/test/widgets/ticker_provider_test.dart
@@ -118,7 +118,7 @@
           'calling dispose() on the AnimationController itself. Otherwise,\n'
           'the ticker will leak.\n'
         );
-        expect(error.diagnostics[3], isInstanceOf<DiagnosticsProperty<Ticker>>());
+        expect(error.diagnostics[3], isA<DiagnosticsProperty<Ticker>>());
         expect(error.toStringDeep().split('\n').take(14).join('\n'), equalsIgnoringHashCodes(
           'FlutterError\n'
             '   _SingleTickerTestState#00000(ticker active) was disposed with an\n'
@@ -161,7 +161,7 @@
           'calling dispose() on the AnimationController itself. Otherwise,\n'
           'the ticker will leak.\n'
         );
-        expect(error.diagnostics[3], isInstanceOf<DiagnosticsProperty<Ticker>>());
+        expect(error.diagnostics[3], isA<DiagnosticsProperty<Ticker>>());
         expect(error.toStringDeep().split('\n').take(14).join('\n'), equalsIgnoringHashCodes(
           'FlutterError\n'
           '   _SingleTickerTestState#00000(ticker active) was disposed with an\n'
@@ -204,7 +204,7 @@
           'calling dispose() on the AnimationController itself. Otherwise,\n'
           'the ticker will leak.\n'
         );
-        expect(error.diagnostics[3], isInstanceOf<DiagnosticsProperty<Ticker>>());
+        expect(error.diagnostics[3], isA<DiagnosticsProperty<Ticker>>());
         expect(error.toStringDeep().split('\n').take(14).join('\n'), equalsIgnoringHashCodes(
           'FlutterError\n'
           '   _MultipleTickerTestState#00000(tickers: tracking 2 tickers) was\n'
diff --git a/packages/flutter/test/widgets/transitions_test.dart b/packages/flutter/test/widgets/transitions_test.dart
index 7ffba0d..a005484 100644
--- a/packages/flutter/test/widgets/transitions_test.dart
+++ b/packages/flutter/test/widgets/transitions_test.dart
@@ -80,7 +80,7 @@
       actualDecoration = actualBox.decoration as BoxDecoration;
 
       expect(actualDecoration.color, const Color(0xFF7F7F7F));
-      expect(actualDecoration.border, isInstanceOf<Border>());
+      expect(actualDecoration.border, isA<Border>());
       final Border border = actualDecoration.border as Border;
       expect(border.left.width, 2.5);
       expect(border.left.style, BorderStyle.solid);
@@ -137,7 +137,7 @@
       // Same as the test above but the values should be much closer to the
       // tween's end values given the easeOut curve.
       expect(actualDecoration.color, const Color(0xFF505050));
-      expect(actualDecoration.border, isInstanceOf<Border>());
+      expect(actualDecoration.border, isA<Border>());
       final Border border = actualDecoration.border as Border;
       expect(border.left.width, closeTo(1.9, 0.1));
       expect(border.left.style, BorderStyle.solid);
diff --git a/packages/flutter/test/widgets/widget_inspector_test.dart b/packages/flutter/test/widgets/widget_inspector_test.dart
index 70c18dc..65261be 100644
--- a/packages/flutter/test/widgets/widget_inspector_test.dart
+++ b/packages/flutter/test/widgets/widget_inspector_test.dart
@@ -728,7 +728,7 @@
         expect(chainNode['node'], isMap);
         final Map<String, Object> jsonNode = chainNode['node'] as Map<String, Object>;
         expect(service.toObject(jsonNode['valueId'] as String), equals(element));
-        expect(service.toObject(jsonNode['objectId'] as String), isInstanceOf<DiagnosticsNode>());
+        expect(service.toObject(jsonNode['objectId'] as String), isA<DiagnosticsNode>());
 
         expect(chainNode['children'], isList);
         final List<Object> jsonChildren = chainNode['children'] as List<Object>;
@@ -744,7 +744,7 @@
           expect(jsonChildren[j], isMap);
           final Map<String, Object> childJson = jsonChildren[j] as Map<String, Object>;
           expect(service.toObject(childJson['valueId'] as String), equals(childrenElements[j]));
-          expect(service.toObject(childJson['objectId'] as String), isInstanceOf<DiagnosticsNode>());
+          expect(service.toObject(childJson['objectId'] as String), isA<DiagnosticsNode>());
         }
       }
     });
@@ -761,7 +761,7 @@
       for (int i = 0; i < propertiesJson.length; ++i) {
         final Map<String, Object> propertyJson = propertiesJson[i] as Map<String, Object>;
         expect(service.toObject(propertyJson['valueId'] as String), equals(properties[i].value));
-        expect(service.toObject(propertyJson['objectId'] as String), isInstanceOf<DiagnosticsNode>());
+        expect(service.toObject(propertyJson['objectId'] as String), isA<DiagnosticsNode>());
       }
     });
 
@@ -790,7 +790,7 @@
       for (int i = 0; i < propertiesJson.length; ++i) {
         final Map<String, Object> propertyJson = propertiesJson[i] as Map<String, Object>;
         expect(service.toObject(propertyJson['valueId'] as String), equals(children[i].value));
-        expect(service.toObject(propertyJson['objectId'] as String), isInstanceOf<DiagnosticsNode>());
+        expect(service.toObject(propertyJson['objectId'] as String), isA<DiagnosticsNode>());
       }
     });
 
@@ -1168,7 +1168,7 @@
         expect(chainNode['node'], isMap);
         final Map<String, Object> jsonNode = chainNode['node'] as Map<String, Object>;
         expect(service.toObject(jsonNode['valueId'] as String), equals(element));
-        expect(service.toObject(jsonNode['objectId'] as String), isInstanceOf<DiagnosticsNode>());
+        expect(service.toObject(jsonNode['objectId'] as String), isA<DiagnosticsNode>());
 
         expect(chainNode['children'], isList);
         final List<Object> jsonChildren = chainNode['children'] as List<Object>;
@@ -1184,7 +1184,7 @@
           expect(jsonChildren[j], isMap);
           final Map<String, Object> childJson = jsonChildren[j] as Map<String, Object>;
           expect(service.toObject(childJson['valueId'] as String), equals(childrenElements[j]));
-          expect(service.toObject(childJson['objectId'] as String), isInstanceOf<DiagnosticsNode>());
+          expect(service.toObject(childJson['objectId'] as String), isA<DiagnosticsNode>());
         }
       }
     });
@@ -1200,7 +1200,7 @@
       for (int i = 0; i < propertiesJson.length; ++i) {
         final Map<String, Object> propertyJson = propertiesJson[i] as Map<String, Object>;
         expect(service.toObject(propertyJson['valueId'] as String), equals(properties[i].value));
-        expect(service.toObject(propertyJson['objectId'] as String), isInstanceOf<DiagnosticsNode>());
+        expect(service.toObject(propertyJson['objectId'] as String), isA<DiagnosticsNode>());
       }
     });
 
@@ -1228,7 +1228,7 @@
       for (int i = 0; i < propertiesJson.length; ++i) {
         final Map<String, Object> propertyJson = propertiesJson[i] as Map<String, Object>;
         expect(service.toObject(propertyJson['valueId'] as String), equals(children[i].value));
-        expect(service.toObject(propertyJson['objectId'] as String), isInstanceOf<DiagnosticsNode>());
+        expect(service.toObject(propertyJson['objectId'] as String), isA<DiagnosticsNode>());
       }
     });
 
@@ -1256,13 +1256,13 @@
       for (int i = 0; i < childrenJson.length; ++i) {
         final Map<String, Object> childJson = childrenJson[i] as Map<String, Object>;
         expect(service.toObject(childJson['valueId'] as String), equals(children[i].value));
-        expect(service.toObject(childJson['objectId'] as String), isInstanceOf<DiagnosticsNode>());
+        expect(service.toObject(childJson['objectId'] as String), isA<DiagnosticsNode>());
         final List<Object> propertiesJson = childJson['properties'] as List<Object>;
         final DiagnosticsNode diagnosticsNode = service.toObject(childJson['objectId'] as String) as DiagnosticsNode;
         final List<DiagnosticsNode> expectedProperties = diagnosticsNode.getProperties();
         for (final Map<String, Object> propertyJson in propertiesJson.cast<Map<String, Object>>()) {
           final Object property = service.toObject(propertyJson['objectId'] as String);
-          expect(property, isInstanceOf<DiagnosticsNode>());
+          expect(property, isA<DiagnosticsNode>());
           expect(expectedProperties, contains(property));
         }
       }
@@ -1294,7 +1294,7 @@
       for (int i = 0; i < childrenJson.length; ++i) {
         final Map<String, Object> childJson = childrenJson[i] as Map<String, Object>;
         expect(service.toObject(childJson['valueId'] as String), equals(children[i].value));
-        expect(service.toObject(childJson['objectId'] as String), isInstanceOf<DiagnosticsNode>());
+        expect(service.toObject(childJson['objectId'] as String), isA<DiagnosticsNode>());
         final List<Object> propertiesJson = childJson['properties'] as List<Object>;
         for (final Map<String, Object> propertyJson in propertiesJson.cast<Map<String, Object>>()) {
           expect(propertyJson, isNot(contains('children')));
@@ -1303,7 +1303,7 @@
         final List<DiagnosticsNode> expectedProperties = diagnosticsNode.getProperties();
         for (final Map<String, Object> propertyJson in propertiesJson.cast<Map<String, Object>>()) {
           final Object property = service.toObject(propertyJson['objectId'] as String);
-          expect(property, isInstanceOf<DiagnosticsNode>());
+          expect(property, isA<DiagnosticsNode>());
           expect(expectedProperties, contains(property));
         }
       }
@@ -1670,7 +1670,7 @@
 
       expect(rebuildEvents.length, equals(1));
       Map<Object, Object> event = rebuildEvents.removeLast();
-      expect(event['startTime'], isInstanceOf<int>());
+      expect(event['startTime'], isA<int>());
       List<int> data = event['events'] as List<int>;
       expect(data.length, equals(14));
       final int numDataEntries = data.length ~/ 2;
@@ -1712,7 +1712,7 @@
       await tester.pump();
       expect(rebuildEvents.length, equals(1));
       event = rebuildEvents.removeLast();
-      expect(event['startTime'], isInstanceOf<int>());
+      expect(event['startTime'], isA<int>());
       data = event['events'] as List<int>;
       // No new locations were rebuilt.
       expect(event, isNot(contains('newLocations')));
@@ -1748,7 +1748,7 @@
       await tester.pump();
       expect(rebuildEvents.length, equals(1));
       event = rebuildEvents.removeLast();
-      expect(event['startTime'], isInstanceOf<int>());
+      expect(event['startTime'], isA<int>());
       data = event['events'] as List<int>;
       // No new locations were rebuilt.
       expect(event, isNot(contains('newLocations')));
@@ -1782,7 +1782,7 @@
       await tester.pump();
       expect(rebuildEvents.length, equals(1));
       event = rebuildEvents.removeLast();
-      expect(event['startTime'], isInstanceOf<int>());
+      expect(event['startTime'], isA<int>());
       data = event['events'] as List<int>;
       // No new locations were rebuilt.
       expect(event, isNot(contains('newLocations')));
@@ -1799,7 +1799,7 @@
       await tester.pump();
       expect(rebuildEvents.length, equals(1));
       event = rebuildEvents.removeLast();
-      expect(event['startTime'], isInstanceOf<int>());
+      expect(event['startTime'], isA<int>());
       data = event['events'] as List<int>;
       newLocations = event['newLocations'] as Map<String, List<int>>;
 
@@ -1872,7 +1872,7 @@
 
       expect(repaintEvents.length, equals(1));
       Map<Object, Object> event = repaintEvents.removeLast();
-      expect(event['startTime'], isInstanceOf<int>());
+      expect(event['startTime'], isA<int>());
       List<int> data = event['events'] as List<int>;
       expect(data.length, equals(18));
       final int numDataEntries = data.length ~/ 2;
@@ -1914,7 +1914,7 @@
       await tester.pump();
       expect(repaintEvents.length, equals(1));
       event = repaintEvents.removeLast();
-      expect(event['startTime'], isInstanceOf<int>());
+      expect(event['startTime'], isA<int>());
       data = event['events'] as List<int>;
       // No new locations were rebuilt.
       expect(event, isNot(contains('newLocations')));
diff --git a/packages/flutter_driver/test/common.dart b/packages/flutter_driver/test/common.dart
index 8010218..e5987b0 100644
--- a/packages/flutter_driver/test/common.dart
+++ b/packages/flutter_driver/test/common.dart
@@ -4,6 +4,7 @@
 
 import 'dart:io';
 
+import 'package:flutter_driver/src/common/error.dart';
 import 'package:test_api/test_api.dart' hide TypeMatcher, isInstanceOf; // ignore: deprecated_member_use
 import 'package:test_api/test_api.dart' as test_package show TypeMatcher; // ignore: deprecated_member_use
 
@@ -13,7 +14,7 @@
 // TODO(ianh): Clean this up once https://github.com/dart-lang/matcher/issues/98 is fixed
 
 /// A matcher that compares the type of the actual value to the type argument T.
-Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();
+test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
 
 void tryToDelete(Directory directory) {
   // This should not be necessary, but it turns out that
@@ -25,3 +26,6 @@
     print('Failed to delete ${directory.path}: $error');
   }
 }
+
+/// Matcher for functions that throw [DriverError].
+final Matcher throwsDriverError = throwsA(isA<DriverError>());
diff --git a/packages/flutter_driver/test/flutter_driver_test.dart b/packages/flutter_driver/test/flutter_driver_test.dart
index a4eacc4..e50d676 100644
--- a/packages/flutter_driver/test/flutter_driver_test.dart
+++ b/packages/flutter_driver/test/flutter_driver_test.dart
@@ -145,8 +145,7 @@
 
     group('ByValueKey', () {
       test('restricts value types', () async {
-        expect(() => find.byValueKey(null),
-            throwsA(isInstanceOf<DriverError>()));
+        expect(() => find.byValueKey(null), throwsDriverError);
       });
 
       test('finds by ValueKey', () async {
@@ -195,7 +194,7 @@
 
     group('tap', () {
       test('requires a target reference', () async {
-        expect(driver.tap(null), throwsA(isInstanceOf<DriverError>()));
+        expect(driver.tap(null), throwsDriverError);
       });
 
       test('sends the tap command', () async {
@@ -214,7 +213,7 @@
 
     group('getText', () {
       test('requires a target reference', () async {
-        expect(driver.getText(null), throwsA(isInstanceOf<DriverError>()));
+        expect(driver.getText(null), throwsDriverError);
       });
 
       test('sends the getText command', () async {
@@ -256,7 +255,7 @@
 
     group('waitFor', () {
       test('requires a target reference', () async {
-        expect(driver.waitFor(null), throwsA(isInstanceOf<DriverError>()));
+        expect(driver.waitFor(null), throwsDriverError);
       });
 
       test('sends the waitFor command', () async {
@@ -379,11 +378,11 @@
 
     group('getOffset', () {
       test('requires a target reference', () async {
-        expect(driver.getCenter(null), throwsA(isInstanceOf<DriverError>()));
-        expect(driver.getTopLeft(null), throwsA(isInstanceOf<DriverError>()));
-        expect(driver.getTopRight(null), throwsA(isInstanceOf<DriverError>()));
-        expect(driver.getBottomLeft(null), throwsA(isInstanceOf<DriverError>()));
-        expect(driver.getBottomRight(null), throwsA(isInstanceOf<DriverError>()));
+        expect(driver.getCenter(null), throwsDriverError);
+        expect(driver.getTopLeft(null), throwsDriverError);
+        expect(driver.getTopRight(null), throwsDriverError);
+        expect(driver.getBottomLeft(null), throwsDriverError);
+        expect(driver.getBottomRight(null), throwsDriverError);
       });
 
       test('sends the getCenter command', () async {
@@ -646,7 +645,7 @@
           await driver.waitFor(find.byTooltip('foo'));
           fail('expected an exception');
         } catch (error) {
-          expect(error is DriverError, isTrue);
+          expect(error, isA<DriverError>());
           expect(error.message, 'Error in Flutter application: {message: This is a failure}');
         }
       });
@@ -706,7 +705,7 @@
     group('ByValueKey', () {
       test('restricts value types', () async {
         expect(() => find.byValueKey(null),
-            throwsA(isInstanceOf<DriverError>()));
+            throwsDriverError);
       });
 
       test('finds by ValueKey', () async {
@@ -758,7 +757,7 @@
 
     group('tap', () {
       test('requires a target reference', () async {
-        expect(driver.tap(null), throwsA(isInstanceOf<DriverError>()));
+        expect(driver.tap(null), throwsDriverError);
       });
 
       test('sends the tap command', () async {
@@ -778,7 +777,7 @@
 
     group('getText', () {
       test('requires a target reference', () async {
-        expect(driver.getText(null), throwsA(isInstanceOf<DriverError>()));
+        expect(driver.getText(null), throwsDriverError);
       });
 
       test('sends the getText command', () async {
@@ -802,7 +801,7 @@
 
     group('waitFor', () {
       test('requires a target reference', () async {
-        expect(driver.waitFor(null), throwsA(isInstanceOf<DriverError>()));
+        expect(driver.waitFor(null), throwsDriverError);
       });
 
       test('sends the waitFor command', () async {
@@ -881,11 +880,11 @@
 
     group('getOffset', () {
       test('requires a target reference', () async {
-        expect(driver.getCenter(null), throwsA(isInstanceOf<DriverError>()));
-        expect(driver.getTopLeft(null), throwsA(isInstanceOf<DriverError>()));
-        expect(driver.getTopRight(null), throwsA(isInstanceOf<DriverError>()));
-        expect(driver.getBottomLeft(null), throwsA(isInstanceOf<DriverError>()));
-        expect(driver.getBottomRight(null), throwsA(isInstanceOf<DriverError>()));
+        expect(driver.getCenter(null), throwsDriverError);
+        expect(driver.getTopLeft(null), throwsDriverError);
+        expect(driver.getTopRight(null), throwsDriverError);
+        expect(driver.getBottomLeft(null), throwsDriverError);
+        expect(driver.getBottomRight(null), throwsDriverError);
       });
 
       test('sends the getCenter command', () async {
@@ -1003,27 +1002,27 @@
     group('WebFlutterDriver Unimplemented error', () {
       test('forceGC', () async {
         expect(driver.forceGC(),
-            throwsA(isInstanceOf<UnimplementedError>()));
+            throwsA(isA<UnimplementedError>()));
       });
 
       test('getVmFlags', () async {
         expect(driver.getVmFlags(),
-            throwsA(isInstanceOf<UnimplementedError>()));
+            throwsA(isA<UnimplementedError>()));
       });
 
       test('waitUntilFirstFrameRasterized', () async {
         expect(driver.waitUntilFirstFrameRasterized(),
-            throwsA(isInstanceOf<UnimplementedError>()));
+            throwsA(isA<UnimplementedError>()));
       });
 
       test('appIsoloate', () async {
         expect(() => driver.appIsolate.invokeExtension('abc', <String, String>{'abc': '123'}),
-            throwsA(isInstanceOf<UnsupportedError>()));
+            throwsA(isA<UnsupportedError>()));
       });
 
       test('serviceClient', () async {
         expect(() => driver.serviceClient.getVM(),
-            throwsA(isInstanceOf<UnsupportedError>()));
+            throwsA(isA<UnsupportedError>()));
       });
     });
   });
@@ -1040,13 +1039,13 @@
 
     test('tracing', () async {
       expect(driver.traceAction(() async { return Future<dynamic>.value(); }),
-          throwsA(isInstanceOf<UnimplementedError>()));
+          throwsA(isA<UnimplementedError>()));
       expect(driver.startTracing(),
-          throwsA(isInstanceOf<UnimplementedError>()));
+          throwsA(isA<UnimplementedError>()));
       expect(driver.stopTracingAndDownloadTimeline(),
-          throwsA(isInstanceOf<UnimplementedError>()));
+          throwsA(isA<UnimplementedError>()));
       expect(driver.clearTimeline(),
-          throwsA(isInstanceOf<UnimplementedError>()));
+          throwsA(isA<UnimplementedError>()));
     });
   });
 }
@@ -1056,7 +1055,7 @@
 /// script will be in the following format:
 //   window.flutterDriver('[actual script]')
 String _checkAndEncode(dynamic script) {
-  expect(script is String, isTrue);
+  expect(script, isA<String>());
   expect(script.startsWith(_kWebScriptPrefix), isTrue);
   expect(script.endsWith(_kWebScriptSuffix), isTrue);
   // Strip prefix and suffix
diff --git a/packages/flutter_driver/test/src/real_tests/extension_test.dart b/packages/flutter_driver/test/src/real_tests/extension_test.dart
index e5b0c8c..7b8aa9e 100644
--- a/packages/flutter_driver/test/src/real_tests/extension_test.dart
+++ b/packages/flutter_driver/test/src/real_tests/extension_test.dart
@@ -563,35 +563,36 @@
                 children: <Widget>[
                   const Text('Hello1', key: ValueKey<String>('text1')),
                   Container(
-                      height: 25.0,
-                      child: RichText(
-                          key: const ValueKey<String>('text2'),
-                          text: const TextSpan(text: 'Hello2')
-                      )
+                    height: 25.0,
+                    child: RichText(
+                      key: const ValueKey<String>('text2'),
+                      text: const TextSpan(text: 'Hello2'),
+                    ),
                   ),
                   Container(
-                      height: 25.0,
-                      child: EditableText(
-                          key: const ValueKey<String>('text3'),
-                          controller: TextEditingController(text: 'Hello3'),
-                          focusNode: FocusNode(),
-                          style: const TextStyle(),
-                          cursorColor: Colors.red,
-                          backgroundCursorColor: Colors.black)
+                    height: 25.0,
+                    child: EditableText(
+                      key: const ValueKey<String>('text3'),
+                      controller: TextEditingController(text: 'Hello3'),
+                      focusNode: FocusNode(),
+                      style: const TextStyle(),
+                      cursorColor: Colors.red,
+                      backgroundCursorColor: Colors.black,
+                    ),
                   ),
                   Container(
-                      height: 25.0,
-                      child: TextField(
-                          key: const ValueKey<String>('text4'),
-                          controller: TextEditingController(text: 'Hello4')
-                      )
+                    height: 25.0,
+                    child: TextField(
+                      key: const ValueKey<String>('text4'),
+                      controller: TextEditingController(text: 'Hello4'),
+                    ),
                   ),
                   Container(
-                      height: 25.0,
-                      child: TextFormField(
-                          key: const ValueKey<String>('text5'),
-                          controller: TextEditingController(text: 'Hello5')
-                      )
+                    height: 25.0,
+                    child: TextFormField(
+                      key: const ValueKey<String>('text5'),
+                      controller: TextEditingController(text: 'Hello5'),
+                    ),
                   ),
                 ],
               ))
diff --git a/packages/flutter_driver/test/src/real_tests/io_extension_test.dart b/packages/flutter_driver/test/src/real_tests/io_extension_test.dart
index dbde050..3644bcf 100644
--- a/packages/flutter_driver/test/src/real_tests/io_extension_test.dart
+++ b/packages/flutter_driver/test/src/real_tests/io_extension_test.dart
@@ -18,7 +18,7 @@
 
     test('io_extension should throw exception', () {
       expect(() => registerWebServiceExtension(call),
-          throwsA(isInstanceOf<UnsupportedError>()));
+          throwsA(isA<UnsupportedError>()));
     });
   });
 }
diff --git a/packages/flutter_localizations/test/cupertino/translations_test.dart b/packages/flutter_localizations/test/cupertino/translations_test.dart
index d13974e..3e5a7a0 100644
--- a/packages/flutter_localizations/test/cupertino/translations_test.dart
+++ b/packages/flutter_localizations/test/cupertino/translations_test.dart
@@ -93,7 +93,7 @@
     const Locale locale = Locale('fr');
     expect(GlobalCupertinoLocalizations.delegate.isSupported(locale), isTrue);
     final CupertinoLocalizations localizations = await GlobalCupertinoLocalizations.delegate.load(locale);
-    expect(localizations is CupertinoLocalizationFr, true);
+    expect(localizations, isA<CupertinoLocalizationFr>());
     expect(localizations.alertDialogLabel, 'Alerte');
     expect(localizations.datePickerHourSemanticsLabel(1), '1 heure');
     expect(localizations.datePickerHourSemanticsLabel(12), '12 heures');
@@ -108,7 +108,7 @@
     const Locale locale = Locale('zh');
     expect(GlobalCupertinoLocalizations.delegate.isSupported(locale), isTrue);
     final CupertinoLocalizations localizations = await GlobalCupertinoLocalizations.delegate.load(locale);
-    expect(localizations is CupertinoLocalizationZh, true);
+    expect(localizations, isA<CupertinoLocalizationZh>());
     expect(localizations.alertDialogLabel, '提醒');
     expect(localizations.datePickerHourSemanticsLabel(1), '1 点');
     expect(localizations.datePickerHourSemanticsLabel(12), '12 点');
diff --git a/packages/flutter_localizations/test/material/translations_test.dart b/packages/flutter_localizations/test/material/translations_test.dart
index fa2c946..1bb5c63 100644
--- a/packages/flutter_localizations/test/material/translations_test.dart
+++ b/packages/flutter_localizations/test/material/translations_test.dart
@@ -159,268 +159,268 @@
     Locale locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: null, countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     MaterialLocalizations localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZh, true);
+    expect(localizations, isA<MaterialLocalizationZh>());
 
     locale = const Locale('zh', 'TW');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHantTw, true);
+    expect(localizations, isA<MaterialLocalizationZhHantTw>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: null, countryCode: 'HK');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHantHk, true);
+    expect(localizations, isA<MaterialLocalizationZhHantHk>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: null, countryCode: 'TW');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHantTw, true);
+    expect(localizations, isA<MaterialLocalizationZhHantTw>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHans, true);
+    expect(localizations, isA<MaterialLocalizationZhHans>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHant, true);
+    expect(localizations, isA<MaterialLocalizationZhHant>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHans, true);
+    expect(localizations, isA<MaterialLocalizationZhHans>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'CN');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHans, true);
+    expect(localizations, isA<MaterialLocalizationZhHans>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: 'TW');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHans, true);
+    expect(localizations, isA<MaterialLocalizationZhHans>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'CN');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHant, true);
+    expect(localizations, isA<MaterialLocalizationZhHant>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHant, true);
+    expect(localizations, isA<MaterialLocalizationZhHant>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: null, countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZh, true);
+    expect(localizations, isA<MaterialLocalizationZh>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Latn', countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZh, true);
+    expect(localizations, isA<MaterialLocalizationZh>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Latn', countryCode: 'TW');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZh, true);
+    expect(localizations, isA<MaterialLocalizationZh>());
 
     locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: null, countryCode: 'TW');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEn, true);
+    expect(localizations, isA<MaterialLocalizationEn>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Cyrl', countryCode: 'RU');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZh, true);
+    expect(localizations, isA<MaterialLocalizationZh>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: null, countryCode: 'RU');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZh, true);
+    expect(localizations, isA<MaterialLocalizationZh>());
 
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Cyrl', countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZh, true);
+    expect(localizations, isA<MaterialLocalizationZh>());
   });
 
   testWidgets('Serbian resolution', (WidgetTester tester) async {
     Locale locale = const Locale.fromSubtags(languageCode: 'sr', scriptCode: null, countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     MaterialLocalizations localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationSr, true);
+    expect(localizations, isA<MaterialLocalizationSr>());
 
     locale = const Locale.fromSubtags(languageCode: 'sr', scriptCode: 'Cyrl', countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationSrCyrl, true);
+    expect(localizations, isA<MaterialLocalizationSrCyrl>());
 
     locale = const Locale.fromSubtags(languageCode: 'sr', scriptCode: 'Latn', countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationSrLatn, true);
+    expect(localizations, isA<MaterialLocalizationSrLatn>());
 
     locale = const Locale.fromSubtags(languageCode: 'sr', scriptCode: null, countryCode: 'SR');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationSr, true);
+    expect(localizations, isA<MaterialLocalizationSr>());
 
     locale = const Locale.fromSubtags(languageCode: 'sr', scriptCode: 'Cyrl', countryCode: 'SR');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationSrCyrl, true);
+    expect(localizations, isA<MaterialLocalizationSrCyrl>());
 
     locale = const Locale.fromSubtags(languageCode: 'sr', scriptCode: 'Latn', countryCode: 'SR');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationSrLatn, true);
+    expect(localizations, isA<MaterialLocalizationSrLatn>());
 
     locale = const Locale.fromSubtags(languageCode: 'sr', scriptCode: 'Cyrl', countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationSrCyrl, true);
+    expect(localizations, isA<MaterialLocalizationSrCyrl>());
 
     locale = const Locale.fromSubtags(languageCode: 'sr', scriptCode: 'Latn', countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationSrLatn, true);
+    expect(localizations, isA<MaterialLocalizationSrLatn>());
 
     locale = const Locale.fromSubtags(languageCode: 'sr', scriptCode: null, countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationSr, true);
+    expect(localizations, isA<MaterialLocalizationSr>());
   });
 
   testWidgets('Misc resolution', (WidgetTester tester) async {
     Locale locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: null, countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     MaterialLocalizations localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEn, true);
+    expect(localizations, isA<MaterialLocalizationEn>());
 
     locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: 'Cyrl', countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEn, true);
+    expect(localizations, isA<MaterialLocalizationEn>());
 
     locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: null, countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEn, true);
+    expect(localizations, isA<MaterialLocalizationEn>());
 
     locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: null, countryCode: 'AU');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEnAu, true);
+    expect(localizations, isA<MaterialLocalizationEnAu>());
 
     locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: null, countryCode: 'GB');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEnGb, true);
+    expect(localizations, isA<MaterialLocalizationEnGb>());
 
     locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: null, countryCode: 'SG');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEnSg, true);
+    expect(localizations, isA<MaterialLocalizationEnSg>());
 
     locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: null, countryCode: 'MX');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEn, true);
+    expect(localizations, isA<MaterialLocalizationEn>());
 
     locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: 'Hant', countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEn, true);
+    expect(localizations, isA<MaterialLocalizationEn>());
 
     locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: 'Hant', countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEn, true);
+    expect(localizations, isA<MaterialLocalizationEn>());
 
     locale = const Locale.fromSubtags(languageCode: 'en', scriptCode: 'Hans', countryCode: 'CN');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEn, true);
+    expect(localizations, isA<MaterialLocalizationEn>());
 
     locale = const Locale.fromSubtags(languageCode: 'es', scriptCode: null, countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEs, true);
+    expect(localizations, isA<MaterialLocalizationEs>());
 
     locale = const Locale.fromSubtags(languageCode: 'es', scriptCode: null, countryCode: '419');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEs419, true);
+    expect(localizations, isA<MaterialLocalizationEs419>());
 
     locale = const Locale.fromSubtags(languageCode: 'es', scriptCode: null, countryCode: 'MX');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEsMx, true);
+    expect(localizations, isA<MaterialLocalizationEsMx>());
 
     locale = const Locale.fromSubtags(languageCode: 'es', scriptCode: null, countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEsUs, true);
+    expect(localizations, isA<MaterialLocalizationEsUs>());
 
     locale = const Locale.fromSubtags(languageCode: 'es', scriptCode: null, countryCode: 'AR');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEsAr, true);
+    expect(localizations, isA<MaterialLocalizationEsAr>());
 
     locale = const Locale.fromSubtags(languageCode: 'es', scriptCode: null, countryCode: 'ES');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEs, true);
+    expect(localizations, isA<MaterialLocalizationEs>());
 
     locale = const Locale.fromSubtags(languageCode: 'es', scriptCode: 'Latn', countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEs, true);
+    expect(localizations, isA<MaterialLocalizationEs>());
 
     locale = const Locale.fromSubtags(languageCode: 'es', scriptCode: 'Latn', countryCode: 'US');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationEsUs, true);
+    expect(localizations, isA<MaterialLocalizationEsUs>());
 
     locale = const Locale.fromSubtags(languageCode: 'fr', scriptCode: null, countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationFr, true);
+    expect(localizations, isA<MaterialLocalizationFr>());
 
     locale = const Locale.fromSubtags(languageCode: 'fr', scriptCode: null, countryCode: 'CA');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationFrCa, true);
+    expect(localizations, isA<MaterialLocalizationFrCa>());
 
     locale = const Locale.fromSubtags(languageCode: 'de', scriptCode: null, countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationDe, true);
+    expect(localizations, isA<MaterialLocalizationDe>());
 
     locale = const Locale.fromSubtags(languageCode: 'de', scriptCode: null, countryCode: 'CH');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationDeCh, true);
+    expect(localizations, isA<MaterialLocalizationDeCh>());
 
     locale = const Locale.fromSubtags(languageCode: 'th', scriptCode: null, countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationTh, true);
+    expect(localizations, isA<MaterialLocalizationTh>());
 
     locale = const Locale.fromSubtags(languageCode: 'ru', scriptCode: null, countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationRu, true);
+    expect(localizations, isA<MaterialLocalizationRu>());
   });
 
   testWidgets('Chinese translations spot check', (WidgetTester tester) async {
     Locale locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: null, countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     MaterialLocalizations localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZh, true);
+    expect(localizations, isA<MaterialLocalizationZh>());
     expect(localizations.alertDialogLabel, '提醒');
     expect(localizations.anteMeridiemAbbreviation, '上午');
     expect(localizations.closeButtonLabel, '关闭');
@@ -429,7 +429,7 @@
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans', countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHans, true);
+    expect(localizations, isA<MaterialLocalizationZhHans>());
     expect(localizations.alertDialogLabel, '提醒');
     expect(localizations.anteMeridiemAbbreviation, '上午');
     expect(localizations.closeButtonLabel, '关闭');
@@ -438,7 +438,7 @@
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: null);
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHant, true);
+    expect(localizations, isA<MaterialLocalizationZhHant>());
     expect(localizations.alertDialogLabel, '通知');
     expect(localizations.anteMeridiemAbbreviation, '上午');
     expect(localizations.closeButtonLabel, '關閉');
@@ -447,7 +447,7 @@
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'TW');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHantTw, true);
+    expect(localizations, isA<MaterialLocalizationZhHantTw>());
     expect(localizations.alertDialogLabel, '快訊');
     expect(localizations.anteMeridiemAbbreviation, '上午');
     expect(localizations.closeButtonLabel, '關閉');
@@ -456,7 +456,7 @@
     locale = const Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant', countryCode: 'HK');
     expect(GlobalMaterialLocalizations.delegate.isSupported(locale), isTrue);
     localizations = await GlobalMaterialLocalizations.delegate.load(locale);
-    expect(localizations is MaterialLocalizationZhHantHk, true);
+    expect(localizations, isA<MaterialLocalizationZhHantHk>());
     expect(localizations.alertDialogLabel, '通知');
     expect(localizations.anteMeridiemAbbreviation, '上午');
     expect(localizations.closeButtonLabel, '關閉');
diff --git a/packages/flutter_test/lib/src/matchers.dart b/packages/flutter_test/lib/src/matchers.dart
index ec45939..7e26302 100644
--- a/packages/flutter_test/lib/src/matchers.dart
+++ b/packages/flutter_test/lib/src/matchers.dart
@@ -162,7 +162,7 @@
 
 /// A matcher for functions that throw [FlutterError].
 ///
-/// This is equivalent to `throwsA(isInstanceOf<FlutterError>())`.
+/// This is equivalent to `throwsA(isA<FlutterError>())`.
 ///
 /// If you are trying to test whether a call to [WidgetTester.pumpWidget]
 /// results in a [FlutterError], see [TestWidgetsFlutterBinding.takeException].
@@ -176,7 +176,7 @@
 
 /// A matcher for functions that throw [AssertionError].
 ///
-/// This is equivalent to `throwsA(isInstanceOf<AssertionError>())`.
+/// This is equivalent to `throwsA(isA<AssertionError>())`.
 ///
 /// If you are trying to test whether a call to [WidgetTester.pumpWidget]
 /// results in an [AssertionError], see
@@ -197,7 +197,7 @@
 ///
 ///  * [throwsFlutterError], to test if a function throws a [FlutterError].
 ///  * [isAssertionError], to test if any object is any kind of [AssertionError].
-final Matcher isFlutterError = isInstanceOf<FlutterError>();
+final test_package.TypeMatcher<FlutterError> isFlutterError = isA<FlutterError>();
 
 /// A matcher for [AssertionError].
 ///
@@ -207,11 +207,11 @@
 ///
 ///  * [throwsAssertionError], to test if a function throws any [AssertionError].
 ///  * [isFlutterError], to test if any object is a [FlutterError].
-final Matcher isAssertionError = isInstanceOf<AssertionError>();
+final test_package.TypeMatcher<AssertionError> isAssertionError = isA<AssertionError>();
 
 /// A matcher that compares the type of the actual value to the type argument T.
 // TODO(ianh): Remove this once https://github.com/dart-lang/matcher/issues/98 is fixed
-Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();
+test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
 
 /// Asserts that two [double]s are equal, within some tolerated error.
 ///
diff --git a/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_false_test.dart b/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_false_test.dart
index 7799762..e39c709 100644
--- a/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_false_test.dart
+++ b/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_false_test.dart
@@ -9,7 +9,7 @@
 void main() {
   test('$WidgetsBinding initializes with $LiveTestWidgetsFlutterBinding when FLUTTER_TEST = "false"', () {
     TestWidgetsFlutterBinding.ensureInitialized(<String, String>{'FLUTTER_TEST': 'false'});
-    expect(WidgetsBinding.instance, isInstanceOf<LiveTestWidgetsFlutterBinding>());
+    expect(WidgetsBinding.instance, isA<LiveTestWidgetsFlutterBinding>());
   }, onPlatform: const <String, dynamic>{
     'browser': <Skip>[Skip('Browser will not use the live binding')]
   });
diff --git a/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_not_true_or_false_test.dart b/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_not_true_or_false_test.dart
index 8510a91..6b62b97 100644
--- a/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_not_true_or_false_test.dart
+++ b/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_not_true_or_false_test.dart
@@ -9,6 +9,6 @@
 void main() {
   test('$WidgetsBinding initializes with $AutomatedTestWidgetsFlutterBinding when FLUTTER_TEST has a value that is not "true" or "false"', () {
     TestWidgetsFlutterBinding.ensureInitialized(<String, String>{'FLUTTER_TEST': 'value that is neither "true" nor "false"'});
-    expect(WidgetsBinding.instance, isInstanceOf<AutomatedTestWidgetsFlutterBinding>());
+    expect(WidgetsBinding.instance, isA<AutomatedTestWidgetsFlutterBinding>());
   });
 }
diff --git a/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_null_test.dart b/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_null_test.dart
index 751c6e9..b42b4fb 100644
--- a/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_null_test.dart
+++ b/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_null_test.dart
@@ -9,6 +9,6 @@
 void main() {
   test('$WidgetsBinding initializes with $AutomatedTestWidgetsFlutterBinding when FLUTTER_TEST is defined but null', () {
     TestWidgetsFlutterBinding.ensureInitialized(<String, String>{'FLUTTER_TEST': null});
-    expect(WidgetsBinding.instance, isInstanceOf<AutomatedTestWidgetsFlutterBinding>());
+    expect(WidgetsBinding.instance, isA<AutomatedTestWidgetsFlutterBinding>());
   });
 }
diff --git a/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_true_test.dart b/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_true_test.dart
index 0e8c16a..d44a683 100644
--- a/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_true_test.dart
+++ b/packages/flutter_test/test/bindings_environment/flutter_test_variable_is_true_test.dart
@@ -9,6 +9,6 @@
 void main() {
   test('$WidgetsBinding initializes with $AutomatedTestWidgetsFlutterBinding when FLUTTER_TEST = "true"', () {
     TestWidgetsFlutterBinding.ensureInitialized(<String, String>{'FLUTTER_TEST': 'true'});
-    expect(WidgetsBinding.instance, isInstanceOf<AutomatedTestWidgetsFlutterBinding>());
+    expect(WidgetsBinding.instance, isA<AutomatedTestWidgetsFlutterBinding>());
   });
 }
diff --git a/packages/flutter_test/test/bindings_environment/no_flutter_test_variable_test.dart b/packages/flutter_test/test/bindings_environment/no_flutter_test_variable_test.dart
index 16771c3..72f75f1 100644
--- a/packages/flutter_test/test/bindings_environment/no_flutter_test_variable_test.dart
+++ b/packages/flutter_test/test/bindings_environment/no_flutter_test_variable_test.dart
@@ -9,6 +9,6 @@
 void main() {
   test('$WidgetsBinding initializes with $LiveTestWidgetsFlutterBinding when the environment does not contain FLUTTER_TEST', () {
     TestWidgetsFlutterBinding.ensureInitialized(<String, String>{});
-    expect(WidgetsBinding.instance, isInstanceOf<LiveTestWidgetsFlutterBinding>());
+    expect(WidgetsBinding.instance, isA<LiveTestWidgetsFlutterBinding>());
   });
 }
diff --git a/packages/flutter_test/test/custom_exception_reporter/flutter_test_config.dart b/packages/flutter_test/test/custom_exception_reporter/flutter_test_config.dart
index 5badb63..6e92939 100644
--- a/packages/flutter_test/test/custom_exception_reporter/flutter_test_config.dart
+++ b/packages/flutter_test/test/custom_exception_reporter/flutter_test_config.dart
@@ -9,7 +9,7 @@
 
 Future<void> main(FutureOr<void> testMain()) async {
   reportTestException = (FlutterErrorDetails details, String testDescription) {
-    expect(details.exception, isInstanceOf<StateError>());
+    expect(details.exception, isA<StateError>());
     expect(details.exception.message, 'foo');
     expect(testDescription, 'custom exception reporter');
   };
diff --git a/packages/flutter_test/test/goldens_test.dart b/packages/flutter_test/test/goldens_test.dart
index fbff2b7..4f30955 100644
--- a/packages/flutter_test/test/goldens_test.dart
+++ b/packages/flutter_test/test/goldens_test.dart
@@ -76,7 +76,7 @@
   group('goldenFileComparator', () {
     test('is initialized by test framework', () {
       expect(goldenFileComparator, isNotNull);
-      expect(goldenFileComparator, isInstanceOf<LocalFileComparator>());
+      expect(goldenFileComparator, isA<LocalFileComparator>());
       final LocalFileComparator comparator = goldenFileComparator as LocalFileComparator;
       expect(comparator.basedir.path, contains('flutter_test'));
     });
diff --git a/packages/flutter_test/test/test_async_utils_test.dart b/packages/flutter_test/test/test_async_utils_test.dart
index 5d7c985..9e3e760 100644
--- a/packages/flutter_test/test/test_async_utils_test.dart
+++ b/packages/flutter_test/test/test_async_utils_test.dart
@@ -153,15 +153,15 @@
       real_test.expect(information[3].level, DiagnosticLevel.info);
       real_test.expect(information[4].level, DiagnosticLevel.info);
       real_test.expect(information[5].level, DiagnosticLevel.info);
-      real_test.expect(information[0], isInstanceOf<DiagnosticsProperty<void>>());
-      real_test.expect(information[1], isInstanceOf<DiagnosticsProperty<void>>());
-      real_test.expect(information[2], isInstanceOf<DiagnosticsProperty<void>>());
-      real_test.expect(information[3], isInstanceOf<DiagnosticsProperty<void>>());
-      real_test.expect(information[4], isInstanceOf<DiagnosticsProperty<void>>());
-      real_test.expect(information[5], isInstanceOf<DiagnosticsStackTrace>());
+      real_test.expect(information[0], isA<DiagnosticsProperty<void>>());
+      real_test.expect(information[1], isA<DiagnosticsProperty<void>>());
+      real_test.expect(information[2], isA<DiagnosticsProperty<void>>());
+      real_test.expect(information[3], isA<DiagnosticsProperty<void>>());
+      real_test.expect(information[4], isA<DiagnosticsProperty<void>>());
+      real_test.expect(information[5], isA<DiagnosticsStackTrace>());
       final DiagnosticsStackTrace stackTraceProperty = information[5] as DiagnosticsStackTrace;
       real_test.expect(stackTraceProperty.name, '\nWhen the first method was called, this was the stack');
-      real_test.expect(stackTraceProperty.value, isInstanceOf<StackTrace>());
+      real_test.expect(stackTraceProperty.value, isA<StackTrace>());
     }
     await f1;
     await f2;
diff --git a/packages/flutter_test/test/test_text_input_test.dart b/packages/flutter_test/test/test_text_input_test.dart
index 116e23f..dfcc602 100644
--- a/packages/flutter_test/test/test_text_input_test.dart
+++ b/packages/flutter_test/test/test_text_input_test.dart
@@ -29,7 +29,7 @@
       await tester.testTextInput.receiveAction(TextInputAction.done);
       fail('Expected a PlatformException, but it was not thrown.');
     } catch (e) {
-      expect(e, isInstanceOf<PlatformException>());
+      expect(e, isA<PlatformException>());
     }
   });
 }
diff --git a/packages/flutter_test/test/widget_tester_test.dart b/packages/flutter_test/test/widget_tester_test.dart
index 0222794..2d06a49 100644
--- a/packages/flutter_test/test/widget_tester_test.dart
+++ b/packages/flutter_test/test/widget_tester_test.dart
@@ -33,8 +33,7 @@
         ),
       );
 
-      expect(() => tester.getSemantics(find.text('hello')),
-        throwsA(isInstanceOf<StateError>()));
+      expect(() => tester.getSemantics(find.text('hello')), throwsStateError);
     }, semanticsEnabled: false);
 
     testWidgets('throws when there are multiple results from the finder', (WidgetTester tester) async {
@@ -53,8 +52,7 @@
         ),
       );
 
-      expect(() => tester.getSemantics(find.text('hello')),
-          throwsA(isInstanceOf<StateError>()));
+      expect(() => tester.getSemantics(find.text('hello')), throwsStateError);
       semanticsHandle.dispose();
     });
 
@@ -472,7 +470,7 @@
 
       expect(
         expectAsync0(tester.pageBack),
-        throwsA(isInstanceOf<TestFailure>()),
+        throwsA(isA<TestFailure>()),
       );
     });
 
@@ -629,7 +627,7 @@
     testWidgets('disallows re-entry', (WidgetTester tester) async {
       final Completer<void> completer = Completer<void>();
       tester.runAsync<void>(() => completer.future);
-      expect(() => tester.runAsync(() async { }), throwsA(isInstanceOf<TestFailure>()));
+      expect(() => tester.runAsync(() async { }), throwsA(isA<TestFailure>()));
       completer.complete();
     });
 
@@ -685,7 +683,7 @@
         'calling dispose() on the AnimationController itself. Otherwise,\n'
         'the ticker will leak.\n',
       );
-      expect(error.diagnostics.last, isInstanceOf<DiagnosticsProperty<Ticker>>());
+      expect(error.diagnostics.last, isA<DiagnosticsProperty<Ticker>>());
       expect(error.diagnostics.last.value, ticker);
       expect(error.toStringDeep(), startsWith(
         'FlutterError\n'
@@ -746,7 +744,6 @@
       }
     }, variant: TargetPlatformVariant.all());
   });
-
 }
 
 class FakeMatcher extends AsyncMatcher {
diff --git a/packages/flutter_tools/lib/src/android/android_emulator.dart b/packages/flutter_tools/lib/src/android/android_emulator.dart
index b7c0557..0aeb57d 100644
--- a/packages/flutter_tools/lib/src/android/android_emulator.dart
+++ b/packages/flutter_tools/lib/src/android/android_emulator.dart
@@ -8,8 +8,12 @@
 
 import '../android/android_sdk.dart';
 import '../android/android_workflow.dart';
+import '../base/common.dart';
 import '../base/file_system.dart';
+import '../base/io.dart';
 import '../base/process.dart';
+import '../base/utils.dart';
+import '../convert.dart';
 import '../device.dart';
 import '../emulator.dart';
 import '../globals.dart' as globals;
@@ -50,18 +54,59 @@
 
   @override
   Future<void> launch() async {
-    final Future<void> launchResult = processUtils.run(
-      <String>[getEmulatorPath(), '-avd', id],
-      throwOnError: true,
+    final Process process = await processUtils.start(
+      <String>[getEmulatorPath(androidSdk), '-avd', id],
     );
-    // The emulator continues running on a successful launch, so if it hasn't
-    // quit within 3 seconds we assume that's a success and just return. This
-    // means that on a slow machine, a failure that takes more than three
-    // seconds won't be recognized as such... :-/
-    return Future.any<void>(<Future<void>>[
-      launchResult,
-      Future<void>.delayed(const Duration(seconds: 3)),
+
+    // Record output from the emulator process.
+    final List<String> stdoutList = <String>[];
+    final List<String> stderrList = <String>[];
+    final StreamSubscription<String> stdoutSubscription = process.stdout
+      .transform<String>(utf8.decoder)
+      .transform<String>(const LineSplitter())
+      .listen(stdoutList.add);
+    final StreamSubscription<String> stderrSubscription = process.stderr
+      .transform<String>(utf8.decoder)
+      .transform<String>(const LineSplitter())
+      .listen(stderrList.add);
+    final Future<void> stdioFuture = waitGroup<void>(<Future<void>>[
+      stdoutSubscription.asFuture<void>(),
+      stderrSubscription.asFuture<void>(),
     ]);
+
+    // The emulator continues running on success, so we don't wait for the
+    // process to complete before continuing. However, if the process fails
+    // after the startup phase (3 seconds), then we only echo its output if
+    // its error code is non-zero and its stderr is non-empty.
+    bool earlyFailure = true;
+    unawaited(process.exitCode.then((int status) async {
+      if (status == 0) {
+        globals.printTrace('The Android emulator exited successfully');
+        return;
+      }
+      // Make sure the process' stdout and stderr are drained.
+      await stdioFuture;
+      unawaited(stdoutSubscription.cancel());
+      unawaited(stderrSubscription.cancel());
+      if (stdoutList.isNotEmpty) {
+        globals.printTrace('Android emulator stdout:');
+        stdoutList.forEach(globals.printTrace);
+      }
+      if (!earlyFailure && stderrList.isEmpty) {
+        globals.printStatus('The Android emulator exited with code $status');
+        return;
+      }
+      final String when = earlyFailure ? 'during startup' : 'after startup';
+      globals.printError('The Android emulator exited with code $status $when');
+      globals.printError('Android emulator stderr:');
+      stderrList.forEach(globals.printError);
+      globals.printError('Address these issues and try again.');
+    }));
+
+    // Wait a few seconds for the emulator to start.
+    await Future<void>.delayed(const Duration(seconds: 3));
+    earlyFailure = false;
+    return;
   }
 }
 
diff --git a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
index 3f159aa..a7dda4c 100644
--- a/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
+++ b/packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
@@ -22,11 +22,14 @@
 import '../base/terminal.dart';
 import '../base/utils.dart';
 import '../build_info.dart';
+import '../compile.dart';
 import '../convert.dart';
 import '../devfs.dart';
 import '../device.dart';
 import '../features.dart';
 import '../globals.dart' as globals;
+import '../platform_plugins.dart';
+import '../plugins.dart';
 import '../project.dart';
 import '../reporting/reporting.dart';
 import '../resident_runner.dart';
@@ -98,6 +101,10 @@
   final List<String> dartDefines;
   DateTime firstBuildTime;
 
+  // Used with the new compiler to generate a bootstrap file containing plugins
+  // and platform initialization.
+  Directory _generatedEntrypointDirectory;
+
   // Only the debug builds of the web support the service protocol.
   @override
   bool get supportsServiceProtocol => isRunningDebug && deviceIsDebuggable;
@@ -151,6 +158,7 @@
     await _stdOutSub?.cancel();
     await _webFs?.stop();
     await device.device.stopApp(null);
+    _generatedEntrypointDirectory?.deleteSync(recursive: true);
     if (ChromeLauncher.hasChromeInstance) {
       final Chrome chrome = await ChromeLauncher.connectedInstance;
       await chrome.close();
@@ -478,6 +486,46 @@
     return OperationResult.ok;
   }
 
+  // Flutter web projects need to include a generated main entrypoint to call the
+  // appropriate bootstrap method and inject plugins.
+  // Keep this in sync with build_system/targets/web.dart.
+  Future<String> _generateEntrypoint(String main, String packagesPath) async {
+    File result = _generatedEntrypointDirectory?.childFile('web_entrypoint.dart');
+    if (_generatedEntrypointDirectory == null) {
+      _generatedEntrypointDirectory ??= globals.fs.systemTempDirectory.createTempSync('flutter_tools.')
+        ..createSync();
+      result = _generatedEntrypointDirectory.childFile('web_entrypoint.dart');
+
+      final bool hasWebPlugins = findPlugins(flutterProject)
+        .any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
+      await injectPlugins(flutterProject, checkProjects: true);
+
+      final PackageUriMapper packageUriMapper = PackageUriMapper(main, packagesPath, null, null);
+      final String generatedPath = globals.fs.currentDirectory
+        .childDirectory('lib')
+        .childFile('generated_plugin_registrant.dart')
+        .absolute.path;
+      final Uri generatedImport = packageUriMapper.map(generatedPath);
+
+      final String entrypoint = <String>[
+        'import "${packageUriMapper.map(main)}" as entrypoint;',
+        'import "dart:ui" as ui;',
+        if (hasWebPlugins)
+          'import "package:flutter_web_plugins/flutter_web_plugins.dart";',
+        if (hasWebPlugins)
+          'import "$generatedImport";',
+        'Future<void> main() async {',
+        if (hasWebPlugins)
+          '  registerPlugins(webPluginRegistry);'
+        '  await ui.webOnlyInitializePlatform();',
+        '  entrypoint.main();',
+        '}',
+      ].join('\n');
+      result.writeAsStringSync(entrypoint);
+    }
+    return result.path;
+  }
+
   Future<UpdateFSReport> _updateDevFS({bool fullRestart = false}) async {
     final bool isFirstUpload = !assetBundle.wasBuiltOnce();
     final bool rebuildBundle = assetBundle.needsBuild();
@@ -499,7 +547,7 @@
       timeout: timeoutConfiguration.fastOperation,
     );
     final UpdateFSReport report = await device.devFS.update(
-      mainPath: mainPath,
+      mainPath: await _generateEntrypoint(mainPath, packagesFilePath),
       target: target,
       bundle: assetBundle,
       firstBuildTime: firstBuildTime,
diff --git a/packages/flutter_tools/lib/src/build_system/targets/web.dart b/packages/flutter_tools/lib/src/build_system/targets/web.dart
index 12ac2e1..a8d0470 100644
--- a/packages/flutter_tools/lib/src/build_system/targets/web.dart
+++ b/packages/flutter_tools/lib/src/build_system/targets/web.dart
@@ -32,6 +32,7 @@
 const String kCspMode = 'cspMode';
 
 /// Generates an entry point for a web target.
+// Keep this in sync with build_runner/resident_web_runner.dart
 class WebEntrypointTarget extends Target {
   const WebEntrypointTarget();
 
diff --git a/packages/flutter_tools/lib/src/commands/emulators.dart b/packages/flutter_tools/lib/src/commands/emulators.dart
index 14671f3..0eaab4c 100644
--- a/packages/flutter_tools/lib/src/commands/emulators.dart
+++ b/packages/flutter_tools/lib/src/commands/emulators.dart
@@ -69,16 +69,7 @@
         "More than one emulator matches '$id':",
       );
     } else {
-      try {
-        await emulators.first.launch();
-      }
-      catch (e) {
-        if (e is String) {
-          globals.printError(e);
-        } else {
-          rethrow;
-        }
-      }
+      await emulators.first.launch();
     }
   }
 
diff --git a/packages/flutter_tools/lib/src/web/bootstrap.dart b/packages/flutter_tools/lib/src/web/bootstrap.dart
index d0435a7..92f2b2c 100644
--- a/packages/flutter_tools/lib/src/web/bootstrap.dart
+++ b/packages/flutter_tools/lib/src/web/bootstrap.dart
@@ -55,7 +55,8 @@
         // once we've reloaded every module, trigger the hot reload.
         if (reloadCount == modules.length) {
           require(["$entrypoint", "dart_sdk"], function(app, dart_sdk) {
-            window.\$mainEntrypoint = app.main.main;
+            // See L81 below for an explanation.
+            window.\$mainEntrypoint = app[Object.keys(app)[0]].main;
             window.\$hotReload(resolve);
           });
         }
@@ -78,22 +79,23 @@
   let voidToNull = () => (voidToNull = dart_sdk.dart.constFn(dart_sdk.dart.fnType(dart_sdk.core.Null, [dart_sdk.dart.void])))();
 
   // Attach the main entrypoint and hot reload functionality to the window.
-  window.\$mainEntrypoint = app.main.main;
+  // The app module will have a single property which contains the actual application
+  // code. The property name is based off of the entrypoint that is generated, for example
+  // the file `foo/bar/baz.dart` will generate a property named approximately
+  // `foo__bar__baz`. Rather than attempt to guess, we assume the first property of
+  // this object is the module.
+  window.\$mainEntrypoint = app[Object.keys(app)[0]].main;
   if (window.\$hotReload == null) {
     window.\$hotReload = function(cb) {
       dart_sdk.developer.invokeExtension("ext.flutter.disassemble", "{}").then((_) => {
         dart_sdk.dart.hotRestart();
-        dart_sdk.ui.webOnlyInitializePlatform().then(dart_sdk.core.Null, dart_sdk.dart.fn(_ => {
-          window.\$mainEntrypoint();
-          window.requestAnimationFrame(cb);
-        }, voidToNull()));
+        window.\$mainEntrypoint();
+        window.requestAnimationFrame(cb);
       });
     }
   }
 
-  dart_sdk.ui.webOnlyInitializePlatform().then(dart_sdk.core.Null, dart_sdk.dart.fn(_ => {
-    app.main.main();
-  }, voidToNull()));
+  window.\$mainEntrypoint();
 });
 
 // Require JS configuration.
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/assemble_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/assemble_test.dart
index 3eeef20..ceeedc1 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/assemble_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/assemble_test.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'package:args/command_runner.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/build_system/build_system.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -53,7 +52,7 @@
     final CommandRunner<void> commandRunner = createTestCommandRunner(AssembleCommand());
 
     expect(commandRunner.run(<String>['assemble', 'debug_macos_bundle_flutter_assets']),
-      throwsA(isInstanceOf<ToolExit>()));
+      throwsToolExit());
   });
 
   testbed.test('Throws ToolExit if called with non-existent rule', () async {
@@ -64,7 +63,7 @@
     final CommandRunner<void> commandRunner = createTestCommandRunner(AssembleCommand());
 
     expect(commandRunner.run(<String>['assemble', '-o Output', 'undefined']),
-      throwsA(isInstanceOf<ToolExit>()));
+      throwsToolExit());
   });
 
   testbed.test('Does not log stack traces during build failure', () async {
@@ -78,7 +77,7 @@
     final CommandRunner<void> commandRunner = createTestCommandRunner(AssembleCommand());
 
     await expectLater(commandRunner.run(<String>['assemble', '-o Output', 'debug_macos_bundle_flutter_assets']),
-      throwsA(isInstanceOf<ToolExit>()));
+      throwsToolExit());
     expect(testLogger.errorText, contains('bar'));
     expect(testLogger.errorText, isNot(contains(testStackTrace.toString())));
   });
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
index c51c372..2231ed7 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
@@ -240,7 +240,7 @@
         });
         testDeviceManager.addDevice(device);
         expect(createTestCommandRunner(AttachCommand()).run(<String>['attach']),
-               throwsA(isA<ToolExit>()));
+               throwsToolExit());
       }, overrides: <Type, Generator>{
         FileSystem: () => testFileSystem,
         ProcessManager: () => FakeProcessManager.any(),
@@ -619,7 +619,7 @@
       final AttachCommand command = AttachCommand();
       await expectLater(
         createTestCommandRunner(command).run(<String>['attach']),
-        throwsA(isInstanceOf<ToolExit>()),
+        throwsToolExit(),
       );
       expect(testLogger.statusText, contains('No supported devices connected'));
     }, overrides: <Type, Generator>{
@@ -642,7 +642,7 @@
       testDeviceManager.addDevice(aDeviceWithId('yy2'));
       await expectLater(
         createTestCommandRunner(command).run(<String>['attach']),
-        throwsA(isInstanceOf<ToolExit>()),
+        throwsToolExit(),
       );
       expect(testLogger.statusText, contains('More than one device'));
       expect(testLogger.statusText, contains('xx1'));
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart
index 404ab86..3597a17 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_fuchsia_test.dart
@@ -5,7 +5,6 @@
 import 'package:file/memory.dart';
 import 'package:platform/platform.dart';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -50,7 +49,7 @@
       expect(
           createTestCommandRunner(command)
               .run(const <String>['build', 'fuchsia']),
-          throwsA(isInstanceOf<ToolExit>()));
+          throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => linuxPlatform,
       FileSystem: () => MemoryFileSystem(),
@@ -67,7 +66,7 @@
       expect(
           createTestCommandRunner(command)
               .run(const <String>['build', 'fuchsia']),
-          throwsA(isInstanceOf<ToolExit>()));
+          throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => linuxPlatform,
       FileSystem: () => MemoryFileSystem(),
@@ -89,7 +88,7 @@
       expect(
           createTestCommandRunner(command)
               .run(const <String>['build', 'fuchsia']),
-          throwsA(isInstanceOf<ToolExit>()));
+          throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => windowsPlatform,
       FileSystem: () => MemoryFileSystem(),
@@ -111,7 +110,7 @@
       expect(
           createTestCommandRunner(command)
               .run(const <String>['build', 'fuchsia']),
-          throwsA(isInstanceOf<ToolExit>()));
+          throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => linuxPlatform,
       FileSystem: () => MemoryFileSystem(),
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart
index e6a7244..9f1f166 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_linux_test.dart
@@ -8,7 +8,6 @@
 import 'package:mockito/mockito.dart';
 import 'package:process/process.dart';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -101,7 +100,7 @@
 
     expect(createTestCommandRunner(command).run(
       const <String>['build', 'linux']
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }, overrides: <Type, Generator>{
     Platform: () => notLinuxPlatform,
     FileSystem: () => MemoryFileSystem(),
@@ -220,7 +219,7 @@
     final CommandRunner<void> runner = createTestCommandRunner(BuildCommand());
 
     expect(() => runner.run(<String>['build', 'linux']),
-        throwsA(isInstanceOf<ToolExit>()));
+        throwsToolExit());
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(isLinuxEnabled: false),
   });
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart
index 18ad8d4..2797f144 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_macos_test.dart
@@ -6,7 +6,6 @@
 import 'package:file/memory.dart';
 import 'package:platform/platform.dart';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/build_info.dart';
@@ -127,7 +126,7 @@
 
     expect(createTestCommandRunner(command).run(
       const <String>['build', 'macos']
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }, overrides: <Type, Generator>{
     Platform: () => notMacosPlatform,
     FileSystem: () => MemoryFileSystem(),
@@ -206,7 +205,7 @@
     final CommandRunner<void> runner = createTestCommandRunner(BuildCommand());
 
     expect(() => runner.run(<String>['build', 'macos']),
-        throwsA(isInstanceOf<ToolExit>()));
+        throwsToolExit());
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(isMacOSEnabled: false),
   });
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart
index 96c790d..b5026e5 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_web_test.dart
@@ -5,7 +5,6 @@
 import 'package:args/command_runner.dart';
 import 'package:platform/platform.dart';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/build_system/build_system.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -60,7 +59,7 @@
       false,
       const <String>[],
       false,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }));
 
   test('Refuses to build using runner when missing index.html', () => testbed.run(() async {
@@ -82,7 +81,7 @@
     final CommandRunner<void> runner = createTestCommandRunner(BuildCommand());
 
     expect(() => runner.run(<String>['build', 'web', '--debug']),
-        throwsA(isInstanceOf<UsageException>()));
+        throwsA(isA<UsageException>()));
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(isWebEnabled: true),
   }));
@@ -91,7 +90,7 @@
     final CommandRunner<void> runner = createTestCommandRunner(BuildCommand());
 
     expect(() => runner.run(<String>['build', 'web']),
-        throwsA(isInstanceOf<ToolExit>()));
+        throwsToolExit());
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(isWebEnabled: false),
   }));
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart
index 5b2f571..0ec38b5 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/build_windows_test.dart
@@ -5,7 +5,6 @@
 import 'package:file/memory.dart';
 import 'package:platform/platform.dart';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -77,7 +76,7 @@
     setUpMockProjectFilesForBuild();
     expect(createTestCommandRunner(command).run(
       const <String>['build', 'windows']
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }, overrides: <Type, Generator>{
     Platform: () => windowsPlatform,
     FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows),
@@ -110,7 +109,7 @@
 
     expect(createTestCommandRunner(command).run(
       const <String>['build', 'windows']
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }, overrides: <Type, Generator>{
     Platform: () => notWindowsPlatform,
     FileSystem: () => MemoryFileSystem(style: FileSystemStyle.windows),
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/config_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/config_test.dart
index bcb4338..8c6def3 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/config_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/config_test.dart
@@ -7,7 +7,6 @@
 import 'package:args/command_runner.dart';
 import 'package:flutter_tools/src/android/android_sdk.dart';
 import 'package:flutter_tools/src/android/android_studio.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -102,7 +101,7 @@
       expect(() => commandRunner.run(<String>[
         'config',
         '--build-dir=/foo',
-      ]), throwsA(isInstanceOf<ToolExit>()));
+      ]), throwsToolExit());
       verifyNoAnalytics();
     }, overrides: <Type, Generator>{
       Usage: () => mockUsage,
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart
index ba5053b..0cda035 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/daemon_test.dart
@@ -47,7 +47,7 @@
       final Map<String, dynamic> response = await responses.stream.firstWhere(_notEvent);
       expect(response['id'], 0);
       expect(response['result'], isNotEmpty);
-      expect(response['result'] is String, true);
+      expect(response['result'], isA<String>());
       await responses.close();
       await commands.close();
     });
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
index ccf8b2f..0257dc1 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
@@ -111,7 +111,7 @@
         ]);
         fail('Expect exception');
       } catch (e) {
-        expect(e, isInstanceOf<ToolExit>());
+        expect(e, isA<ToolExit>());
       }
 
       final BufferLogger bufferLogger = globals.logger as BufferLogger;
diff --git a/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart
index 45a0330..bb11c7a 100644
--- a/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart
+++ b/packages/flutter_tools/test/commands.shard/hermetic/version_test.dart
@@ -107,7 +107,7 @@
           '--no-pub',
           version,
         ]),
-        throwsA(isInstanceOf<ToolExit>()),
+        throwsToolExit(),
       );
     }, overrides: <Type, Generator>{
       ProcessManager: () => MockProcessManager(),
@@ -119,7 +119,7 @@
         await command.getTags();
         fail('ToolExit expected');
       } catch(e) {
-        expect(e, isInstanceOf<ToolExit>());
+        expect(e, isA<ToolExit>());
       }
     }, overrides: <Type, Generator>{
       ProcessManager: () => MockProcessManager(failGitTag: true),
diff --git a/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart b/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart
index 3018b67..2db9ff8 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/build_bundle_test.dart
@@ -4,7 +4,6 @@
 
 import 'package:args/command_runner.dart';
 import 'package:file/memory.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/build_system/build_system.dart';
 import 'package:flutter_tools/src/build_system/targets/dart.dart';
@@ -109,7 +108,7 @@
       'bundle',
       '--no-pub',
       '--target-platform=windows-x64',
-    ]), throwsA(isInstanceOf<ToolExit>()));
+    ]), throwsToolExit());
   }, overrides: <Type, Generator>{
     FileSystem: () => MemoryFileSystem(),
     ProcessManager: () => FakeProcessManager.any(),
@@ -127,7 +126,7 @@
       'bundle',
       '--no-pub',
       '--target-platform=linux-x64',
-    ]), throwsA(isInstanceOf<ToolExit>()));
+    ]), throwsToolExit());
   }, overrides: <Type, Generator>{
     FileSystem: () => MemoryFileSystem(),
     ProcessManager: () => FakeProcessManager.any(),
@@ -145,7 +144,7 @@
       'bundle',
       '--no-pub',
       '--target-platform=darwin-x64',
-    ]), throwsA(isInstanceOf<ToolExit>()));
+    ]), throwsToolExit());
   }, overrides: <Type, Generator>{
     FileSystem: () => MemoryFileSystem(),
     ProcessManager: () => FakeProcessManager.any(),
diff --git a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart
index 4fc4ebc..e89aac6 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/upgrade_test.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
 
@@ -63,7 +62,7 @@
         const GitTagVersion.unknown(),
         flutterVersion,
       );
-      expect(result, throwsA(isInstanceOf<ToolExit>()));
+      expect(result, throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => fakePlatform,
     });
@@ -89,7 +88,7 @@
         gitTagVersion,
         flutterVersion,
       );
-      expect(result, throwsA(isA<ToolExit>()));
+      expect(result, throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => fakePlatform,
     });
diff --git a/packages/flutter_tools/test/general.shard/android/android_device_test.dart b/packages/flutter_tools/test/general.shard/android/android_device_test.dart
index c6ade4c..62f2171 100644
--- a/packages/flutter_tools/test/general.shard/android/android_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/android_device_test.dart
@@ -13,7 +13,6 @@
 import 'package:flutter_tools/src/application_package.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
-import 'package:flutter_tools/src/base/process.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/device.dart';
 import 'package:flutter_tools/src/project.dart';
@@ -44,45 +43,6 @@
   File get file => MockFile();
 }
 
-class MockProcessUtils extends Mock implements ProcessUtils {
-  @override
-  Future<RunResult> run(
-      List<String> cmd, {
-        bool throwOnError = false,
-        RunResultChecker whiteListFailures,
-        String workingDirectory,
-        bool allowReentrantFlutter = false,
-        Map<String, String> environment,
-        Duration timeout,
-        int timeoutRetries = 0,
-      }) async {
-    if (cmd.contains('version')) {
-      return RunResult(ProcessResult(0, 0, 'Android Debug Bridge version 1.0.41', ''), cmd);
-    }
-    if (cmd.contains('android.intent.action.RUN')) {
-      _runCmd = cmd;
-    }
-    return RunResult(ProcessResult(0, 0, '', ''), cmd);
-  }
-
-  @override
-  Future<int> stream(
-      List<String> cmd, {
-        String workingDirectory,
-        bool allowReentrantFlutter = false,
-        String prefix = '',
-        bool trace = false,
-        RegExp filter,
-        StringConverter mapFunction,
-        Map<String, String> environment,
-      }) async {
-    return 0;
-  }
-
-  List<String> _runCmd;
-  List<String> get runCmd => _runCmd;
-}
-
 class MockAndroidSdkVersion extends Mock implements AndroidSdkVersion {}
 
 void main() {
@@ -97,13 +57,11 @@
       MockAndroidApk mockApk;
       MockProcessManager mockProcessManager;
       MockAndroidSdk mockAndroidSdk;
-      MockProcessUtils mockProcessUtils;
 
       setUp(() {
         mockApk = MockAndroidApk();
         mockProcessManager = MockProcessManager();
         mockAndroidSdk = MockAndroidSdk();
-        mockProcessUtils = MockProcessUtils();
       });
 
       testUsingContext('succeeds with --cache-sksl', () async {
@@ -124,6 +82,20 @@
         )).thenAnswer((_) async {
           return ProcessResult(0, 0, '[ro.build.version.sdk]: [24]', '');
         });
+        when(mockProcessManager.run(
+          any,
+          workingDirectory: anyNamed('workingDirectory'),
+          environment: anyNamed('environment')
+        )).thenAnswer((_) async {
+          return ProcessResult(0, 0, '', '');
+        });
+        when(mockProcessManager.start(
+          any,
+          workingDirectory: anyNamed('workingDirectory'),
+          environment: anyNamed('environment')
+        )).thenAnswer((_) async {
+          return FakeProcess();
+        });
 
         final LaunchResult launchResult = await device.startApp(
           mockApk,
@@ -134,18 +106,14 @@
           ),
           platformArgs: <String, dynamic>{},
         );
-        expect(launchResult.started, isTrue);
 
-        final int cmdIndex = mockProcessUtils.runCmd.indexOf('cache-sksl');
-        expect(
-            mockProcessUtils.runCmd.sublist(cmdIndex - 1, cmdIndex + 2),
-            equals(<String>['--ez', 'cache-sksl', 'true']),
-        );
+        expect(launchResult.started, isTrue);
+        expect(verify(mockProcessManager.run(captureAny)).captured.last.join(','),
+          contains(<String>['--ez', 'cache-sksl', 'true'].join(',')));
       }, overrides: <Type, Generator>{
         AndroidSdk: () => mockAndroidSdk,
         FileSystem: () => MemoryFileSystem(),
         ProcessManager: () => mockProcessManager,
-        ProcessUtils: () => mockProcessUtils,
       });
 
       testUsingContext('can run a release build on x64', () async {
@@ -166,6 +134,20 @@
         )).thenAnswer((_) async {
           return ProcessResult(0, 0, '[ro.build.version.sdk]: [24]\n[ro.product.cpu.abi]: [x86_64]', '');
         });
+        when(mockProcessManager.run(
+          any,
+          workingDirectory: anyNamed('workingDirectory'),
+          environment: anyNamed('environment')
+        )).thenAnswer((_) async {
+          return ProcessResult(0, 0, '', '');
+        });
+        when(mockProcessManager.start(
+          any,
+          workingDirectory: anyNamed('workingDirectory'),
+          environment: anyNamed('environment')
+        )).thenAnswer((_) async {
+          return FakeProcess();
+        });
 
         final LaunchResult launchResult = await device.startApp(
           mockApk,
@@ -180,7 +162,6 @@
         AndroidSdk: () => mockAndroidSdk,
         FileSystem: () => MemoryFileSystem(),
         ProcessManager: () => mockProcessManager,
-        ProcessUtils: () => mockProcessUtils,
       });
     });
   });
@@ -652,7 +633,7 @@
       when(mockProcessManager.run(argThat(contains('forward'))))
           .thenAnswer((_) async => ProcessResult(0, 0, '123456', ''));
 
-      expect(forwarder.forward(123, hostPort: 456), throwsA(isInstanceOf<ProcessException>()));
+      expect(forwarder.forward(123, hostPort: 456), throwsA(isA<ProcessException>()));
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
     });
diff --git a/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart b/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart
index 5f37cc2..9b776a2 100644
--- a/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart
@@ -2,11 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:async';
+
+import 'package:file/file.dart';
+import 'package:file/memory.dart';
+import 'package:flutter_tools/src/android/android_sdk.dart'
+  show getEmulatorPath, AndroidSdk, androidSdk;
 import 'package:flutter_tools/src/android/android_emulator.dart';
+import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/device.dart';
+import 'package:mockito/mockito.dart';
+import 'package:quiver/testing/async.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
+import '../../src/fake_process_manager.dart';
+import '../../src/mocks.dart' show MockAndroidSdk;
 
 void main() {
   group('android_emulator', () {
@@ -18,8 +29,10 @@
     });
     testUsingContext('flags emulators with config', () {
       const String emulatorID = '1234';
-      final AndroidEmulator emulator =
-          AndroidEmulator(emulatorID, <String, String>{'name': 'test'});
+      final AndroidEmulator emulator = AndroidEmulator(
+        emulatorID,
+        <String, String>{'name': 'test'},
+      );
       expect(emulator.id, emulatorID);
       expect(emulator.hasConfig, true);
     });
@@ -31,8 +44,7 @@
         'hw.device.manufacturer': manufacturer,
         'avd.ini.displayname': displayName,
       };
-      final AndroidEmulator emulator =
-          AndroidEmulator(emulatorID, properties);
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID, properties);
       expect(emulator.id, emulatorID);
       expect(emulator.name, displayName);
       expect(emulator.manufacturer, manufacturer);
@@ -45,8 +57,7 @@
       final Map<String, String> properties = <String, String>{
         'avd.ini.displayname': displayName,
       };
-      final AndroidEmulator emulator =
-          AndroidEmulator(emulatorID, properties);
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID, properties);
       expect(emulator.name, displayName);
     });
     testUsingContext('uses cleaned up ID if no displayname is set', () {
@@ -56,8 +67,7 @@
       final Map<String, String> properties = <String, String>{
         'avd.ini.notadisplayname': 'this is not a display name',
       };
-      final AndroidEmulator emulator =
-          AndroidEmulator(emulatorID, properties);
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID, properties);
       expect(emulator.name, 'This is my ID');
     });
     testUsingContext('parses ini files', () {
@@ -74,4 +84,98 @@
       expect(results['avd.ini.displayname'], 'dispName');
     });
   });
+
+  group('Android emulator launch ', () {
+    const String emulatorID = 'i1234';
+    const String errorText = '[Android emulator test error]';
+    MockAndroidSdk mockSdk;
+    FakeProcessManager successProcessManager;
+    FakeProcessManager errorProcessManager;
+    FakeProcessManager lateFailureProcessManager;
+    MemoryFileSystem fs;
+
+    setUp(() {
+      fs = MemoryFileSystem();
+      mockSdk = MockAndroidSdk();
+      when(mockSdk.emulatorPath).thenReturn('emulator');
+
+      const List<String> command = <String>[
+        'emulator', '-avd', emulatorID,
+      ];
+
+      successProcessManager = FakeProcessManager.list(<FakeCommand>[
+        const FakeCommand(command: command),
+      ]);
+
+      errorProcessManager = FakeProcessManager.list(<FakeCommand>[
+        const FakeCommand(
+          command: command,
+          exitCode: 1,
+          stderr: errorText,
+          stdout: 'dummy text',
+          duration: Duration(seconds: 1),
+        ),
+      ]);
+
+      lateFailureProcessManager = FakeProcessManager.list(<FakeCommand>[
+        const FakeCommand(
+          command: command,
+          exitCode: 1,
+          stderr: '',
+          stdout: 'dummy text',
+          duration: Duration(seconds: 4),
+        ),
+      ]);
+    });
+
+    testUsingContext('succeeds', () async {
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID);
+      expect(getEmulatorPath(androidSdk), mockSdk.emulatorPath);
+      final Completer<void> completer = Completer<void>();
+      FakeAsync().run((FakeAsync time) {
+        unawaited(emulator.launch().whenComplete(completer.complete));
+        time.elapse(const Duration(seconds: 5));
+        time.flushMicrotasks();
+      });
+      await completer.future;
+
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => successProcessManager,
+      AndroidSdk: () => mockSdk,
+      FileSystem: () => fs,
+    });
+
+    testUsingContext('prints error on failure', () async {
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID);
+      final Completer<void> completer = Completer<void>();
+      FakeAsync().run((FakeAsync time) {
+        unawaited(emulator.launch().whenComplete(completer.complete));
+        time.elapse(const Duration(seconds: 5));
+        time.flushMicrotasks();
+      });
+      await completer.future;
+
+      expect(testLogger.errorText, contains(errorText));
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => errorProcessManager,
+      AndroidSdk: () => mockSdk,
+      FileSystem: () => fs,
+    });
+
+    testUsingContext('prints nothing on late failure with empty stderr', () async {
+      final AndroidEmulator emulator = AndroidEmulator(emulatorID);
+      final Completer<void> completer = Completer<void>();
+      FakeAsync().run((FakeAsync time) async {
+        unawaited(emulator.launch().whenComplete(completer.complete));
+        time.elapse(const Duration(seconds: 5));
+        time.flushMicrotasks();
+      });
+      await completer.future;
+      expect(testLogger.errorText, isEmpty);
+    }, overrides: <Type, Generator>{
+      ProcessManager: () => lateFailureProcessManager,
+      AndroidSdk: () => mockSdk,
+      FileSystem: () => fs,
+    });
+  });
 }
diff --git a/packages/flutter_tools/test/general.shard/android/gradle_test.dart b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
index 265267a..cd3f773 100644
--- a/packages/flutter_tools/test/general.shard/android/gradle_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
@@ -1358,7 +1358,7 @@
           localGradleErrors: const <GradleHandledError>[],
         );
       },
-      throwsA(isInstanceOf<ProcessException>()));
+      throwsA(isA<ProcessException>()));
 
     }, overrides: <Type, Generator>{
       AndroidSdk: () => mockAndroidSdk,
diff --git a/packages/flutter_tools/test/general.shard/base/common_test.dart b/packages/flutter_tools/test/general.shard/base/common_test.dart
index 958e0ad..0ffb6c2 100644
--- a/packages/flutter_tools/test/general.shard/base/common_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/common_test.dart
@@ -26,7 +26,7 @@
     });
 
     testWithoutContext('Throws if accessing the Zone', () {
-      expect(() => context.get<Object>(), throwsA(isInstanceOf<UnsupportedError>()));
+      expect(() => context.get<Object>(), throwsA(isA<UnsupportedError>()));
     });
   });
 }
diff --git a/packages/flutter_tools/test/general.shard/base/io_test.dart b/packages/flutter_tools/test/general.shard/base/io_test.dart
index c6778d0..603b07c 100644
--- a/packages/flutter_tools/test/general.shard/base/io_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/io_test.dart
@@ -70,7 +70,7 @@
   });
 
   test('exit throws a StateError if called without being overriden', () {
-    expect(() => exit(0), throwsA(isInstanceOf<AssertionError>()));
+    expect(() => exit(0), throwsAssertionError);
   });
 
   test('exit does not throw a StateError if overriden', () {
diff --git a/packages/flutter_tools/test/general.shard/base/logger_test.dart b/packages/flutter_tools/test/general.shard/base/logger_test.dart
index 69921f6..e1c3374 100644
--- a/packages/flutter_tools/test/general.shard/base/logger_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/logger_test.dart
@@ -182,8 +182,8 @@
           expect(lines.length, equals(1));
 
           // Verify that stopping or canceling multiple times throws.
-          expect(ansiSpinner.stop, throwsA(isInstanceOf<AssertionError>()));
-          expect(ansiSpinner.cancel, throwsA(isInstanceOf<AssertionError>()));
+          expect(ansiSpinner.stop, throwsAssertionError);
+          expect(ansiSpinner.cancel, throwsAssertionError);
           done = true;
         });
         expect(done, isTrue);
@@ -361,8 +361,8 @@
           expect(lines[1], equals(''));
 
           // Verify that stopping or canceling multiple times throws.
-          expect(() { ansiStatus.cancel(); }, throwsA(isInstanceOf<AssertionError>()));
-          expect(() { ansiStatus.stop(); }, throwsA(isInstanceOf<AssertionError>()));
+          expect(() { ansiStatus.cancel(); }, throwsAssertionError);
+          expect(() { ansiStatus.stop(); }, throwsAssertionError);
           done = true;
         });
         expect(done, isTrue);
@@ -405,8 +405,8 @@
           expect(lines[1], equals(''));
 
           // Verify that stopping or canceling multiple times throws.
-          expect(ansiStatus.stop, throwsA(isInstanceOf<AssertionError>()));
-          expect(ansiStatus.cancel, throwsA(isInstanceOf<AssertionError>()));
+          expect(ansiStatus.stop, throwsAssertionError);
+          expect(ansiStatus.cancel, throwsAssertionError);
           done = true;
         });
         expect(done, isTrue);
@@ -775,8 +775,8 @@
       expect(lines[1], equals(''));
 
       // Verify that stopping or canceling multiple times throws.
-      expect(summaryStatus.cancel, throwsA(isInstanceOf<AssertionError>()));
-      expect(summaryStatus.stop, throwsA(isInstanceOf<AssertionError>()));
+      expect(summaryStatus.cancel, throwsAssertionError);
+      expect(summaryStatus.stop, throwsAssertionError);
     });
 
     testWithoutContext('SummaryStatus works when stopped', () async {
@@ -798,8 +798,8 @@
       expect(lines[1], equals(''));
 
       // Verify that stopping or canceling multiple times throws.
-      expect(summaryStatus.stop, throwsA(isInstanceOf<AssertionError>()));
-      expect(summaryStatus.cancel, throwsA(isInstanceOf<AssertionError>()));
+      expect(summaryStatus.stop, throwsAssertionError);
+      expect(summaryStatus.cancel, throwsAssertionError);
     });
 
     testWithoutContext('sequential startProgress calls with StdoutLogger', () async {
diff --git a/packages/flutter_tools/test/general.shard/base/process_test.dart b/packages/flutter_tools/test/general.shard/base/process_test.dart
index 605d417..0259767 100644
--- a/packages/flutter_tools/test/general.shard/base/process_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/process_test.dart
@@ -38,7 +38,7 @@
       when(mockProcessManager.run(<String>['false'])).thenAnswer(
           (Invocation invocation) => Future<ProcessResult>.value(ProcessResult(0, 1, '', '')));
       expect(() async => await processUtils.run(<String>['false'], throwOnError: true),
-             throwsA(isInstanceOf<ProcessException>()));
+             throwsA(isA<ProcessException>()));
     });
   });
 
@@ -236,7 +236,7 @@
         <String>['dummy'],
         timeout: delay - const Duration(milliseconds: 500),
         timeoutRetries: 0,
-      ), throwsA(isInstanceOf<ProcessException>()));
+      ), throwsA(isA<ProcessException>()));
     });
   });
 
diff --git a/packages/flutter_tools/test/general.shard/base/terminal_test.dart b/packages/flutter_tools/test/general.shard/base/terminal_test.dart
index 78bb1d4..d36b959 100644
--- a/packages/flutter_tools/test/general.shard/base/terminal_test.dart
+++ b/packages/flutter_tools/test/general.shard/base/terminal_test.dart
@@ -120,7 +120,7 @@
         <String>['a', 'b', 'c'],
         prompt: 'Please choose something',
         logger: null,
-      ), throwsA(isInstanceOf<StateError>()));
+      ), throwsStateError);
     });
 
     testWithoutContext('character prompt', () async {
diff --git a/packages/flutter_tools/test/general.shard/build_info_test.dart b/packages/flutter_tools/test/general.shard/build_info_test.dart
index 7aa13b9..fcd28ee 100644
--- a/packages/flutter_tools/test/general.shard/build_info_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_info_test.dart
@@ -75,7 +75,7 @@
       expect(BuildMode.fromName('profile'), BuildMode.profile);
       expect(BuildMode.fromName('jit_release'), BuildMode.jitRelease);
       expect(BuildMode.fromName('release'), BuildMode.release);
-      expect(() => BuildMode.fromName('foo'), throwsA(isInstanceOf<ArgumentError>()));
+      expect(() => BuildMode.fromName('foo'), throwsArgumentError);
     });
   });
 }
diff --git a/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart b/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart
index 778fb59..6bc91d5 100644
--- a/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/build_system_test.dart
@@ -309,7 +309,7 @@
     barTarget.dependencies.add(fooTarget);
     fooTarget.dependencies.add(barTarget);
 
-    expect(() => checkCycles(barTarget), throwsA(isInstanceOf<CycleException>()));
+    expect(() => checkCycles(barTarget), throwsA(isA<CycleException>()));
   });
 
   test('Target with depfile dependency will not run twice without invalidation', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/build_system/source_test.dart b/packages/flutter_tools/test/general.shard/build_system/source_test.dart
index a1dd81a..56e22bb 100644
--- a/packages/flutter_tools/test/general.shard/build_system/source_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/source_test.dart
@@ -141,14 +141,14 @@
 
     globals.fs.file('abcd.bar').createSync();
 
-    expect(() => fizzSource.accept(visitor), throwsA(isInstanceOf<InvalidPatternException>()));
+    expect(() => fizzSource.accept(visitor), throwsA(isA<InvalidPatternException>()));
   }));
 
 
   test('can\'t substitute foo', () => testbed.run(() {
     const Source invalidBase = Source.pattern('foo');
 
-    expect(() => invalidBase.accept(visitor), throwsA(isInstanceOf<InvalidPatternException>()));
+    expect(() => invalidBase.accept(visitor), throwsA(isA<InvalidPatternException>()));
   }));
 
   test('can substitute optional files', () => testbed.run(() {
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
index c3c9295..baa0699 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/dart_test.dart
@@ -113,7 +113,7 @@
     final BuildResult result = await buildSystem.build(const KernelSnapshot(),
         androidEnvironment..defines.remove(kBuildMode));
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<MissingDefineException>());
+    expect(result.exceptions.values.single.exception, isA<MissingDefineException>());
   }));
 
   test('kernel_snapshot handles null result from kernel compilation', () => testbed.run(() async {
@@ -141,7 +141,7 @@
     });
     final BuildResult result = await buildSystem.build(const KernelSnapshot(), androidEnvironment);
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<Exception>());
+    expect(result.exceptions.values.single.exception, isA<Exception>());
   }));
 
   test('kernel_snapshot does not use track widget creation on profile builds', () => testbed.run(() async {
@@ -283,35 +283,35 @@
     final BuildResult result = await buildSystem.build(const AotElfProfile(),
         androidEnvironment..defines.remove(kBuildMode));
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<MissingDefineException>());
+    expect(result.exceptions.values.single.exception, isA<MissingDefineException>());
   }));
 
   test('aot_elf_profile throws error if missing target platform', () => testbed.run(() async {
     final BuildResult result = await buildSystem.build(const AotElfProfile(),
         androidEnvironment..defines.remove(kTargetPlatform));
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<MissingDefineException>());
+    expect(result.exceptions.values.single.exception, isA<MissingDefineException>());
   }));
 
   test('aot_assembly_profile throws error if missing build mode', () => testbed.run(() async {
     final BuildResult result = await buildSystem.build(const AotAssemblyProfile(),
         iosEnvironment..defines.remove(kBuildMode));
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<MissingDefineException>());
+    expect(result.exceptions.values.single.exception, isA<MissingDefineException>());
   }));
 
   test('aot_assembly_profile throws error if missing target platform', () => testbed.run(() async {
     final BuildResult result = await buildSystem.build(const AotAssemblyProfile(),
         iosEnvironment..defines.remove(kTargetPlatform));
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<MissingDefineException>());
+    expect(result.exceptions.values.single.exception, isA<MissingDefineException>());
   }));
 
   test('aot_assembly_profile throws error if built for non-iOS platform', () => testbed.run(() async {
     final BuildResult result = await buildSystem
         .build(const AotAssemblyProfile(), androidEnvironment);
 
-    expect(result.exceptions.values.single.exception, isInstanceOf<Exception>());
+    expect(result.exceptions.values.single.exception, isA<Exception>());
   }));
 
   test('aot_assembly_profile will lipo binaries together when multiple archs are requested', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/build_system/targets/macos_test.dart b/packages/flutter_tools/test/general.shard/build_system/targets/macos_test.dart
index e1efca9..f7d7912 100644
--- a/packages/flutter_tools/test/general.shard/build_system/targets/macos_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_system/targets/macos_test.dart
@@ -128,7 +128,7 @@
       ..writeAsStringSync('testing');
 
     expect(() async => await const DebugMacOSBundleFlutterAssets().build(environment),
-        throwsA(isInstanceOf<Exception>()));
+        throwsException);
   }));
 
   test('debug macOS application creates correctly structured framework', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/bundle_shim_test.dart b/packages/flutter_tools/test/general.shard/bundle_shim_test.dart
index 706bf73..770602b 100644
--- a/packages/flutter_tools/test/general.shard/bundle_shim_test.dart
+++ b/packages/flutter_tools/test/general.shard/bundle_shim_test.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/build_system/build_system.dart';
 import 'package:flutter_tools/src/bundle.dart';
@@ -62,7 +61,7 @@
       targetPlatform: TargetPlatform.linux_x64,
       depfilePath: 'example.d',
       precompiled: false,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
   }));
 }
 
diff --git a/packages/flutter_tools/test/general.shard/cache_test.dart b/packages/flutter_tools/test/general.shard/cache_test.dart
index adf3da9..65248b3 100644
--- a/packages/flutter_tools/test/general.shard/cache_test.dart
+++ b/packages/flutter_tools/test/general.shard/cache_test.dart
@@ -12,7 +12,6 @@
 import 'package:process/process.dart';
 
 import 'package:flutter_tools/src/android/gradle_utils.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/cache.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
@@ -72,7 +71,7 @@
     testUsingContext('throws tool exit when lockfile open fails', () async {
       when(mockFileSystem.file(argThat(endsWith('lockfile')))).thenReturn(mockFile);
       when(mockFile.openSync(mode: anyNamed('mode'))).thenThrow(const FileSystemException());
-      expect(() async => await Cache.lock(), throwsA(isA<ToolExit>()));
+      expect(() async => await Cache.lock(), throwsToolExit());
     }, overrides: <Type, Generator>{
       FileSystem: () => mockFileSystem,
       ProcessManager: () => FakeProcessManager.any(),
@@ -248,7 +247,7 @@
         'FLUTTER_STORAGE_BASE_URL': ' http://foo',
       });
       final Cache cache = Cache();
-      expect(() => cache.storageBaseUrl, throwsA(isInstanceOf<ToolExit>()));
+      expect(() => cache.storageBaseUrl, throwsToolExit());
     }, overrides: <Type, Generator>{
       Platform: () => MockPlatform(),
     });
diff --git a/packages/flutter_tools/test/general.shard/compile_incremental_test.dart b/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
index 9279c8b..79788ba 100644
--- a/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_incremental_test.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 
 import 'package:flutter_tools/src/base/async_guard.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/terminal.dart';
 import 'package:flutter_tools/src/build_info.dart';
@@ -82,7 +81,7 @@
       '/path/to/main.dart',
       null, /* invalidatedFiles */
       outputPath: '/build/',
-    )), throwsA(isInstanceOf<ToolExit>()));
+    )), throwsToolExit());
   }, overrides: <Type, Generator>{
     ProcessManager: () => mockProcessManager,
     OutputPreferences: () => OutputPreferences(showColor: false),
@@ -100,7 +99,7 @@
       '/path/to/main.dart',
       null, /* invalidatedFiles */
       outputPath: '/build/',
-    )), throwsA(isInstanceOf<ToolExit>()));
+    )), throwsToolExit());
   }, overrides: <Type, Generator>{
     ProcessManager: () => mockProcessManager,
     OutputPreferences: () => OutputPreferences(showColor: false),
diff --git a/packages/flutter_tools/test/general.shard/compile_test.dart b/packages/flutter_tools/test/general.shard/compile_test.dart
index 412e9d5..7901a82 100644
--- a/packages/flutter_tools/test/general.shard/compile_test.dart
+++ b/packages/flutter_tools/test/general.shard/compile_test.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/compile.dart';
 
 import '../src/common.dart';
@@ -25,7 +24,7 @@
     final Future<CompilerOutput> output = stdoutHandler.compilerOutput.future;
     stdoutHandler.handler('message with no result');
 
-    expect(output, throwsA(isInstanceOf<ToolExit>()));
+    expect(output, throwsToolExit());
   });
 
   test('TargetModel values', () {
@@ -41,6 +40,6 @@
     expect(TargetModel('dartdevc'), TargetModel.dartdevc);
     expect(TargetModel.dartdevc.toString(), 'dartdevc');
 
-    expect(() => TargetModel('foobar'), throwsA(isInstanceOf<AssertionError>()));
+    expect(() => TargetModel('foobar'), throwsAssertionError);
   });
 }
diff --git a/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart b/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart
index ff95577..f820969 100644
--- a/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart
+++ b/packages/flutter_tools/test/general.shard/dart/pub_get_test.dart
@@ -328,7 +328,7 @@
         await pub.get(context: PubContext.flutterTests, checkLastModified: true);
         expect(true, isFalse, reason: 'pub.get did not throw');
       } catch (error) {
-        expect(error, isInstanceOf<Exception>());
+        expect(error, isA<Exception>());
         expect(error.message, '/: unexpected concurrent modification of pubspec.yaml while running pub.');
       }
       expect(testLogger.statusText, 'Running "flutter pub get" in /...\n');
diff --git a/packages/flutter_tools/test/general.shard/doctor.dart b/packages/flutter_tools/test/general.shard/doctor.dart
index 9f0913f..3839adf 100644
--- a/packages/flutter_tools/test/general.shard/doctor.dart
+++ b/packages/flutter_tools/test/general.shard/doctor.dart
@@ -20,9 +20,9 @@
 
   test('doctor validators includes desktop when features are enabled', () => testbed.run(() {
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        contains(isInstanceOf<LinuxDoctorValidator>()));
+        contains(isA<LinuxDoctorValidator>()));
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        contains(isInstanceOf<VisualStudioValidator>()));
+        contains(isA<VisualStudioValidator>()));
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(
       isLinuxEnabled: true,
@@ -32,9 +32,9 @@
 
   test('doctor validators does not include desktop when features are enabled', () => testbed.run(() {
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        isNot(contains(isInstanceOf<LinuxDoctorValidator>())));
+        isNot(contains(isA<LinuxDoctorValidator>())));
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        isNot(contains(isInstanceOf<VisualStudioValidator>())));
+        isNot(contains(isA<VisualStudioValidator>())));
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(
       isLinuxEnabled: false,
@@ -44,7 +44,7 @@
 
   test('doctor validators includes web when feature is enabled', () => testbed.run(() {
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        contains(isInstanceOf<WebValidator>()));
+        contains(isA<WebValidator>()));
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(
       isWebEnabled: true,
@@ -53,7 +53,7 @@
 
   test('doctor validators does not include web when feature is disabled', () => testbed.run(() {
     expect(DoctorValidatorsProvider.defaultInstance.validators,
-        isNot(contains(isInstanceOf<WebValidator>())));
+        isNot(contains(isA<WebValidator>())));
   }, overrides: <Type, Generator>{
     FeatureFlags: () => TestFeatureFlags(
       isWebEnabled: false,
diff --git a/packages/flutter_tools/test/general.shard/flutter_platform_test.dart b/packages/flutter_tools/test/general.shard/flutter_platform_test.dart
index fb9f9f1..13ef1af 100644
--- a/packages/flutter_tools/test/general.shard/flutter_platform_test.dart
+++ b/packages/flutter_tools/test/general.shard/flutter_platform_test.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'package:flutter_tools/src/build_info.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/test/flutter_platform.dart';
 import 'package:meta/meta.dart';
@@ -21,13 +20,13 @@
     testUsingContext('ensureConfiguration throws an error if an explicitObservatoryPort is specified and more than one test file', () async {
       final FlutterPlatform flutterPlatform = FlutterPlatform(buildMode: BuildMode.debug, shellPath: '/', explicitObservatoryPort: 1234);
       flutterPlatform.loadChannel('test1.dart', MockSuitePlatform());
-      expect(() => flutterPlatform.loadChannel('test2.dart', MockSuitePlatform()), throwsA(isA<ToolExit>()));
+      expect(() => flutterPlatform.loadChannel('test2.dart', MockSuitePlatform()), throwsToolExit());
     });
 
     testUsingContext('ensureConfiguration throws an error if a precompiled entrypoint is specified and more that one test file', () {
       final FlutterPlatform flutterPlatform = FlutterPlatform(buildMode: BuildMode.debug, shellPath: '/', precompiledDillPath: 'example.dill');
       flutterPlatform.loadChannel('test1.dart', MockSuitePlatform());
-      expect(() => flutterPlatform.loadChannel('test2.dart', MockSuitePlatform()), throwsA(isA<ToolExit>()));
+      expect(() => flutterPlatform.loadChannel('test2.dart', MockSuitePlatform()), throwsToolExit());
     });
 
     group('The FLUTTER_TEST environment variable is passed to the test process', () {
@@ -50,7 +49,7 @@
         await untilCalled(mockProcessManager.start(any, environment: anyNamed('environment')));
         final VerificationResult toVerify = verify(mockProcessManager.start(any, environment: captureAnyNamed('environment')));
         expect(toVerify.captured, hasLength(1));
-        expect(toVerify.captured.first, isInstanceOf<Map<String, String>>());
+        expect(toVerify.captured.first, isA<Map<String, String>>());
         return toVerify.captured.first as Map<String, String>;
       }
 
@@ -91,7 +90,7 @@
         shellPath: 'abc',
         enableObservatory: false,
         startPaused: true,
-      ), throwsA(isA<AssertionError>()));
+      ), throwsAssertionError);
 
       expect(() => installHook(
         buildMode: BuildMode.debug,
@@ -99,7 +98,7 @@
         enableObservatory: false,
         startPaused: false,
         observatoryPort: 123,
-      ), throwsA(isA<AssertionError>()));
+      ), throwsAssertionError);
 
       FlutterPlatform capturedPlatform;
       final Map<String, String> expectedPrecompiledDillFiles = <String, String>{'Key': 'Value'};
diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart
index 2810fcf..c0a2a0b 100644
--- a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart
+++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_device_test.dart
@@ -12,7 +12,6 @@
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
-import 'package:flutter_tools/src/base/process.dart';
 import 'package:flutter_tools/src/base/os.dart';
 import 'package:flutter_tools/src/base/time.dart';
 import 'package:flutter_tools/src/build_info.dart';
@@ -30,8 +29,8 @@
 import 'package:flutter_tools/src/vmservice.dart';
 import 'package:meta/meta.dart';
 import 'package:mockito/mockito.dart';
-import 'package:process/process.dart';
 import 'package:platform/platform.dart';
+import 'package:process/process.dart';
 
 import '../../src/common.dart';
 import '../../src/context.dart';
@@ -40,11 +39,10 @@
   group('fuchsia device', () {
     MemoryFileSystem memoryFileSystem;
     MockFile sshConfig;
-    MockProcessUtils mockProcessUtils;
+
     setUp(() {
       memoryFileSystem = MemoryFileSystem();
       sshConfig = MockFile();
-      mockProcessUtils = MockProcessUtils();
       when(sshConfig.absolute).thenReturn(sshConfig);
     });
 
@@ -118,27 +116,27 @@
     });
 
     testUsingContext('targetPlatform arm64 works', () async {
-      when(mockProcessUtils.run(any)).thenAnswer((Invocation _) {
-        return Future<RunResult>.value(RunResult(ProcessResult(1, 0, 'aarch64', ''), <String>['']));
+      when(globals.processManager.run(any)).thenAnswer((Invocation _) async {
+        return ProcessResult(1, 0, 'aarch64', '');
       });
       final FuchsiaDevice device = FuchsiaDevice('123');
       expect(await device.targetPlatform, TargetPlatform.fuchsia_arm64);
     }, overrides: <Type, Generator>{
       FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
       FuchsiaSdk: () => MockFuchsiaSdk(),
-      ProcessUtils: () => mockProcessUtils,
+      ProcessManager: () => MockProcessManager(),
     });
 
     testUsingContext('targetPlatform x64 works', () async {
-      when(mockProcessUtils.run(any)).thenAnswer((Invocation _) {
-        return Future<RunResult>.value(RunResult(ProcessResult(1, 0, 'x86_64', ''), <String>['']));
+      when(globals.processManager.run(any)).thenAnswer((Invocation _) async {
+        return ProcessResult(1, 0, 'x86_64', '');
       });
       final FuchsiaDevice device = FuchsiaDevice('123');
       expect(await device.targetPlatform, TargetPlatform.fuchsia_x64);
     }, overrides: <Type, Generator>{
       FuchsiaArtifacts: () => FuchsiaArtifacts(sshConfig: sshConfig),
       FuchsiaSdk: () => MockFuchsiaSdk(),
-      ProcessUtils: () => mockProcessUtils,
+      ProcessManager: () => MockProcessManager(),
     });
   });
 
@@ -326,8 +324,8 @@
     });
   });
 
-   group('screenshot', () {
-      MockProcessManager mockProcessManager;
+  group('screenshot', () {
+    MockProcessManager mockProcessManager;
 
     setUp(() {
       mockProcessManager = MockProcessManager();
@@ -550,6 +548,7 @@
     }, testOn: 'posix');
   });
 
+
   group(FuchsiaIsolateDiscoveryProtocol, () {
     MockPortForwarder portForwarder;
     MockVMService vmService;
@@ -960,8 +959,6 @@
 
 class MockProcessResult extends Mock implements ProcessResult {}
 
-class MockProcessUtils extends Mock implements ProcessUtils {}
-
 class MockFile extends Mock implements File {}
 
 class MockProcess extends Mock implements Process {}
diff --git a/packages/flutter_tools/test/general.shard/ios/devices_test.dart b/packages/flutter_tools/test/general.shard/ios/devices_test.dart
index fbf7ff0..74fb188 100644
--- a/packages/flutter_tools/test/general.shard/ios/devices_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/devices_test.dart
@@ -84,7 +84,7 @@
       testUsingContext('throws UnsupportedError exception if instantiated on ${platform.operatingSystem}', () {
         expect(
           () { IOSDevice('device-123'); },
-          throwsA(isInstanceOf<AssertionError>()),
+          throwsAssertionError,
         );
       }, overrides: <Type, Generator>{
         Platform: () => platform,
@@ -788,7 +788,7 @@
             .thenAnswer((Invocation invocation) => Future<String>.value(''));
         expect(
             () async { await IOSDevice.getAttachedDevices(); },
-            throwsA(isInstanceOf<UnsupportedError>()),
+            throwsA(isA<UnsupportedError>()),
         );
       }, overrides: <Type, Generator>{
         IMobileDevice: () => mockIMobileDevice,
diff --git a/packages/flutter_tools/test/general.shard/ios/mac_test.dart b/packages/flutter_tools/test/general.shard/ios/mac_test.dart
index ae846bf..0f2c9d7 100644
--- a/packages/flutter_tools/test/general.shard/ios/mac_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/mac_test.dart
@@ -108,7 +108,7 @@
         <String>[ideviceInfoPath, '-u', 'foo', '-k', 'bar'],
         environment: <String, String>{'DYLD_LIBRARY_PATH': libimobiledevicePath},
       )).thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(1, 255, 'No device found with udid foo, is it plugged in?', '')));
-      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isInstanceOf<IOSDeviceNotFoundError>()));
+      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isA<IOSDeviceNotFoundError>()));
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
       Cache: () => mockCache,
@@ -129,7 +129,7 @@
         );
         return Future<ProcessResult>.value(result);
       });
-      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isInstanceOf<IOSDeviceNotTrustedError>()));
+      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isA<IOSDeviceNotTrustedError>()));
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
       Cache: () => mockCache,
@@ -171,7 +171,7 @@
         );
         return Future<ProcessResult>.value(result);
       });
-      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isInstanceOf<IOSDeviceNotTrustedError>()));
+      expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isA<IOSDeviceNotTrustedError>()));
     }, overrides: <Type, Generator>{
       ProcessManager: () => mockProcessManager,
       Cache: () => mockCache,
diff --git a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart
index ecd7e47..504a7dd 100644
--- a/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart
+++ b/packages/flutter_tools/test/general.shard/macos/cocoapods_test.dart
@@ -345,7 +345,7 @@
         );
         fail('ToolExit expected');
       } catch(e) {
-        expect(e, isInstanceOf<ToolExit>());
+        expect(e, isA<ToolExit>());
         verifyNever(mockProcessManager.run(
         argThat(containsAllInOrder(<String>['pod', 'install'])),
           workingDirectory: anyNamed('workingDirectory'),
@@ -394,7 +394,7 @@
         );
         fail('ToolExit expected');
       } catch (e) {
-        expect(e, isInstanceOf<ToolExit>());
+        expect(e, isA<ToolExit>());
         expect(
           testLogger.errorText,
           contains("CocoaPods's specs repository is too out-of-date to satisfy dependencies"),
diff --git a/packages/flutter_tools/test/general.shard/project_test.dart b/packages/flutter_tools/test/general.shard/project_test.dart
index 1fcdfe6..4a404b6 100644
--- a/packages/flutter_tools/test/general.shard/project_test.dart
+++ b/packages/flutter_tools/test/general.shard/project_test.dart
@@ -6,7 +6,6 @@
 
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/cache.dart';
@@ -29,7 +28,7 @@
       testInMemory('fails on null directory', () async {
         expect(
           () => FlutterProject.fromDirectory(null),
-          throwsA(isInstanceOf<AssertionError>()),
+          throwsAssertionError,
         );
       });
 
@@ -41,7 +40,7 @@
 
         expect(
           () => FlutterProject.fromDirectory(directory),
-          throwsA(isInstanceOf<ToolExit>()),
+          throwsToolExit(),
         );
       });
 
@@ -53,7 +52,7 @@
 
         expect(
           () => FlutterProject.fromDirectory(directory),
-          throwsA(isInstanceOf<ToolExit>()),
+          throwsToolExit(),
         );
       });
 
@@ -65,7 +64,7 @@
 
         expect(
           () => FlutterProject.fromDirectory(directory),
-          throwsA(isInstanceOf<ToolExit>()),
+          throwsToolExit(),
         );
       });
 
@@ -110,7 +109,7 @@
         final FlutterProject project = await someProject();
         await expectLater(
           project.android.makeHostAppEditable(),
-          throwsA(isInstanceOf<AssertionError>()),
+          throwsAssertionError,
         );
       });
       testInMemory('exits on already editable module', () async {
diff --git a/packages/flutter_tools/test/general.shard/resident_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_runner_test.dart
index ef835f1..e576d2c 100644
--- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart
@@ -445,7 +445,7 @@
     when(mockDevice.supportsScreenshot).thenReturn(false);
 
     expect(() => residentRunner.screenshot(mockFlutterDevice),
-        throwsA(isInstanceOf<AssertionError>()));
+        throwsAssertionError);
   }));
 
   test('ResidentRunner does not toggle banner in non-debug mode', () => testbed.run(() async {
@@ -725,7 +725,7 @@
     expect(nextPlatform('iOS', TestFeatureFlags()), 'fuchsia');
     expect(nextPlatform('fuchsia', TestFeatureFlags()), 'android');
     expect(nextPlatform('fuchsia', TestFeatureFlags(isMacOSEnabled: true)), 'macOS');
-    expect(() => nextPlatform('unknown', TestFeatureFlags()), throwsA(isInstanceOf<AssertionError>()));
+    expect(() => nextPlatform('unknown', TestFeatureFlags()), throwsAssertionError);
   });
 }
 
diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
index 96698bf..d2b159c 100644
--- a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
@@ -82,6 +82,8 @@
           dartDefines: const <String>[],
           urlTunneller: null,
         ) as ResidentWebRunner;
+        globals.fs.currentDirectory.childFile('.packages')
+          ..writeAsStringSync('\n');
       },
       overrides: <Type, Generator>{
         WebFsFactory: () => ({
@@ -378,6 +380,8 @@
       pathToReload: anyNamed('pathToReload'),
       invalidatedFiles: anyNamed('invalidatedFiles'),
     )).thenAnswer((Invocation invocation) async {
+      // Generated entrypoint file in temp dir.
+      expect(invocation.namedArguments[#mainPath], contains('entrypoint.dart'));
       return UpdateFSReport(success: true)
         ..invalidatedModules = <String>['example'];
     });
@@ -926,7 +930,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -945,7 +949,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -964,7 +968,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -983,7 +987,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -1002,7 +1006,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -1021,7 +1025,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -1041,7 +1045,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<Exception>()));
+    ), throwsException);
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -1060,7 +1064,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<ToolExit>()));
+    ), throwsToolExit());
 
     unhandledErrorCompleter.complete();
     await expectation;
@@ -1082,7 +1086,7 @@
 
     final Future<void> expectation = expectLater(() => residentWebRunner.run(
       connectionInfoCompleter: connectionInfoCompleter,
-    ), throwsA(isInstanceOf<StateError>()));
+    ), throwsStateError);
 
     unhandledErrorCompleter.complete();
     await expectation;
diff --git a/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart b/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart
index 8cea9b0..e76b8b3 100644
--- a/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart
+++ b/packages/flutter_tools/test/general.shard/runner/flutter_command_runner_test.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'package:file/memory.dart';
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
@@ -92,7 +91,7 @@
         final MockFlutterVersion version = FlutterVersion.instance as MockFlutterVersion;
         when(version.ensureVersionFile()).thenThrow(const FileSystemException());
 
-        expect(() async => await runner.run(<String>['dummy']), throwsA(isA<ToolExit>()));
+        expect(() async => await runner.run(<String>['dummy']), throwsToolExit());
 
       }, overrides: <Type, Generator>{
         FileSystem: () => fs,
diff --git a/packages/flutter_tools/test/general.shard/terminal_handler_test.dart b/packages/flutter_tools/test/general.shard/terminal_handler_test.dart
index 9243191..57c1395 100644
--- a/packages/flutter_tools/test/general.shard/terminal_handler_test.dart
+++ b/packages/flutter_tools/test/general.shard/terminal_handler_test.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/device.dart';
 import 'package:flutter_tools/src/resident_runner.dart';
@@ -249,7 +248,7 @@
         .thenAnswer((Invocation invocation) async {
           return OperationResult(1, 'fail', fatal: true);
         });
-      expect(terminalHandler.processTerminalInput('r'), throwsA(isInstanceOf<ToolExit>()));
+      expect(terminalHandler.processTerminalInput('r'), throwsToolExit());
     });
 
     testUsingContext('r - hotReload unsupported', () async {
@@ -292,7 +291,7 @@
         .thenAnswer((Invocation invocation) async {
           return OperationResult(1, 'fail', fatal: true);
         });
-      expect(() => terminalHandler.processTerminalInput('R'), throwsA(isInstanceOf<ToolExit>()));
+      expect(() => terminalHandler.processTerminalInput('R'), throwsToolExit());
     });
 
     testUsingContext('R - hot restart unsupported', () async {
diff --git a/packages/flutter_tools/test/general.shard/testbed_test.dart b/packages/flutter_tools/test/general.shard/testbed_test.dart
index 6e10a6b..5735442 100644
--- a/packages/flutter_tools/test/general.shard/testbed_test.dart
+++ b/packages/flutter_tools/test/general.shard/testbed_test.dart
@@ -10,9 +10,11 @@
 import 'package:flutter_tools/src/base/context.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/error_handling_file_system.dart';
+import 'package:flutter_tools/src/base/process.dart';
 import 'package:flutter_tools/src/globals.dart' as globals;
 
 import '../src/common.dart';
+import '../src/context.dart';
 import '../src/testbed.dart';
 
 void main() {
@@ -76,7 +78,7 @@
 
       expect(testbed.run(() async {
         Timer.periodic(const Duration(seconds: 1), (Timer timer) { });
-      }), throwsA(isInstanceOf<StateError>()));
+      }), throwsStateError);
     });
 
     test('Doesnt throw a StateError if Timer is left cleaned up', () async {
@@ -87,6 +89,14 @@
         timer.cancel();
       });
     });
+
+    test('Throws if ProcessUtils is injected',() {
+      final Testbed testbed = Testbed(overrides: <Type, Generator>{
+        ProcessUtils: () => null,
+      });
+
+      expect(() => testbed.run(() {}), throwsA(isInstanceOf<StateError>()));
+    });
   });
 }
 
diff --git a/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart b/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart
index ea2eed1..86beb37 100644
--- a/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart
+++ b/packages/flutter_tools/test/general.shard/tester/flutter_tester_test.dart
@@ -61,7 +61,7 @@
       expect(devices, hasLength(1));
 
       final Device device = devices.single;
-      expect(device, isInstanceOf<FlutterTesterDevice>());
+      expect(device, isA<FlutterTesterDevice>());
       expect(device.id, 'flutter-tester');
     });
   });
diff --git a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
index 1c9878a..8f255ac 100644
--- a/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
+++ b/packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 import 'dart:io';
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/convert.dart';
@@ -80,7 +79,7 @@
   });
 
   test('Throws a tool exit if bind fails with a SocketException', () => testbed.run(() async {
-    expect(WebAssetServer.start('hello', 1234), throwsA(isInstanceOf<ToolExit>()));
+    expect(WebAssetServer.start('hello', 1234), throwsToolExit());
   }));
 
   test('Can catch exceptions through the onError callback', () => testbed.run(() async {
@@ -92,7 +91,7 @@
     when(request.uri).thenReturn(Uri.parse('http://foobar/foo.js'));
     requestController.add(request);
 
-    expect(closeCompleter.future, throwsA(isInstanceOf<StateError>()));
+    expect(closeCompleter.future, throwsStateError);
   }));
 
   test('Handles against malformed manifest', () => testbed.run(() async {
diff --git a/packages/flutter_tools/test/general.shard/web/devices_test.dart b/packages/flutter_tools/test/general.shard/web/devices_test.dart
index 47958a7..f3c0d51 100644
--- a/packages/flutter_tools/test/general.shard/web/devices_test.dart
+++ b/packages/flutter_tools/test/general.shard/web/devices_test.dart
@@ -41,8 +41,8 @@
     expect(chromeDevice.supportsFlutterExit, true);
     expect(chromeDevice.supportsScreenshot, false);
     expect(await chromeDevice.isLocalEmulator, false);
-    expect(chromeDevice.getLogReader(app: mockWebApplicationPackage), isInstanceOf<NoOpDeviceLogReader>());
-    expect(chromeDevice.getLogReader(), isInstanceOf<NoOpDeviceLogReader>());
+    expect(chromeDevice.getLogReader(app: mockWebApplicationPackage), isA<NoOpDeviceLogReader>());
+    expect(chromeDevice.getLogReader(), isA<NoOpDeviceLogReader>());
     expect(await chromeDevice.portForwarder.forward(1), 1);
   });
 
@@ -57,8 +57,8 @@
     expect(device.supportsFlutterExit, true);
     expect(device.supportsScreenshot, false);
     expect(await device.isLocalEmulator, false);
-    expect(device.getLogReader(app: mockWebApplicationPackage), isInstanceOf<NoOpDeviceLogReader>());
-    expect(device.getLogReader(), isInstanceOf<NoOpDeviceLogReader>());
+    expect(device.getLogReader(app: mockWebApplicationPackage), isA<NoOpDeviceLogReader>());
+    expect(device.getLogReader(), isA<NoOpDeviceLogReader>());
     expect(await device.portForwarder.forward(1), 1);
   });
 
@@ -67,7 +67,7 @@
 
     final WebDevices deviceDiscoverer = WebDevices();
     final List<Device> devices = await deviceDiscoverer.pollingGetDevices();
-    expect(devices, contains(isInstanceOf<ChromeDevice>()));
+    expect(devices, contains(isA<ChromeDevice>()));
   }, overrides: <Type, Generator>{
     ChromeLauncher: () => mockChromeLauncher,
   });
@@ -77,7 +77,7 @@
 
     final WebDevices deviceDiscoverer = WebDevices();
     final List<Device> devices = await deviceDiscoverer.pollingGetDevices();
-    expect(devices, isNot(contains(isInstanceOf<ChromeDevice>())));
+    expect(devices, isNot(contains(isA<ChromeDevice>())));
   }, overrides: <Type, Generator>{
     ChromeLauncher: () => mockChromeLauncher,
   });
@@ -87,7 +87,7 @@
 
     final WebDevices deviceDiscoverer = WebDevices();
     final List<Device> devices = await deviceDiscoverer.pollingGetDevices();
-    expect(devices, contains(isInstanceOf<WebServerDevice>()));
+    expect(devices, contains(isA<WebServerDevice>()));
   }, overrides: <Type, Generator>{
     ChromeLauncher: () => mockChromeLauncher,
   });
diff --git a/packages/flutter_tools/test/general.shard/web/web_fs_test.dart b/packages/flutter_tools/test/general.shard/web/web_fs_test.dart
index b4ab4f4..9645022 100644
--- a/packages/flutter_tools/test/general.shard/web/web_fs_test.dart
+++ b/packages/flutter_tools/test/general.shard/web/web_fs_test.dart
@@ -8,7 +8,6 @@
 import 'package:dwds/asset_handler.dart';
 import 'package:dwds/dwds.dart';
 import 'package:flutter_tools/src/base/os.dart';
-import 'package:flutter_tools/src/base/process.dart';
 import 'package:flutter_tools/src/build_info.dart';
 import 'package:flutter_tools/src/dart/pub.dart';
 import 'package:flutter_tools/src/project.dart';
@@ -18,8 +17,10 @@
 import 'package:http_multi_server/http_multi_server.dart';
 import 'package:meta/meta.dart';
 import 'package:mockito/mockito.dart';
+import 'package:process/process.dart';
 
 import '../../src/common.dart';
+import '../../src/mocks.dart';
 import '../../src/testbed.dart';
 
 void main() {
@@ -30,7 +31,7 @@
   MockHttpMultiServer mockHttpMultiServer;
   MockBuildDaemonClient mockBuildDaemonClient;
   MockOperatingSystemUtils mockOperatingSystemUtils;
-  MockProcessUtils mockProcessUtils;
+  MockProcessManager mockProcessManager;
   bool lastInitializePlatform;
   int lastPort;
 
@@ -43,7 +44,7 @@
     mockBuildDaemonClient = MockBuildDaemonClient();
     mockOperatingSystemUtils = MockOperatingSystemUtils();
     mockDwds = MockDwds();
-    mockProcessUtils = MockProcessUtils();
+    mockProcessManager = MockProcessManager();
     when(mockBuildDaemonCreator.startBuildDaemon(any, release: anyNamed('release'), initializePlatform: anyNamed('initializePlatform')))
       .thenAnswer((Invocation invocation) async {
         lastInitializePlatform = invocation.namedArguments[#initializePlatform] as bool;
@@ -52,15 +53,14 @@
     when(mockOperatingSystemUtils.findFreePort()).thenAnswer((Invocation _) async {
       return 1234;
     });
-    when(mockProcessUtils.stream(
+    when(mockProcessManager.start(
       any,
       workingDirectory: anyNamed('workingDirectory'),
-      mapFunction: anyNamed('mapFunction'),
       environment: anyNamed('environment'),
     )).thenAnswer((Invocation invocation) async {
       final String workingDirectory = invocation.namedArguments[#workingDirectory] as String;
       globals.fs.file(globals.fs.path.join(workingDirectory, '.packages')).createSync(recursive: true);
-      return 0;
+      return FakeProcess();
     });
     when(mockBuildDaemonClient.buildResults).thenAnswer((Invocation _) {
       return Stream<BuildResults>.fromFuture(Future<BuildResults>.value(
@@ -91,7 +91,7 @@
         OperatingSystemUtils: () => mockOperatingSystemUtils,
         BuildDaemonCreator: () => mockBuildDaemonCreator,
         ChromeLauncher: () => mockChromeLauncher,
-        ProcessUtils: () => mockProcessUtils,
+        ProcessManager: () => mockProcessManager,
         HttpMultiServerFactory: () => (dynamic address, int port) async {
           lastPort = port;
           return mockHttpMultiServer;
@@ -215,7 +215,7 @@
       port: '1234',
       urlTunneller: null,
       dartDefines: const <String>[],
-    ), throwsA(isInstanceOf<Exception>()));
+    ), throwsException);
   }));
 }
 
@@ -225,5 +225,5 @@
 class MockHttpMultiServer extends Mock implements HttpMultiServer {}
 class MockChromeLauncher extends Mock implements ChromeLauncher {}
 class MockOperatingSystemUtils extends Mock implements OperatingSystemUtils {}
-class MockProcessUtils extends Mock implements ProcessUtils {}
 class MockPub extends Mock implements Pub {}
+class MockProcessManager extends Mock implements ProcessManager {}
diff --git a/packages/flutter_tools/test/src/common.dart b/packages/flutter_tools/test/src/common.dart
index 419674a..fb446bc 100644
--- a/packages/flutter_tools/test/src/common.dart
+++ b/packages/flutter_tools/test/src/common.dart
@@ -22,7 +22,7 @@
 
 /// A matcher that compares the type of the actual value to the type argument T.
 // TODO(ianh): Remove this once https://github.com/dart-lang/matcher/issues/98 is fixed
-Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();
+test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
 
 void tryToDelete(Directory directory) {
   // This should not be necessary, but it turns out that
@@ -91,6 +91,9 @@
   globals.fs.file(path).setLastModifiedSync(modificationTime);
 }
 
+/// Matcher for functions that throw [AssertionError].
+final Matcher throwsAssertionError = throwsA(isA<AssertionError>());
+
 /// Matcher for functions that throw [ToolExit].
 Matcher throwsToolExit({ int exitCode, Pattern message }) {
   Matcher matcher = isToolExit;
@@ -104,7 +107,7 @@
 }
 
 /// Matcher for [ToolExit]s.
-final Matcher isToolExit = isInstanceOf<ToolExit>();
+final test_package.TypeMatcher<ToolExit> isToolExit = isA<ToolExit>();
 
 /// Matcher for functions that throw [ProcessExit].
 Matcher throwsProcessExit([ dynamic exitCode ]) {
@@ -114,7 +117,7 @@
 }
 
 /// Matcher for [ProcessExit]s.
-final Matcher isProcessExit = isInstanceOf<ProcessExit>();
+final test_package.TypeMatcher<ProcessExit> isProcessExit = isA<ProcessExit>();
 
 /// Creates a flutter project in the [temp] directory using the
 /// [arguments] list if specified, or `--no-pub` if not.
diff --git a/packages/flutter_tools/test/src/context.dart b/packages/flutter_tools/test/src/context.dart
index 80d2d30..ad67944 100644
--- a/packages/flutter_tools/test/src/context.dart
+++ b/packages/flutter_tools/test/src/context.dart
@@ -12,6 +12,7 @@
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/base/os.dart';
+import 'package:flutter_tools/src/base/process.dart';
 import 'package:flutter_tools/src/base/signals.dart';
 import 'package:flutter_tools/src/base/terminal.dart';
 import 'package:flutter_tools/src/base/time.dart';
@@ -63,6 +64,9 @@
       'that you are dealing with in your test.'
     );
   }
+  if (overrides.containsKey(ProcessUtils)) {
+    throw StateError('Do not inject ProcessUtils for testing, use ProcessManager instead.');
+  }
 
   // Ensure we don't rely on the default [Config] constructor which will
   // leak a sticky $HOME/.flutter_settings behind!
diff --git a/packages/flutter_tools/test/src/testbed.dart b/packages/flutter_tools/test/src/testbed.dart
index 5934d28..4bd9694 100644
--- a/packages/flutter_tools/test/src/testbed.dart
+++ b/packages/flutter_tools/test/src/testbed.dart
@@ -12,6 +12,7 @@
 import 'package:flutter_tools/src/base/io.dart';
 import 'package:flutter_tools/src/base/logger.dart';
 import 'package:flutter_tools/src/base/os.dart';
+import 'package:flutter_tools/src/base/process.dart';
 
 import 'package:flutter_tools/src/base/signals.dart';
 import 'package:flutter_tools/src/base/terminal.dart';
@@ -113,6 +114,9 @@
       // Add the test-specific overrides
       ...?overrides,
     };
+    if (testOverrides.containsKey(ProcessUtils)) {
+      throw StateError('Do not inject ProcessUtils for testing, use ProcessManager instead.');
+    }
     // Cache the original flutter root to restore after the test case.
     final String originalFlutterRoot = Cache.flutterRoot;
     // Track pending timers to verify that they were correctly cleaned up.
diff --git a/packages/flutter_tools/test/template_test.dart b/packages/flutter_tools/test/template_test.dart
index 2aedd4e..936cf57 100644
--- a/packages/flutter_tools/test/template_test.dart
+++ b/packages/flutter_tools/test/template_test.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'package:flutter_tools/src/base/common.dart';
 import 'package:flutter_tools/src/base/file_system.dart';
 import 'package:flutter_tools/src/template.dart';
 import 'package:flutter_tools/src/globals.dart' as globals;
@@ -24,7 +23,7 @@
     when(mockDirectory.createSync(recursive: true)).thenThrow(const FileSystemException());
 
     expect(() => template.render(mockDirectory, <String, Object>{}),
-        throwsA(isInstanceOf<ToolExit>()));
+        throwsToolExit());
   }));
 }
 
diff --git a/packages/fuchsia_remote_debug_protocol/test/common.dart b/packages/fuchsia_remote_debug_protocol/test/common.dart
index bc195e5..ea979f0 100644
--- a/packages/fuchsia_remote_debug_protocol/test/common.dart
+++ b/packages/fuchsia_remote_debug_protocol/test/common.dart
@@ -11,4 +11,4 @@
 export 'package:test_api/test_api.dart' hide TypeMatcher, isInstanceOf; // ignore: deprecated_member_use
 
 /// A matcher that compares the type of the actual value to the type argument T.
-Matcher isInstanceOf<T>() => test_package.TypeMatcher<T>();
+test_package.TypeMatcher<T> isInstanceOf<T>() => isA<T>();
diff --git a/packages/fuchsia_remote_debug_protocol/test/fuchsia_remote_connection_test.dart b/packages/fuchsia_remote_debug_protocol/test/fuchsia_remote_connection_test.dart
index 94d9849..833d79b 100644
--- a/packages/fuchsia_remote_debug_protocol/test/fuchsia_remote_connection_test.dart
+++ b/packages/fuchsia_remote_debug_protocol/test/fuchsia_remote_connection_test.dart
@@ -161,7 +161,7 @@
 
       // Should fail as no env variable has been passed.
       expect(failingFunction,
-          throwsA(isInstanceOf<FuchsiaRemoteConnectionError>()));
+          throwsA(isA<FuchsiaRemoteConnectionError>()));
     });
   });
 }
diff --git a/packages/fuchsia_remote_debug_protocol/test/src/dart/dart_vm_test.dart b/packages/fuchsia_remote_debug_protocol/test/src/dart/dart_vm_test.dart
index 832ed69..c3ae83a 100644
--- a/packages/fuchsia_remote_debug_protocol/test/src/dart/dart_vm_test.dart
+++ b/packages/fuchsia_remote_debug_protocol/test/src/dart/dart_vm_test.dart
@@ -217,7 +217,7 @@
       }
 
       // Both views should be invalid as they were missing required fields.
-      expect(failingFunction, throwsA(isInstanceOf<RpcFormatError>()));
+      expect(failingFunction, throwsA(isA<RpcFormatError>()));
     });
 
     test('get isolates by pattern', () async {
@@ -311,7 +311,7 @@
       }
 
       // Both views should be invalid as they were missing required fields.
-      expect(failingFunction, throwsA(isInstanceOf<RpcFormatError>()));
+      expect(failingFunction, throwsA(isA<RpcFormatError>()));
     });
   });
 
@@ -346,7 +346,7 @@
         await vm.invokeRpc('somesillyfunction', timeout: timeoutTime);
       }
 
-      expect(failingFunction, throwsA(isInstanceOf<TimeoutException>()));
+      expect(failingFunction, throwsA(isA<TimeoutException>()));
     });
   });
 }
diff --git a/packages/fuchsia_remote_debug_protocol/test/src/runners/ssh_command_runner_test.dart b/packages/fuchsia_remote_debug_protocol/test/src/runners/ssh_command_runner_test.dart
index 6e5567c..e2a8670 100644
--- a/packages/fuchsia_remote_debug_protocol/test/src/runners/ssh_command_runner_test.dart
+++ b/packages/fuchsia_remote_debug_protocol/test/src/runners/ssh_command_runner_test.dart
@@ -98,7 +98,7 @@
         await runner.run('oihaw');
       }
 
-      expect(failingFunction, throwsA(isInstanceOf<SshCommandError>()));
+      expect(failingFunction, throwsA(isA<SshCommandError>()));
     });
 
     test('verify correct args with config', () async {