diff --git a/script/tool/lib/src/update_dependency_command.dart b/script/tool/lib/src/update_dependency_command.dart
index 6fa1dae564..30060bc228 100644
--- a/script/tool/lib/src/update_dependency_command.dart
+++ b/script/tool/lib/src/update_dependency_command.dart
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:io' as io;
+
 import 'package:file/file.dart';
 import 'package:http/http.dart' as http;
 import 'package:pub_semver/pub_semver.dart';
@@ -10,6 +12,7 @@ import 'package:yaml_edit/yaml_edit.dart';
 
 import 'common/core.dart';
 import 'common/package_looping_command.dart';
+import 'common/process_runner.dart';
 import 'common/pub_version_finder.dart';
 import 'common/repository_package.dart';
 
@@ -26,10 +29,11 @@ class UpdateDependencyCommand extends PackageLoopingCommand {
   /// Creates an instance of the version check command.
   UpdateDependencyCommand(
     Directory packagesDir, {
+    ProcessRunner processRunner = const ProcessRunner(),
     http.Client? httpClient,
   })  : _pubVersionFinder =
             PubVersionFinder(httpClient: httpClient ?? http.Client()),
-        super(packagesDir) {
+        super(packagesDir, processRunner: processRunner) {
     argParser.addOption(
       _pubPackageFlag,
       help: 'A pub package to update.',
@@ -129,6 +133,7 @@ ${response.httpResponse.body}
       return PackageResult.skip('$dependency in not a hosted dependency');
     }
 
+    // Determine the target version constraint.
     final String sectionKey = dependencyInfo.type == _PubDependencyType.dev
         ? 'dev_dependencies'
         : 'dependencies';
@@ -147,6 +152,7 @@ ${response.httpResponse.body}
       versionString = '^$minVersion';
     }
 
+    // Update pubspec.yaml with the new version.
     print('${indentation}Updating to "$versionString"');
     if (versionString == dependencyInfo.constraintString) {
       return PackageResult.skip('Already depends on $versionString');
@@ -159,8 +165,14 @@ ${response.httpResponse.body}
     );
     package.pubspecFile.writeAsStringSync(editablePubspec.toString());
 
-    // TODO(stuartmorgan): Add additionally handling of known packages that
-    // do file generation (mockito, pigeon, etc.).
+    // Do any dependency-specific extra processing.
+    if (dependency == 'pigeon') {
+      if (!await _regeneratePigeonFiles(package)) {
+        return PackageResult.fail(<String>['Failed to update pigeon files']);
+      }
+    }
+    // TODO(stuartmorgan): Add additional handling of known packages that
+    // do file generation (mockito, etc.).
 
     return PackageResult.success();
   }
@@ -193,6 +205,59 @@ ${response.httpResponse.body}
     }
     return _PubDependencyInfo(type, pinned: false, hosted: false);
   }
+
+  /// Returns all of the files in [package] that are, according to repository
+  /// convention, Pigeon input files.
+  Iterable<File> _getPigeonInputFiles(RepositoryPackage package) {
+    // Repo convention is that the Pigeon input files are the Dart files in a
+    // top-level "pigeons" directory.
+    final Directory pigeonsDir = package.directory.childDirectory('pigeons');
+    if (!pigeonsDir.existsSync()) {
+      return <File>[];
+    }
+    return pigeonsDir
+        .listSync()
+        .whereType<File>()
+        .where((File file) => file.basename.endsWith('.dart'));
+  }
+
+  /// Re-runs Pigeon generation for [package].
+  ///
+  /// This assumes that all output configuration is set in the input files, so
+  /// no additional arguments are needed. If that assumption stops holding true,
+  /// the tooling will need a way for packages to control the generation (e.g.,
+  /// with a script file with a known name in the pigeons/ directory.)
+  Future<bool> _regeneratePigeonFiles(RepositoryPackage package) async {
+    final Iterable<File> inputs = _getPigeonInputFiles(package);
+    if (inputs.isEmpty) {
+      logWarning('No pigeon input files found.');
+      return true;
+    }
+
+    print('${indentation}Running pub get...');
+    final io.ProcessResult getResult = await processRunner
+        .run('dart', <String>['pub', 'get'], workingDir: package.directory);
+    if (getResult.exitCode != 0) {
+      printError('dart pub get failed (${getResult.exitCode}):\n'
+          '${getResult.stdout}\n${getResult.stderr}\n');
+      return false;
+    }
+
+    print('${indentation}Updating Pigeon files...');
+    for (final File input in inputs) {
+      final String relativePath =
+          getRelativePosixPath(input, from: package.directory);
+      final io.ProcessResult pigeonResult = await processRunner.run(
+          'dart', <String>['run', 'pigeon', '--input', relativePath],
+          workingDir: package.directory);
+      if (pigeonResult.exitCode != 0) {
+        printError('dart run pigeon failed (${pigeonResult.exitCode}):\n'
+            '${pigeonResult.stdout}\n${pigeonResult.stderr}\n');
+        return false;
+      }
+    }
+    return true;
+  }
 }
 
 class _PubDependencyInfo {
diff --git a/script/tool/test/analyze_command_test.dart b/script/tool/test/analyze_command_test.dart
index e6b9109608..37f3332d83 100644
--- a/script/tool/test/analyze_command_test.dart
+++ b/script/tool/test/analyze_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -320,8 +318,8 @@ void main() {
   test('fails if "pub get" fails', () async {
     createFakePlugin('foo', packagesDir);
 
-    processRunner.mockProcessesForExecutable['flutter'] = <io.Process>[
-      MockProcess(exitCode: 1) // flutter pub get
+    processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'get'])
     ];
 
     Error? commandError;
@@ -342,8 +340,8 @@ void main() {
   test('fails if "pub downgrade" fails', () async {
     createFakePlugin('foo', packagesDir);
 
-    processRunner.mockProcessesForExecutable['flutter'] = <io.Process>[
-      MockProcess(exitCode: 1) // flutter pub downgrade
+    processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'downgrade'])
     ];
 
     Error? commandError;
@@ -364,8 +362,8 @@ void main() {
   test('fails if "analyze" fails', () async {
     createFakePlugin('foo', packagesDir);
 
-    processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-      MockProcess(exitCode: 1) // dart analyze
+    processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['analyze'])
     ];
 
     Error? commandError;
diff --git a/script/tool/test/build_examples_command_test.dart b/script/tool/test/build_examples_command_test.dart
index a819e7a126..04d4c824c7 100644
--- a/script/tool/test/build_examples_command_test.dart
+++ b/script/tool/test/build_examples_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -62,8 +60,8 @@ void main() {
 
       processRunner
               .mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
-          <io.Process>[
-        MockProcess(exitCode: 1) // flutter pub get
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['build'])
       ];
 
       Error? commandError;
@@ -91,8 +89,8 @@ void main() {
 
       processRunner
               .mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
-          <io.Process>[
-        MockProcess(exitCode: 1) // flutter pub get
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'get'])
       ];
 
       Error? commandError;
diff --git a/script/tool/test/common/gradle_test.dart b/script/tool/test/common/gradle_test.dart
index 8df4a65b93..4f06900eb8 100644
--- a/script/tool/test/common/gradle_test.dart
+++ b/script/tool/test/common/gradle_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
 import 'package:flutter_plugin_tools/src/common/gradle.dart';
@@ -176,8 +174,8 @@ void main() {
       );
 
       processRunner.mockProcessesForExecutable[project.gradleWrapper.path] =
-          <io.Process>[
-        MockProcess(exitCode: 1),
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1)),
       ];
 
       final int exitCode = await project.runCommand('foo');
diff --git a/script/tool/test/common/package_command_test.dart b/script/tool/test/common/package_command_test.dart
index 3620f8fd63..24100bafed 100644
--- a/script/tool/test/common/package_command_test.dart
+++ b/script/tool/test/common/package_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io';
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -211,10 +209,10 @@ void main() {
     test(
         'explicitly specifying the plugin (group) name of a federated plugin '
         'should include all plugins in the group', () async {
-      processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-        MockProcess(stdout: '''
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin1/plugin1/plugin1.dart
-'''),
+''')),
       ];
       final Directory pluginGroup = packagesDir.childDirectory('plugin1');
       final RepositoryPackage appFacingPackage =
@@ -239,10 +237,10 @@ packages/plugin1/plugin1/plugin1.dart
     test(
         'specifying the app-facing package of a federated plugin using its '
         'fully qualified name should include only that package', () async {
-      processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-        MockProcess(stdout: '''
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin1/plugin1/plugin1.dart
-'''),
+''')),
       ];
       final Directory pluginGroup = packagesDir.childDirectory('plugin1');
       final RepositoryPackage appFacingPackage =
@@ -259,10 +257,10 @@ packages/plugin1/plugin1/plugin1.dart
     test(
         'specifying a package of a federated plugin by its name should '
         'include only that package', () async {
-      processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-        MockProcess(stdout: '''
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin1/plugin1/plugin1.dart
-'''),
+''')),
       ];
       final Directory pluginGroup = packagesDir.childDirectory('plugin1');
 
@@ -383,8 +381,9 @@ packages/plugin1/plugin1/plugin1.dart
       test(
           'all plugins should be tested if there are no plugin related changes.',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: 'AUTHORS'),
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'AUTHORS')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir);
@@ -398,11 +397,12 @@ packages/plugin1/plugin1/plugin1.dart
       });
 
       test('all plugins should be tested if .cirrus.yml changes.', () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 .cirrus.yml
 packages/plugin1/CHANGELOG
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir);
@@ -423,11 +423,12 @@ packages/plugin1/CHANGELOG
       });
 
       test('all plugins should be tested if .ci.yaml changes', () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 .ci.yaml
 packages/plugin1/CHANGELOG
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir);
@@ -448,11 +449,12 @@ packages/plugin1/CHANGELOG
 
       test('all plugins should be tested if anything in .ci/ changes',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 .ci/Dockerfile
 packages/plugin1/CHANGELOG
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir);
@@ -473,11 +475,12 @@ packages/plugin1/CHANGELOG
 
       test('all plugins should be tested if anything in script/ changes.',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 script/tool_runner.sh
 packages/plugin1/CHANGELOG
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir);
@@ -498,11 +501,12 @@ packages/plugin1/CHANGELOG
 
       test('all plugins should be tested if the root analysis options change.',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 analysis_options.yaml
 packages/plugin1/CHANGELOG
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir);
@@ -523,11 +527,12 @@ packages/plugin1/CHANGELOG
 
       test('all plugins should be tested if formatting options change.',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 .clang-format
 packages/plugin1/CHANGELOG
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir);
@@ -547,8 +552,9 @@ packages/plugin1/CHANGELOG
       });
 
       test('Only changed plugin should be tested.', () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: 'packages/plugin1/plugin1.dart'),
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'packages/plugin1/plugin1.dart')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir);
@@ -568,11 +574,12 @@ packages/plugin1/CHANGELOG
 
       test('multiple files in one plugin should also test the plugin',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin1/plugin1.dart
 packages/plugin1/ios/plugin1.m
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir);
@@ -585,11 +592,12 @@ packages/plugin1/ios/plugin1.m
 
       test('multiple plugins changed should test all the changed plugins',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin1/plugin1.dart
 packages/plugin2/ios/plugin2.m
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir);
@@ -606,12 +614,13 @@ packages/plugin2/ios/plugin2.m
       test(
           'multiple plugins inside the same plugin group changed should output the plugin group name',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin1/plugin1/plugin1.dart
 packages/plugin1/plugin1_platform_interface/plugin1_platform_interface.dart
 packages/plugin1/plugin1_web/plugin1_web.dart
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir.childDirectory('plugin1'));
@@ -626,10 +635,11 @@ packages/plugin1/plugin1_web/plugin1_web.dart
       test(
           'changing one plugin in a federated group should only include that plugin',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin1/plugin1/plugin1.dart
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir.childDirectory('plugin1'));
@@ -643,12 +653,13 @@ packages/plugin1/plugin1/plugin1.dart
       });
 
       test('--exclude flag works with --run-on-changed-packages', () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin1/plugin1.dart
 packages/plugin2/ios/plugin2.m
 packages/plugin3/plugin3.dart
-'''),
+''')),
         ];
         final RepositoryPackage plugin1 =
             createFakePlugin('plugin1', packagesDir.childDirectory('plugin1'));
@@ -677,8 +688,9 @@ packages/plugin3/plugin3.dart
       test(
           'no packages should be tested if there are no plugin related changes.',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: 'AUTHORS'),
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'AUTHORS')),
         ];
         createFakePackage('a_package', packagesDir);
         await runCapturingPrint(
@@ -689,15 +701,16 @@ packages/plugin3/plugin3.dart
 
       test('no packages should be tested even if special repo files change.',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 .cirrus.yml
 .ci.yaml
 .ci/Dockerfile
 .clang-format
 analysis_options.yaml
 script/tool_runner.sh
-'''),
+''')),
         ];
         createFakePackage('a_package', packagesDir);
         await runCapturingPrint(
@@ -707,8 +720,10 @@ script/tool_runner.sh
       });
 
       test('Only changed packages should be tested.', () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: 'packages/a_package/lib/a_package.dart'),
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(
+              MockProcess(stdout: 'packages/a_package/lib/a_package.dart')),
         ];
         final RepositoryPackage packageA =
             createFakePackage('a_package', packagesDir);
@@ -728,11 +743,12 @@ script/tool_runner.sh
 
       test('multiple packages changed should test all the changed packages',
           () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/a_package/lib/a_package.dart
 packages/b_package/lib/src/foo.dart
-'''),
+''')),
         ];
         final RepositoryPackage packageA =
             createFakePackage('a_package', packagesDir);
@@ -747,11 +763,12 @@ packages/b_package/lib/src/foo.dart
       });
 
       test('honors --exclude flag', () async {
-        processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/a_package/lib/a_package.dart
 packages/b_package/lib/src/foo.dart
-'''),
+''')),
         ];
         final RepositoryPackage packageA =
             createFakePackage('a_package', packagesDir);
@@ -771,15 +788,18 @@ packages/b_package/lib/src/foo.dart
   group('--packages-for-branch', () {
     test('only tests changed packages relative to the merge base on a branch',
         () async {
-      processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-        MockProcess(stdout: 'packages/plugin1/plugin1.dart'),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'packages/plugin1/plugin1.dart')),
       ];
-      processRunner.mockProcessesForExecutable['git-rev-parse'] = <Process>[
-        MockProcess(stdout: 'a-branch'),
+      processRunner.mockProcessesForExecutable['git-rev-parse'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'a-branch')),
       ];
-      processRunner.mockProcessesForExecutable['git-merge-base'] = <Process>[
-        MockProcess(exitCode: 1), // --is-ancestor check
-        MockProcess(stdout: 'abc123'), // finding merge base
+      processRunner.mockProcessesForExecutable['git-merge-base'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['--is-ancestor']),
+        FakeProcessInfo(MockProcess(stdout: 'abc123'),
+            <String>['--fork-point']), // finding merge base
       ];
       final RepositoryPackage plugin1 =
           createFakePlugin('plugin1', packagesDir);
@@ -807,11 +827,12 @@ packages/b_package/lib/src/foo.dart
 
     test('only tests changed packages relative to the previous commit on main',
         () async {
-      processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-        MockProcess(stdout: 'packages/plugin1/plugin1.dart'),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'packages/plugin1/plugin1.dart')),
       ];
-      processRunner.mockProcessesForExecutable['git-rev-parse'] = <Process>[
-        MockProcess(stdout: 'main'),
+      processRunner.mockProcessesForExecutable['git-rev-parse'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'main')),
       ];
       final RepositoryPackage plugin1 =
           createFakePlugin('plugin1', packagesDir);
@@ -842,11 +863,12 @@ packages/b_package/lib/src/foo.dart
     test(
         'only tests changed packages relative to the previous commit if '
         'running on a specific hash from main', () async {
-      processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-        MockProcess(stdout: 'packages/plugin1/plugin1.dart'),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'packages/plugin1/plugin1.dart')),
       ];
-      processRunner.mockProcessesForExecutable['git-rev-parse'] = <Process>[
-        MockProcess(stdout: 'HEAD'),
+      processRunner.mockProcessesForExecutable['git-rev-parse'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'HEAD')),
       ];
       final RepositoryPackage plugin1 =
           createFakePlugin('plugin1', packagesDir);
@@ -878,15 +900,25 @@ packages/b_package/lib/src/foo.dart
     test(
         'only tests changed packages relative to the previous commit if '
         'running on a specific hash from origin/main', () async {
-      processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-        MockProcess(stdout: 'packages/plugin1/plugin1.dart'),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'packages/plugin1/plugin1.dart')),
       ];
-      processRunner.mockProcessesForExecutable['git-rev-parse'] = <Process>[
-        MockProcess(stdout: 'HEAD'),
+      processRunner.mockProcessesForExecutable['git-rev-parse'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'HEAD')),
       ];
-      processRunner.mockProcessesForExecutable['git-merge-base'] = <Process>[
-        MockProcess(exitCode: 128), // Fail with a non-1 exit code for 'main'
-        MockProcess(), // Succeed for the variant.
+      processRunner.mockProcessesForExecutable['git-merge-base'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 128), <String>[
+          '--is-ancestor',
+          'HEAD',
+          'main'
+        ]), // Fail with a non-1 exit code for 'main'
+        FakeProcessInfo(MockProcess(), <String>[
+          '--is-ancestor',
+          'HEAD',
+          'origin/main'
+        ]), // Succeed for the variant.
       ];
       final RepositoryPackage plugin1 =
           createFakePlugin('plugin1', packagesDir);
@@ -918,11 +950,12 @@ packages/b_package/lib/src/foo.dart
     test(
         'only tests changed packages relative to the previous commit on master',
         () async {
-      processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-        MockProcess(stdout: 'packages/plugin1/plugin1.dart'),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'packages/plugin1/plugin1.dart')),
       ];
-      processRunner.mockProcessesForExecutable['git-rev-parse'] = <Process>[
-        MockProcess(stdout: 'master'),
+      processRunner.mockProcessesForExecutable['git-rev-parse'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'master')),
       ];
       final RepositoryPackage plugin1 =
           createFakePlugin('plugin1', packagesDir);
@@ -951,11 +984,12 @@ packages/b_package/lib/src/foo.dart
     });
 
     test('throws if getting the branch fails', () async {
-      processRunner.mockProcessesForExecutable['git-diff'] = <Process>[
-        MockProcess(stdout: 'packages/plugin1/plugin1.dart'),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'packages/plugin1/plugin1.dart')),
       ];
-      processRunner.mockProcessesForExecutable['git-rev-parse'] = <Process>[
-        MockProcess(exitCode: 1),
+      processRunner.mockProcessesForExecutable['git-rev-parse'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1)),
       ];
 
       Error? commandError;
diff --git a/script/tool/test/common/xcode_test.dart b/script/tool/test/common/xcode_test.dart
index 259d8ea36c..b401287e15 100644
--- a/script/tool/test/common/xcode_test.dart
+++ b/script/tool/test/common/xcode_test.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'dart:convert';
-import 'dart:io' as io;
 
 import 'package:file/file.dart';
 import 'package:file/local.dart';
@@ -94,8 +93,9 @@ void main() {
         }
       };
 
-      processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-        MockProcess(stdout: jsonEncode(devices)),
+      processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: jsonEncode(devices)),
+            <String>['simctl', 'list']),
       ];
 
       expect(await xcode.findBestAvailableIphoneSimulator(), expectedDeviceId);
@@ -138,16 +138,17 @@ void main() {
         }
       };
 
-      processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-        MockProcess(stdout: jsonEncode(devices)),
+      processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: jsonEncode(devices)),
+            <String>['simctl', 'list']),
       ];
 
       expect(await xcode.findBestAvailableIphoneSimulator(), null);
     });
 
     test('returns null if simctl fails', () async {
-      processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-        MockProcess(exitCode: 1),
+      processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['simctl', 'list']),
       ];
 
       expect(await xcode.findBestAvailableIphoneSimulator(), null);
@@ -217,8 +218,8 @@ void main() {
     });
 
     test('returns error codes', () async {
-      processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-        MockProcess(exitCode: 1),
+      processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['xcodebuild']),
       ];
       final Directory directory = const LocalFileSystem().currentDirectory;
 
@@ -267,8 +268,8 @@ void main() {
     ]
   }
 }''';
-      processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-        MockProcess(stdout: stdout),
+      processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: stdout), <String>['xcodebuild']),
       ];
 
       final Directory project =
@@ -308,8 +309,8 @@ void main() {
     ]
   }
 }''';
-      processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-        MockProcess(stdout: stdout),
+      processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: stdout), <String>['xcodebuild']),
       ];
 
       final Directory project =
@@ -332,8 +333,8 @@ void main() {
     });
 
     test('returns null for unexpected output', () async {
-      processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-        MockProcess(stdout: '{}'),
+      processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: '{}'), <String>['xcodebuild']),
       ];
 
       final Directory project =
@@ -356,8 +357,8 @@ void main() {
     });
 
     test('returns null for invalid output', () async {
-      processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-        MockProcess(stdout: ':)'),
+      processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: ':)'), <String>['xcodebuild']),
       ];
 
       final Directory project =
@@ -380,8 +381,9 @@ void main() {
     });
 
     test('returns null for failure', () async {
-      processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-        MockProcess(exitCode: 1), // xcodebuild -list
+      processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+        FakeProcessInfo(
+            MockProcess(exitCode: 1), <String>['xcodebuild', '-list'])
       ];
 
       final Directory project =
diff --git a/script/tool/test/create_all_packages_app_command_test.dart b/script/tool/test/create_all_packages_app_command_test.dart
index 54551cbc37..c545c1f3f5 100644
--- a/script/tool/test/create_all_packages_app_command_test.dart
+++ b/script/tool/test/create_all_packages_app_command_test.dart
@@ -161,8 +161,8 @@ void main() {
       createFakePlugin('plugina', packagesDir);
 
       processRunner.mockProcessesForExecutable[
-          getFlutterCommand(const LocalPlatform())] = <io.Process>[
-        MockProcess(exitCode: 1)
+          getFlutterCommand(const LocalPlatform())] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'get'])
       ];
       Error? commandError;
       final List<String> output = await runCapturingPrint(
diff --git a/script/tool/test/custom_test_command_test.dart b/script/tool/test/custom_test_command_test.dart
index 8b0c021b12..1b6f0a470e 100644
--- a/script/tool/test/custom_test_command_test.dart
+++ b/script/tool/test/custom_test_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -145,9 +143,9 @@ void main() {
         'run_tests.sh',
       ]);
 
-      processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-        MockProcess(), // pub get
-        MockProcess(exitCode: 1), // test script
+      processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(), <String>['pub', 'get']),
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['test']),
       ];
 
       Error? commandError;
@@ -171,8 +169,8 @@ void main() {
         'run_tests.sh',
       ]);
 
-      processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-        MockProcess(exitCode: 1),
+      processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'get']),
       ];
 
       Error? commandError;
@@ -199,8 +197,8 @@ void main() {
       ]);
 
       processRunner.mockProcessesForExecutable[
-          package.directory.childFile('run_tests.sh').path] = <io.Process>[
-        MockProcess(exitCode: 1),
+          package.directory.childFile('run_tests.sh').path] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1)),
       ];
 
       Error? commandError;
@@ -305,9 +303,9 @@ void main() {
         'run_tests.sh',
       ]);
 
-      processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-        MockProcess(), // pub get
-        MockProcess(exitCode: 1), // test script
+      processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(), <String>['pub', 'get']),
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['test']),
       ];
 
       Error? commandError;
diff --git a/script/tool/test/drive_examples_command_test.dart b/script/tool/test/drive_examples_command_test.dart
index 0b6082098a..841ffd5578 100644
--- a/script/tool/test/drive_examples_command_test.dart
+++ b/script/tool/test/drive_examples_command_test.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'dart:convert';
-import 'dart:io' as io;
 
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
@@ -65,7 +64,9 @@ void main() {
           MockProcess(stdout: output, stdoutEncoding: utf8);
       processRunner
               .mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
-          <io.Process>[mockDevicesProcess];
+          <FakeProcessInfo>[
+        FakeProcessInfo(mockDevicesProcess, <String>['devices'])
+      ];
     }
 
     test('fails if no platforms are provided', () async {
@@ -152,7 +153,9 @@ void main() {
       // Simulate failure from `flutter devices`.
       processRunner
               .mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
-          <io.Process>[MockProcess(exitCode: 1)];
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['devices'])
+      ];
 
       Error? commandError;
       final List<String> output = await runCapturingPrint(
@@ -1055,10 +1058,12 @@ void main() {
       // Simulate failure from `flutter drive`.
       processRunner
               .mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
-          <io.Process>[
+          <FakeProcessInfo>[
         // No mock for 'devices', since it's running for macOS.
-        MockProcess(exitCode: 1), // 'drive' #1
-        MockProcess(exitCode: 1), // 'drive' #2
+        FakeProcessInfo(
+            MockProcess(exitCode: 1), <String>['drive']), // 'drive' #1
+        FakeProcessInfo(
+            MockProcess(exitCode: 1), <String>['drive']), // 'drive' #2
       ];
 
       Error? commandError;
diff --git a/script/tool/test/federation_safety_check_command_test.dart b/script/tool/test/federation_safety_check_command_test.dart
index 6b6b1a5145..0699dc251c 100644
--- a/script/tool/test/federation_safety_check_command_test.dart
+++ b/script/tool/test/federation_safety_check_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -59,8 +57,8 @@ void main() {
     final String changedFileOutput = <File>[
       package.libDirectory.childFile('foo.dart'),
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
 
     final List<String> output =
@@ -82,8 +80,8 @@ void main() {
     final String changedFileOutput = <File>[
       package.libDirectory.childFile('foo.dart'),
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
 
     final List<String> output =
@@ -107,8 +105,8 @@ void main() {
     final String changedFileOutput = <File>[
       platformInterface.libDirectory.childFile('foo.dart'),
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
 
     final List<String> output =
@@ -136,8 +134,8 @@ void main() {
       platformInterface.libDirectory.childFile('foo.dart'),
       platformInterface.pubspecFile,
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
 
     final List<String> output =
@@ -176,8 +174,8 @@ void main() {
       appFacing.libDirectory.childFile('foo.dart'),
       implementation.libDirectory.childFile('foo.dart'),
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
 
     final List<String> output =
@@ -210,8 +208,8 @@ void main() {
       platformInterface.pubspecFile,
       platformInterface.libDirectory.childFile('foo.dart'),
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
 
     Error? commandError;
@@ -255,8 +253,8 @@ void main() {
       platformInterface.pubspecFile,
       platformInterface.testDirectory.childFile('foo.dart'),
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
 
     final List<String> output =
@@ -287,12 +285,13 @@ void main() {
       platformInterface.pubspecFile,
       platformInterface.libDirectory.childFile('foo.dart'),
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
     // Simulate no change to the version in the interface's pubspec.yaml.
-    processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-      MockProcess(stdout: platformInterface.pubspecFile.readAsStringSync()),
+    processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(
+          stdout: platformInterface.pubspecFile.readAsStringSync())),
     ];
 
     final List<String> output =
@@ -328,8 +327,8 @@ void main() {
       otherPlugin1.libDirectory.childFile('bar.dart'),
       otherPlugin2.libDirectory.childFile('baz.dart'),
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
 
     final List<String> output =
@@ -357,8 +356,8 @@ void main() {
       // This should be picked up as a change to 'foo', and not crash.
       plugin.directory.childFile('foo_bar.baz'),
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
 
     final List<String> output =
@@ -394,8 +393,8 @@ void main() {
           .childDirectory('lib')
           .childFile('foo.dart'),
     ].map((File file) => file.path).join('\n');
-    processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-      MockProcess(stdout: changedFileOutput),
+    processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
     ];
 
     final List<String> output =
diff --git a/script/tool/test/firebase_test_lab_command_test.dart b/script/tool/test/firebase_test_lab_command_test.dart
index 364f0697b2..70aabf7611 100644
--- a/script/tool/test/firebase_test_lab_command_test.dart
+++ b/script/tool/test/firebase_test_lab_command_test.dart
@@ -55,8 +55,8 @@ public class MainActivityTest {
     }
 
     test('fails if gcloud auth fails', () async {
-      processRunner.mockProcessesForExecutable['gcloud'] = <Process>[
-        MockProcess(exitCode: 1)
+      processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['auth'])
       ];
 
       const String javaTestFileRelativePath =
@@ -84,9 +84,9 @@ public class MainActivityTest {
     });
 
     test('retries gcloud set', () async {
-      processRunner.mockProcessesForExecutable['gcloud'] = <Process>[
-        MockProcess(), // auth
-        MockProcess(exitCode: 1), // config
+      processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(), <String>['auth']),
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['config']),
       ];
 
       const String javaTestFileRelativePath =
@@ -349,12 +349,15 @@ public class MainActivityTest {
       ]);
       writeJavaTestFile(plugin, javaTestFileRelativePath);
 
-      processRunner.mockProcessesForExecutable['gcloud'] = <Process>[
-        MockProcess(), // auth
-        MockProcess(), // config
-        MockProcess(exitCode: 1), // integration test #1
-        MockProcess(exitCode: 1), // integration test #1 retry
-        MockProcess(), // integration test #2
+      processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(), <String>['auth']),
+        FakeProcessInfo(MockProcess(), <String>['config']),
+        FakeProcessInfo(MockProcess(exitCode: 1),
+            <String>['firebase', 'test']), // integration test #1
+        FakeProcessInfo(MockProcess(exitCode: 1),
+            <String>['firebase', 'test']), // integration test #1 retry
+        FakeProcessInfo(
+            MockProcess(), <String>['firebase', 'test']), // integration test #2
       ];
 
       Error? commandError;
@@ -395,12 +398,15 @@ public class MainActivityTest {
       ]);
       writeJavaTestFile(plugin, javaTestFileRelativePath);
 
-      processRunner.mockProcessesForExecutable['gcloud'] = <Process>[
-        MockProcess(), // auth
-        MockProcess(), // config
-        MockProcess(exitCode: 1), // integration test #1
-        MockProcess(), // integration test #1 retry
-        MockProcess(), // integration test #2
+      processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(), <String>['auth']),
+        FakeProcessInfo(MockProcess(), <String>['config']),
+        FakeProcessInfo(MockProcess(exitCode: 1),
+            <String>['firebase', 'test']), // integration test #1
+        FakeProcessInfo(MockProcess(),
+            <String>['firebase', 'test']), // integration test #1 retry
+        FakeProcessInfo(
+            MockProcess(), <String>['firebase', 'test']), // integration test #2
       ];
 
       final List<String> output = await runCapturingPrint(runner, <String>[
@@ -654,8 +660,8 @@ public class MainActivityTest {
       ]);
       writeJavaTestFile(plugin, javaTestFileRelativePath);
 
-      processRunner.mockProcessesForExecutable['flutter'] = <Process>[
-        MockProcess(exitCode: 1) // flutter build
+      processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['build'])
       ];
 
       Error? commandError;
@@ -695,8 +701,9 @@ public class MainActivityTest {
           .platformDirectory(FlutterPlatform.android)
           .childFile('gradlew')
           .path;
-      processRunner.mockProcessesForExecutable[gradlewPath] = <Process>[
-        MockProcess(exitCode: 1)
+      processRunner.mockProcessesForExecutable[gradlewPath] = <FakeProcessInfo>[
+        FakeProcessInfo(
+            MockProcess(exitCode: 1), <String>['app:assembleAndroidTest']),
       ];
 
       Error? commandError;
@@ -736,9 +743,9 @@ public class MainActivityTest {
           .platformDirectory(FlutterPlatform.android)
           .childFile('gradlew')
           .path;
-      processRunner.mockProcessesForExecutable[gradlewPath] = <Process>[
-        MockProcess(), // assembleAndroidTest
-        MockProcess(exitCode: 1), // assembleDebug
+      processRunner.mockProcessesForExecutable[gradlewPath] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(), <String>['app:assembleAndroidTest']),
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['app:assembleDebug'])
       ];
 
       Error? commandError;
diff --git a/script/tool/test/fix_command_test.dart b/script/tool/test/fix_command_test.dart
index 16061d2206..ad767968e2 100644
--- a/script/tool/test/fix_command_test.dart
+++ b/script/tool/test/fix_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -57,8 +55,8 @@ void main() {
   test('fails if "dart fix" fails', () async {
     createFakePlugin('foo', packagesDir);
 
-    processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-      MockProcess(exitCode: 1),
+    processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['fix']),
     ];
 
     Error? commandError;
diff --git a/script/tool/test/format_command_test.dart b/script/tool/test/format_command_test.dart
index 634a996bcc..546be9289f 100644
--- a/script/tool/test/format_command_test.dart
+++ b/script/tool/test/format_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -149,8 +147,8 @@ void main() {
     ];
     createFakePlugin('a_plugin', packagesDir, extraFiles: files);
 
-    processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-      MockProcess(exitCode: 1)
+    processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['format'])
     ];
     Error? commandError;
     final List<String> output = await runCapturingPrint(
@@ -202,8 +200,8 @@ void main() {
     ];
     createFakePlugin('a_plugin', packagesDir, extraFiles: files);
 
-    processRunner.mockProcessesForExecutable['java'] = <io.Process>[
-      MockProcess(exitCode: 1)
+    processRunner.mockProcessesForExecutable['java'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['-version'])
     ];
     Error? commandError;
     final List<String> output = await runCapturingPrint(
@@ -228,9 +226,10 @@ void main() {
     ];
     createFakePlugin('a_plugin', packagesDir, extraFiles: files);
 
-    processRunner.mockProcessesForExecutable['java'] = <io.Process>[
-      MockProcess(), // check for working java
-      MockProcess(exitCode: 1), // format
+    processRunner.mockProcessesForExecutable['java'] = <FakeProcessInfo>[
+      FakeProcessInfo(
+          MockProcess(), <String>['-version']), // check for working java
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['-jar']), // format
     ];
     Error? commandError;
     final List<String> output = await runCapturingPrint(
@@ -315,9 +314,8 @@ void main() {
     ];
     createFakePlugin('a_plugin', packagesDir, extraFiles: files);
 
-    processRunner.mockProcessesForExecutable['clang-format'] = <io.Process>[
-      MockProcess(exitCode: 1)
-    ];
+    processRunner.mockProcessesForExecutable['clang-format'] =
+        <FakeProcessInfo>[FakeProcessInfo(MockProcess(exitCode: 1))];
     Error? commandError;
     final List<String> output = await runCapturingPrint(
         runner, <String>['format'], errorHandler: (Error e) {
@@ -344,15 +342,17 @@ void main() {
       extraFiles: files,
     );
 
-    processRunner.mockProcessesForExecutable['clang-format'] = <io.Process>[
-      MockProcess(exitCode: 1)
-    ];
-    processRunner.mockProcessesForExecutable['which'] = <io.Process>[
-      MockProcess(
-          stdout: '/usr/local/bin/clang-format\n/path/to/working-clang-format')
+    processRunner.mockProcessesForExecutable['clang-format'] =
+        <FakeProcessInfo>[FakeProcessInfo(MockProcess(exitCode: 1))];
+    processRunner.mockProcessesForExecutable['which'] = <FakeProcessInfo>[
+      FakeProcessInfo(
+          MockProcess(
+              stdout:
+                  '/usr/local/bin/clang-format\n/path/to/working-clang-format'),
+          <String>['-a', 'clang-format'])
     ];
     processRunner.mockProcessesForExecutable['/usr/local/bin/clang-format'] =
-        <io.Process>[MockProcess(exitCode: 1)];
+        <FakeProcessInfo>[FakeProcessInfo(MockProcess(exitCode: 1))];
     await runCapturingPrint(runner, <String>['format']);
 
     expect(
@@ -407,9 +407,11 @@ void main() {
     ];
     createFakePlugin('a_plugin', packagesDir, extraFiles: files);
 
-    processRunner.mockProcessesForExecutable['clang-format'] = <io.Process>[
-      MockProcess(), // check for working clang-format
-      MockProcess(exitCode: 1), // format
+    processRunner.mockProcessesForExecutable['clang-format'] =
+        <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(),
+          <String>['--version']), // check for working clang-format
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['-i']), // format
     ];
     Error? commandError;
     final List<String> output = await runCapturingPrint(
@@ -492,8 +494,9 @@ void main() {
     createFakePlugin('a_plugin', packagesDir, extraFiles: files);
 
     const String changedFilePath = 'packages/a_plugin/linux/foo_plugin.cc';
-    processRunner.mockProcessesForExecutable['git'] = <io.Process>[
-      MockProcess(stdout: changedFilePath),
+    processRunner.mockProcessesForExecutable['git'] = <FakeProcessInfo>[
+      FakeProcessInfo(
+          MockProcess(stdout: changedFilePath), <String>['ls-files']),
     ];
 
     Error? commandError;
@@ -520,8 +523,8 @@ void main() {
     ];
     createFakePlugin('a_plugin', packagesDir, extraFiles: files);
 
-    processRunner.mockProcessesForExecutable['git'] = <io.Process>[
-      MockProcess(exitCode: 1)
+    processRunner.mockProcessesForExecutable['git'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['ls-files'])
     ];
     Error? commandError;
     final List<String> output =
@@ -546,9 +549,10 @@ void main() {
     createFakePlugin('a_plugin', packagesDir, extraFiles: files);
 
     const String changedFilePath = 'packages/a_plugin/linux/foo_plugin.cc';
-    processRunner.mockProcessesForExecutable['git'] = <io.Process>[
-      MockProcess(stdout: changedFilePath), // ls-files
-      MockProcess(exitCode: 1), // diff
+    processRunner.mockProcessesForExecutable['git'] = <FakeProcessInfo>[
+      FakeProcessInfo(
+          MockProcess(stdout: changedFilePath), <String>['ls-files']),
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['diff']),
     ];
 
     Error? commandError;
diff --git a/script/tool/test/lint_android_command_test.dart b/script/tool/test/lint_android_command_test.dart
index 40ffaf177a..ee1db42f10 100644
--- a/script/tool/test/lint_android_command_test.dart
+++ b/script/tool/test/lint_android_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -186,8 +184,8 @@ ${warningsConfigured ? warningConfig : ''}
           .platformDirectory(FlutterPlatform.android)
           .childFile('gradlew')
           .path;
-      processRunner.mockProcessesForExecutable[gradlewPath] = <io.Process>[
-        MockProcess(exitCode: 1),
+      processRunner.mockProcessesForExecutable[gradlewPath] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1)),
       ];
 
       Error? commandError;
diff --git a/script/tool/test/make_deps_path_based_command_test.dart b/script/tool/test/make_deps_path_based_command_test.dart
index dd248cd9c9..05ca0ca6aa 100644
--- a/script/tool/test/make_deps_path_based_command_test.dart
+++ b/script/tool/test/make_deps_path_based_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -352,12 +350,13 @@ ${devDependencies.map((String dep) => '  $dep: ^1.0.0').join('\n')}
       final String changedFileOutput = <File>[
         package.pubspecFile,
       ].map((File file) => file.path).join('\n');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: changedFileOutput),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
       ];
       // Simulate no change to the version in the interface's pubspec.yaml.
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: package.pubspecFile.readAsStringSync()),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(
+            MockProcess(stdout: package.pubspecFile.readAsStringSync())),
       ];
 
       final List<String> output = await runCapturingPrint(runner, <String>[
@@ -378,8 +377,8 @@ ${devDependencies.map((String dep) => '  $dep: ^1.0.0').join('\n')}
         // A change for a file that's not on disk simulates a deletion.
         packagesDir.childDirectory('foo').childFile('pubspec.yaml'),
       ].map((File file) => file.path).join('\n');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: changedFileOutput),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
       ];
 
       final List<String> output = await runCapturingPrint(runner, <String>[
@@ -405,14 +404,14 @@ ${devDependencies.map((String dep) => '  $dep: ^1.0.0').join('\n')}
       final String changedFileOutput = <File>[
         pubspecFile,
       ].map((File file) => file.path).join('\n');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: changedFileOutput),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
       ];
       final String gitPubspecContents =
           pubspecFile.readAsStringSync().replaceAll(newVersion, '1.0.0');
       // Simulate no change to the version in the interface's pubspec.yaml.
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: gitPubspecContents),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: gitPubspecContents)),
       ];
 
       final List<String> output = await runCapturingPrint(runner, <String>[
@@ -437,14 +436,14 @@ ${devDependencies.map((String dep) => '  $dep: ^1.0.0').join('\n')}
       final String changedFileOutput = <File>[
         pubspecFile,
       ].map((File file) => file.path).join('\n');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: changedFileOutput),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
       ];
       final String gitPubspecContents =
           pubspecFile.readAsStringSync().replaceAll(newVersion, '1.0.0');
       // Simulate no change to the version in the interface's pubspec.yaml.
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: gitPubspecContents),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: gitPubspecContents)),
       ];
 
       final List<String> output = await runCapturingPrint(runner, <String>[
@@ -469,14 +468,14 @@ ${devDependencies.map((String dep) => '  $dep: ^1.0.0').join('\n')}
       final String changedFileOutput = <File>[
         pubspecFile,
       ].map((File file) => file.path).join('\n');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: changedFileOutput),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
       ];
       final String gitPubspecContents =
           pubspecFile.readAsStringSync().replaceAll(newVersion, '1.0.0');
       // Simulate no change to the version in the interface's pubspec.yaml.
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: gitPubspecContents),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: gitPubspecContents)),
       ];
 
       final List<String> output = await runCapturingPrint(runner, <String>[
@@ -501,14 +500,14 @@ ${devDependencies.map((String dep) => '  $dep: ^1.0.0').join('\n')}
       final String changedFileOutput = <File>[
         pubspecFile,
       ].map((File file) => file.path).join('\n');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: changedFileOutput),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
       ];
       final String gitPubspecContents =
           pubspecFile.readAsStringSync().replaceAll(newVersion, '0.7.0');
       // Simulate no change to the version in the interface's pubspec.yaml.
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: gitPubspecContents),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: gitPubspecContents)),
       ];
 
       final List<String> output = await runCapturingPrint(runner, <String>[
@@ -536,13 +535,13 @@ ${devDependencies.map((String dep) => '  $dep: ^1.0.0').join('\n')}
       final String changedFileOutput = <File>[
         pubspecFile,
       ].map((File file) => file.path).join('\n');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: changedFileOutput),
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: changedFileOutput)),
       ];
       final String gitPubspecContents =
           pubspecFile.readAsStringSync().replaceAll(newVersion, '1.0.0');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: gitPubspecContents),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: gitPubspecContents)),
       ];
 
       final List<String> output = await runCapturingPrint(runner, <String>[
diff --git a/script/tool/test/native_test_command_test.dart b/script/tool/test/native_test_command_test.dart
index ddbf6a5069..3d327a0e39 100644
--- a/script/tool/test/native_test_command_test.dart
+++ b/script/tool/test/native_test_command_test.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'dart:convert';
-import 'dart:io' as io;
 
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
@@ -94,15 +93,16 @@ void main() {
       runner.addCommand(command);
     });
 
-    // Returns a MockProcess to provide for "xcrun xcodebuild -list" for a
+    // Returns a FakeProcessInfo to provide for "xcrun xcodebuild -list" for a
     // project that contains [targets].
-    MockProcess getMockXcodebuildListProcess(List<String> targets) {
+    FakeProcessInfo getMockXcodebuildListProcess(List<String> targets) {
       final Map<String, dynamic> projects = <String, dynamic>{
         'project': <String, dynamic>{
           'targets': targets,
         }
       };
-      return MockProcess(stdout: jsonEncode(projects));
+      return FakeProcessInfo(MockProcess(stdout: jsonEncode(projects)),
+          <String>['xcodebuild', '-list']);
     }
 
     // Returns the ProcessCall to expect for checking the targets present in
@@ -212,10 +212,11 @@ void main() {
 
       final Directory pluginExampleDirectory = getExampleDir(plugin);
 
-      processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+      processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
         getMockXcodebuildListProcess(<String>['RunnerTests', 'RunnerUITests']),
         // Exit code 66 from testing indicates no tests.
-        MockProcess(exitCode: 66),
+        FakeProcessInfo(
+            MockProcess(exitCode: 66), <String>['xcodebuild', 'test']),
       ];
       final List<String> output = await runCapturingPrint(
           runner, <String>['native-test', '--macos', '--no-unit']);
@@ -279,7 +280,7 @@ void main() {
 
         final Directory pluginExampleDirectory = getExampleDir(plugin);
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
           getMockXcodebuildListProcess(
               <String>['RunnerTests', 'RunnerUITests']),
         ];
@@ -315,8 +316,9 @@ void main() {
             });
         final Directory pluginExampleDirectory = getExampleDir(plugin);
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-          MockProcess(stdout: jsonEncode(_kDeviceListMap)), // simctl
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: jsonEncode(_kDeviceListMap)),
+              <String>['simctl', 'list']),
           getMockXcodebuildListProcess(
               <String>['RunnerTests', 'RunnerUITests']),
         ];
@@ -386,7 +388,7 @@ void main() {
 
         final Directory pluginExampleDirectory = getExampleDir(plugin);
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
           getMockXcodebuildListProcess(
               <String>['RunnerTests', 'RunnerUITests']),
         ];
@@ -807,9 +809,8 @@ public class FlutterActivityTest {
             .platformDirectory(FlutterPlatform.android)
             .childFile('gradlew')
             .path;
-        processRunner.mockProcessesForExecutable[gradlewPath] = <io.Process>[
-          MockProcess(exitCode: 1)
-        ];
+        processRunner.mockProcessesForExecutable[gradlewPath] =
+            <FakeProcessInfo>[FakeProcessInfo(MockProcess(exitCode: 1))];
 
         Error? commandError;
         final List<String> output = await runCapturingPrint(
@@ -850,9 +851,12 @@ public class FlutterActivityTest {
             .platformDirectory(FlutterPlatform.android)
             .childFile('gradlew')
             .path;
-        processRunner.mockProcessesForExecutable[gradlewPath] = <io.Process>[
-          MockProcess(), // unit passes
-          MockProcess(exitCode: 1), // integration fails
+        processRunner.mockProcessesForExecutable[gradlewPath] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(
+              MockProcess(), <String>['testDebugUnitTest']), // unit passes
+          FakeProcessInfo(MockProcess(exitCode: 1),
+              <String>['app:connectedAndroidTest']), // integration fails
         ];
 
         Error? commandError;
@@ -1099,7 +1103,9 @@ public class FlutterActivityTest {
             <String>['example', ...testBinaryRelativePath.split('/')]);
 
         processRunner.mockProcessesForExecutable[testBinary.path] =
-            <io.Process>[MockProcess(exitCode: 1)];
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(exitCode: 1)),
+        ];
 
         Error? commandError;
         final List<String> output = await runCapturingPrint(runner, <String>[
@@ -1135,8 +1141,8 @@ public class FlutterActivityTest {
               platformMacOS: const PlatformDetails(PlatformSupport.inline),
             });
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-          MockProcess(exitCode: 1)
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(exitCode: 1))
         ];
 
         Error? commandError;
@@ -1164,7 +1170,7 @@ public class FlutterActivityTest {
 
         final Directory pluginExampleDirectory = getExampleDir(plugin);
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
           getMockXcodebuildListProcess(
               <String>['RunnerTests', 'RunnerUITests']),
         ];
@@ -1199,7 +1205,7 @@ public class FlutterActivityTest {
 
         final Directory pluginExampleDirectory = getExampleDir(plugin1);
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
           getMockXcodebuildListProcess(
               <String>['RunnerTests', 'RunnerUITests']),
         ];
@@ -1235,7 +1241,7 @@ public class FlutterActivityTest {
         final Directory pluginExampleDirectory = getExampleDir(plugin1);
 
         // Simulate a project with unit tests but no integration tests...
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
           getMockXcodebuildListProcess(<String>['RunnerTests']),
         ];
 
@@ -1269,7 +1275,7 @@ public class FlutterActivityTest {
 
         final Directory pluginExampleDirectory = getExampleDir(plugin1);
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
           getMockXcodebuildListProcess(<String>['RunnerUITests']),
         ];
 
@@ -1308,8 +1314,9 @@ public class FlutterActivityTest {
 
         final Directory pluginExampleDirectory = getExampleDir(plugin1);
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-          MockProcess(exitCode: 1), // xcodebuild -list
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+          FakeProcessInfo(
+              MockProcess(exitCode: 1), <String>['xcodebuild', '-list']),
         ];
 
         Error? commandError;
@@ -1357,13 +1364,15 @@ public class FlutterActivityTest {
         final Directory androidFolder =
             pluginExampleDirectory.childDirectory('android');
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
           getMockXcodebuildListProcess(
               <String>['RunnerTests', 'RunnerUITests']), // iOS list
-          MockProcess(), // iOS run
+          FakeProcessInfo(
+              MockProcess(), <String>['xcodebuild', 'test']), // iOS run
           getMockXcodebuildListProcess(
               <String>['RunnerTests', 'RunnerUITests']), // macOS list
-          MockProcess(), // macOS run
+          FakeProcessInfo(
+              MockProcess(), <String>['xcodebuild', 'test']), // macOS run
         ];
 
         final List<String> output = await runCapturingPrint(runner, <String>[
@@ -1404,7 +1413,7 @@ public class FlutterActivityTest {
 
         final Directory pluginExampleDirectory = getExampleDir(plugin);
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
           getMockXcodebuildListProcess(
               <String>['RunnerTests', 'RunnerUITests']),
         ];
@@ -1440,7 +1449,7 @@ public class FlutterActivityTest {
 
         final Directory pluginExampleDirectory = getExampleDir(plugin);
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
           getMockXcodebuildListProcess(
               <String>['RunnerTests', 'RunnerUITests']),
         ];
@@ -1539,7 +1548,7 @@ public class FlutterActivityTest {
           ],
         );
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
           getMockXcodebuildListProcess(
               <String>['RunnerTests', 'RunnerUITests']),
         ];
@@ -1551,9 +1560,8 @@ public class FlutterActivityTest {
             .platformDirectory(FlutterPlatform.android)
             .childFile('gradlew')
             .path;
-        processRunner.mockProcessesForExecutable[gradlewPath] = <io.Process>[
-          MockProcess(exitCode: 1)
-        ];
+        processRunner.mockProcessesForExecutable[gradlewPath] =
+            <FakeProcessInfo>[FakeProcessInfo(MockProcess(exitCode: 1))];
 
         Error? commandError;
         final List<String> output = await runCapturingPrint(runner, <String>[
@@ -1603,12 +1611,11 @@ public class FlutterActivityTest {
             .platformDirectory(FlutterPlatform.android)
             .childFile('gradlew')
             .path;
-        processRunner.mockProcessesForExecutable[gradlewPath] = <io.Process>[
-          MockProcess(exitCode: 1)
-        ];
-        // Simulate failing Android.
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-          MockProcess(exitCode: 1)
+        processRunner.mockProcessesForExecutable[gradlewPath] =
+            <FakeProcessInfo>[FakeProcessInfo(MockProcess(exitCode: 1))];
+        // Simulate failing iOS.
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(exitCode: 1))
         ];
 
         Error? commandError;
@@ -1828,7 +1835,9 @@ public class FlutterActivityTest {
             <String>['example', ...testBinaryRelativePath.split('/')]);
 
         processRunner.mockProcessesForExecutable[testBinary.path] =
-            <io.Process>[MockProcess(exitCode: 1)];
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(exitCode: 1)),
+        ];
 
         Error? commandError;
         final List<String> output = await runCapturingPrint(runner, <String>[
diff --git a/script/tool/test/podspec_check_command_test.dart b/script/tool/test/podspec_check_command_test.dart
index 70632017ff..a1244a2337 100644
--- a/script/tool/test/podspec_check_command_test.dart
+++ b/script/tool/test/podspec_check_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -122,9 +120,9 @@ void main() {
       );
       _writeFakePodspec(plugin, 'ios');
 
-      processRunner.mockProcessesForExecutable['pod'] = <io.Process>[
-        MockProcess(stdout: 'Foo', stderr: 'Bar'),
-        MockProcess(),
+      processRunner.mockProcessesForExecutable['pod'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'Foo', stderr: 'Bar')),
+        FakeProcessInfo(MockProcess()),
       ];
 
       final List<String> output =
@@ -176,8 +174,8 @@ void main() {
       _writeFakePodspec(plugin, 'ios');
 
       // Simulate failure from `which pod`.
-      processRunner.mockProcessesForExecutable['which'] = <io.Process>[
-        MockProcess(exitCode: 1),
+      processRunner.mockProcessesForExecutable['which'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['pod']),
       ];
 
       Error? commandError;
@@ -202,8 +200,8 @@ void main() {
       _writeFakePodspec(plugin, 'ios');
 
       // Simulate failure from `pod`.
-      processRunner.mockProcessesForExecutable['pod'] = <io.Process>[
-        MockProcess(exitCode: 1),
+      processRunner.mockProcessesForExecutable['pod'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1)),
       ];
 
       Error? commandError;
@@ -230,9 +228,9 @@ void main() {
       _writeFakePodspec(plugin, 'ios');
 
       // Simulate failure from the second call to `pod`.
-      processRunner.mockProcessesForExecutable['pod'] = <io.Process>[
-        MockProcess(),
-        MockProcess(exitCode: 1),
+      processRunner.mockProcessesForExecutable['pod'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess()),
+        FakeProcessInfo(MockProcess(exitCode: 1)),
       ];
 
       Error? commandError;
diff --git a/script/tool/test/publish_check_command_test.dart b/script/tool/test/publish_check_command_test.dart
index c1e8028399..f2120040fc 100644
--- a/script/tool/test/publish_check_command_test.dart
+++ b/script/tool/test/publish_check_command_test.dart
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import 'dart:convert';
-import 'dart:io' as io;
 
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
@@ -117,8 +116,9 @@ void main() {
     test('fail on negative test', () async {
       createFakePlugin('plugin_tools_test_package_a', packagesDir);
 
-      processRunner.mockProcessesForExecutable['flutter'] = <io.Process>[
-        MockProcess(exitCode: 1, stdout: 'Some error from pub')
+      processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1, stdout: 'Some error from pub'),
+            <String>['pub', 'publish'])
       ];
 
       Error? commandError;
@@ -204,8 +204,8 @@ void main() {
           stdout: 'Package has 1 warning.\n'
               'Packages with an SDK constraint on a pre-release of the Dart '
               'SDK should themselves be published as a pre-release version.');
-      processRunner.mockProcessesForExecutable['flutter'] = <io.Process>[
-        process,
+      processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
+        FakeProcessInfo(process, <String>['pub', 'publish'])
       ];
 
       expect(
@@ -222,8 +222,8 @@ void main() {
           stdout: 'Package has 1 warning.\n'
               'Packages with an SDK constraint on a pre-release of the Dart '
               'SDK should themselves be published as a pre-release version.');
-      processRunner.mockProcessesForExecutable['flutter'] = <io.Process>[
-        process,
+      processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
+        FakeProcessInfo(process, <String>['pub', 'publish'])
       ];
 
       Error? commandError;
@@ -246,8 +246,9 @@ void main() {
     test('Success message on stderr is not printed as an error', () async {
       createFakePlugin('d', packagesDir);
 
-      processRunner.mockProcessesForExecutable['flutter'] = <io.Process>[
-        MockProcess(stdout: 'Package has 0 warnings.'),
+      processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'Package has 0 warnings.'),
+            <String>['pub', 'publish']),
       ];
 
       final List<String> output =
@@ -284,8 +285,9 @@ void main() {
       runner.addCommand(PublishCheckCommand(packagesDir,
           processRunner: processRunner, httpClient: mockClient));
 
-      processRunner.mockProcessesForExecutable['flutter'] = <io.Process>[
-        MockProcess(exitCode: 1, stdout: 'Some error from pub')
+      processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1, stdout: 'Some error from pub'),
+            <String>['pub', 'publish'])
       ];
 
       Error? commandError;
diff --git a/script/tool/test/publish_command_test.dart b/script/tool/test/publish_command_test.dart
index da5f9c871f..94023032ec 100644
--- a/script/tool/test/publish_command_test.dart
+++ b/script/tool/test/publish_command_test.dart
@@ -86,8 +86,10 @@ void main() {
       final RepositoryPackage plugin =
           createFakePlugin('foo', packagesDir, examples: <String>[]);
 
-      processRunner.mockProcessesForExecutable['git-status'] = <io.Process>[
-        MockProcess(stdout: '?? ${plugin.directory.childFile('tmp').path}\n')
+      processRunner.mockProcessesForExecutable['git-status'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(
+            stdout: '?? ${plugin.directory.childFile('tmp').path}\n'))
       ];
 
       Error? commandError;
@@ -116,8 +118,9 @@ void main() {
     test("fails immediately if the remote doesn't exist", () async {
       createFakePlugin('foo', packagesDir, examples: <String>[]);
 
-      processRunner.mockProcessesForExecutable['git-remote'] = <io.Process>[
-        MockProcess(exitCode: 1),
+      processRunner.mockProcessesForExecutable['git-remote'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1)),
       ];
 
       Error? commandError;
@@ -142,16 +145,19 @@ void main() {
       createFakePlugin('plugin1', packagesDir, examples: <String>[]);
       createFakePlugin('plugin2', packagesDir, examples: <String>[]);
 
-      processRunner.mockProcessesForExecutable[flutterCommand] = <io.Process>[
-        MockProcess(
-            stdout: 'Foo',
-            stderr: 'Bar',
-            stdoutEncoding: utf8,
-            stderrEncoding: utf8), // pub publish for plugin1
-        MockProcess(
-            stdout: 'Baz',
-            stdoutEncoding: utf8,
-            stderrEncoding: utf8), // pub publish for plugin1
+      processRunner.mockProcessesForExecutable[flutterCommand] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(
+            MockProcess(
+                stdout: 'Foo',
+                stderr: 'Bar',
+                stdoutEncoding: utf8,
+                stderrEncoding: utf8),
+            <String>['pub', 'publish']), // publish for plugin1
+        FakeProcessInfo(
+            MockProcess(
+                stdout: 'Baz', stdoutEncoding: utf8, stderrEncoding: utf8),
+            <String>['pub', 'publish']), // publish for plugin2
       ];
 
       final List<String> output = await runCapturingPrint(
@@ -256,8 +262,9 @@ void main() {
     test('throws if pub publish fails', () async {
       createFakePlugin('foo', packagesDir, examples: <String>[]);
 
-      processRunner.mockProcessesForExecutable[flutterCommand] = <io.Process>[
-        MockProcess(exitCode: 128) // pub publish
+      processRunner.mockProcessesForExecutable[flutterCommand] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 128), <String>['pub', 'publish'])
       ];
 
       Error? commandError;
@@ -341,8 +348,9 @@ void main() {
     test('only if publishing succeeded', () async {
       createFakePlugin('foo', packagesDir, examples: <String>[]);
 
-      processRunner.mockProcessesForExecutable[flutterCommand] = <io.Process>[
-        MockProcess(exitCode: 128) // pub publish
+      processRunner.mockProcessesForExecutable[flutterCommand] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 128), <String>['pub', 'publish']),
       ];
 
       Error? commandError;
@@ -483,10 +491,10 @@ void main() {
         'plugin2',
         packagesDir.childDirectory('plugin2'),
       );
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(
             stdout: '${plugin1.pubspecFile.path}\n'
-                '${plugin2.pubspecFile.path}\n')
+                '${plugin2.pubspecFile.path}\n'))
       ];
       mockStdin.readLineOutput = 'y';
 
@@ -541,13 +549,13 @@ void main() {
 
       // Git results for plugin0 having been released already, and plugin1 and
       // plugin2 being new.
-      processRunner.mockProcessesForExecutable['git-tag'] = <io.Process>[
-        MockProcess(stdout: 'plugin0-v0.0.1\n')
+      processRunner.mockProcessesForExecutable['git-tag'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'plugin0-v0.0.1\n'))
       ];
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(
             stdout: '${plugin1.pubspecFile.path}\n'
-                '${plugin2.pubspecFile.path}\n')
+                '${plugin2.pubspecFile.path}\n'))
       ];
 
       mockStdin.readLineOutput = 'y';
@@ -589,10 +597,10 @@ void main() {
       final RepositoryPackage plugin2 =
           createFakePlugin('plugin2', packagesDir.childDirectory('plugin2'));
 
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(
             stdout: '${plugin1.pubspecFile.path}\n'
-                '${plugin2.pubspecFile.path}\n')
+                '${plugin2.pubspecFile.path}\n'))
       ];
       mockStdin.readLineOutput = 'y';
 
@@ -642,10 +650,10 @@ void main() {
           'plugin2', packagesDir.childDirectory('plugin2'),
           version: '0.0.2');
 
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(
             stdout: '${plugin1.pubspecFile.path}\n'
-                '${plugin2.pubspecFile.path}\n')
+                '${plugin2.pubspecFile.path}\n'))
       ];
 
       mockStdin.readLineOutput = 'y';
@@ -691,10 +699,10 @@ void main() {
           createFakePlugin('plugin2', packagesDir.childDirectory('plugin2'));
       plugin2.directory.deleteSync(recursive: true);
 
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(
             stdout: '${plugin1.pubspecFile.path}\n'
-                '${plugin2.pubspecFile.path}\n')
+                '${plugin2.pubspecFile.path}\n'))
       ];
 
       mockStdin.readLineOutput = 'y';
@@ -737,15 +745,15 @@ void main() {
           'plugin2', packagesDir.childDirectory('plugin2'),
           version: '0.0.2');
 
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(
             stdout: '${plugin1.pubspecFile.path}\n'
-                '${plugin2.pubspecFile.path}\n')
+                '${plugin2.pubspecFile.path}\n'))
       ];
-      processRunner.mockProcessesForExecutable['git-tag'] = <io.Process>[
-        MockProcess(
+      processRunner.mockProcessesForExecutable['git-tag'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(
             stdout: 'plugin1-v0.0.2\n'
-                'plugin2-v0.0.2\n')
+                'plugin2-v0.0.2\n'))
       ];
 
       final List<String> output = await runCapturingPrint(commandRunner,
@@ -787,10 +795,10 @@ void main() {
           'plugin2', packagesDir.childDirectory('plugin2'),
           version: '0.0.2');
 
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(
             stdout: '${plugin1.pubspecFile.path}\n'
-                '${plugin2.pubspecFile.path}\n')
+                '${plugin2.pubspecFile.path}\n'))
       ];
 
       Error? commandError;
@@ -823,10 +831,10 @@ void main() {
       final RepositoryPackage plugin2 =
           createFakePlugin('plugin2', packagesDir.childDirectory('plugin2'));
 
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(
             stdout: '${plugin1.libDirectory.childFile('plugin1.dart').path}\n'
-                '${plugin2.libDirectory.childFile('plugin2.dart').path}\n')
+                '${plugin2.libDirectory.childFile('plugin2.dart').path}\n'))
       ];
 
       final List<String> output = await runCapturingPrint(commandRunner,
@@ -847,8 +855,9 @@ void main() {
 
       final RepositoryPackage flutterPluginTools =
           createFakePlugin('flutter_plugin_tools', packagesDir);
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: flutterPluginTools.pubspecFile.path)
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(
+            MockProcess(stdout: flutterPluginTools.pubspecFile.path))
       ];
 
       final List<String> output = await runCapturingPrint(commandRunner,
diff --git a/script/tool/test/test_command_test.dart b/script/tool/test/test_command_test.dart
index 14a1e4a67c..5d34e390fd 100644
--- a/script/tool/test/test_command_test.dart
+++ b/script/tool/test/test_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -86,9 +84,10 @@ void main() {
 
       processRunner
               .mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
-          <io.Process>[
-        MockProcess(exitCode: 1), // plugin 1 test
-        MockProcess(), // plugin 2 test
+          <FakeProcessInfo>[
+        FakeProcessInfo(
+            MockProcess(exitCode: 1), <String>['test']), // plugin 1 test
+        FakeProcessInfo(MockProcess(), <String>['test']), // plugin 2 test
       ];
 
       Error? commandError;
@@ -173,8 +172,8 @@ void main() {
       createFakePackage('a_package', packagesDir,
           extraFiles: <String>['test/empty_test.dart']);
 
-      processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-        MockProcess(exitCode: 1), // dart pub get
+      processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'get'])
       ];
 
       Error? commandError;
@@ -197,9 +196,9 @@ void main() {
       createFakePackage('a_package', packagesDir,
           extraFiles: <String>['test/empty_test.dart']);
 
-      processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-        MockProcess(), // dart pub get
-        MockProcess(exitCode: 1), // dart pub run test
+      processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(), <String>['pub', 'get']),
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['run']), // run test
       ];
 
       Error? commandError;
diff --git a/script/tool/test/update_dependency_command_test.dart b/script/tool/test/update_dependency_command_test.dart
index 5d99a2df2e..e0687b2bfd 100644
--- a/script/tool/test/update_dependency_command_test.dart
+++ b/script/tool/test/update_dependency_command_test.dart
@@ -14,19 +14,23 @@ import 'package:http/testing.dart';
 import 'package:pubspec_parse/pubspec_parse.dart';
 import 'package:test/test.dart';
 
+import 'mocks.dart';
 import 'util.dart';
 
 void main() {
   FileSystem fileSystem;
   late Directory packagesDir;
+  late RecordingProcessRunner processRunner;
   late CommandRunner<void> runner;
   Future<http.Response> Function(http.Request request)? mockHttpResponse;
 
   setUp(() {
     fileSystem = MemoryFileSystem();
+    processRunner = RecordingProcessRunner();
     packagesDir = createPackagesDirectory(fileSystem: fileSystem);
     final UpdateDependencyCommand command = UpdateDependencyCommand(
       packagesDir,
+      processRunner: processRunner,
       httpClient:
           MockClient((http.Request request) => mockHttpResponse!(request)),
     );
@@ -339,5 +343,128 @@ dev_dependencies:
       expect(dep, isA<HostedDependency>());
       expect((dep! as HostedDependency).version.toString(), '1.5.0');
     });
+
+    test('regenerates all pigeon files when updating pigeon', () async {
+      final RepositoryPackage package =
+          createFakePackage('a_package', packagesDir, extraFiles: <String>[
+        'pigeons/foo.dart',
+        'pigeons/bar.dart',
+      ]);
+      addDependency(package, 'pigeon', version: '1.0.0');
+
+      await runCapturingPrint(runner, <String>[
+        'update-dependency',
+        '--pub-package',
+        'pigeon',
+        '--version',
+        '1.5.0',
+      ]);
+
+      expect(
+        processRunner.recordedCalls,
+        orderedEquals(<ProcessCall>[
+          ProcessCall(
+            'dart',
+            const <String>['pub', 'get'],
+            package.path,
+          ),
+          ProcessCall(
+            'dart',
+            const <String>['run', 'pigeon', '--input', 'pigeons/foo.dart'],
+            package.path,
+          ),
+          ProcessCall(
+            'dart',
+            const <String>['run', 'pigeon', '--input', 'pigeons/bar.dart'],
+            package.path,
+          ),
+        ]),
+      );
+    });
+
+    test('warns when regenerating pigeon if there are no pigeon files',
+        () async {
+      final RepositoryPackage package =
+          createFakePackage('a_package', packagesDir);
+      addDependency(package, 'pigeon', version: '1.0.0');
+
+      final List<String> output = await runCapturingPrint(runner, <String>[
+        'update-dependency',
+        '--pub-package',
+        'pigeon',
+        '--version',
+        '1.5.0',
+      ]);
+
+      expect(
+        output,
+        containsAllInOrder(<Matcher>[
+          contains('No pigeon input files found'),
+        ]),
+      );
+    });
+
+    test('updating pigeon fails if pub get fails', () async {
+      final RepositoryPackage package = createFakePackage(
+          'a_package', packagesDir,
+          extraFiles: <String>['pigeons/foo.dart']);
+      addDependency(package, 'pigeon', version: '1.0.0');
+
+      processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'get'])
+      ];
+
+      Error? commandError;
+      final List<String> output = await runCapturingPrint(runner, <String>[
+        'update-dependency',
+        '--pub-package',
+        'pigeon',
+        '--version',
+        '1.5.0',
+      ], errorHandler: (Error e) {
+        commandError = e;
+      });
+
+      expect(commandError, isA<ToolExit>());
+      expect(
+        output,
+        containsAllInOrder(<Matcher>[
+          contains('dart pub get failed'),
+          contains('Failed to update pigeon files'),
+        ]),
+      );
+    });
+
+    test('updating pigeon fails if running pigeon fails', () async {
+      final RepositoryPackage package = createFakePackage(
+          'a_package', packagesDir,
+          extraFiles: <String>['pigeons/foo.dart']);
+      addDependency(package, 'pigeon', version: '1.0.0');
+
+      processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(), <String>['pub', 'get']),
+        FakeProcessInfo(MockProcess(exitCode: 1), <String>['run', 'pigeon']),
+      ];
+
+      Error? commandError;
+      final List<String> output = await runCapturingPrint(runner, <String>[
+        'update-dependency',
+        '--pub-package',
+        'pigeon',
+        '--version',
+        '1.5.0',
+      ], errorHandler: (Error e) {
+        commandError = e;
+      });
+
+      expect(commandError, isA<ToolExit>());
+      expect(
+        output,
+        containsAllInOrder(<Matcher>[
+          contains('dart run pigeon failed'),
+          contains('Failed to update pigeon files'),
+        ]),
+      );
+    });
   });
 }
diff --git a/script/tool/test/update_excerpts_command_test.dart b/script/tool/test/update_excerpts_command_test.dart
index 5a2f0f3404..193001fed6 100644
--- a/script/tool/test/update_excerpts_command_test.dart
+++ b/script/tool/test/update_excerpts_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -130,8 +128,8 @@ void main() {
     final RepositoryPackage package = createFakePlugin('a_package', packagesDir,
         extraFiles: <String>[kReadmeExcerptConfigPath]);
 
-    processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-      MockProcess(exitCode: 1), // dart pub get
+    processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'get'])
     ];
 
     Error? commandError;
@@ -161,8 +159,8 @@ void main() {
     createFakePlugin('a_package', packagesDir,
         extraFiles: <String>[kReadmeExcerptConfigPath]);
 
-    processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-      MockProcess(exitCode: 1), // dart pub get
+    processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['pub', 'get'])
     ];
 
     Error? commandError;
@@ -185,9 +183,9 @@ void main() {
     createFakePlugin('a_package', packagesDir,
         extraFiles: <String>[kReadmeExcerptConfigPath]);
 
-    processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-      MockProcess(), // dart pub get
-      MockProcess(exitCode: 1), // dart run build_runner ...
+    processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(), <String>['pub', 'get']),
+      FakeProcessInfo(MockProcess(exitCode: 1), <String>['run', 'build_runner'])
     ];
 
     Error? commandError;
@@ -210,10 +208,11 @@ void main() {
     createFakePlugin('a_package', packagesDir,
         extraFiles: <String>[kReadmeExcerptConfigPath]);
 
-    processRunner.mockProcessesForExecutable['dart'] = <io.Process>[
-      MockProcess(), // dart pub get
-      MockProcess(), // dart run build_runner ...
-      MockProcess(exitCode: 1), // dart run code_excerpt_updater ...
+    processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(), <String>['pub', 'get']),
+      FakeProcessInfo(MockProcess(), <String>['run', 'build_runner']),
+      FakeProcessInfo(
+          MockProcess(exitCode: 1), <String>['run', 'code_excerpt_updater']),
     ];
 
     Error? commandError;
@@ -237,8 +236,8 @@ void main() {
         extraFiles: <String>[kReadmeExcerptConfigPath]);
 
     const String changedFilePath = 'packages/a_plugin/README.md';
-    processRunner.mockProcessesForExecutable['git'] = <io.Process>[
-      MockProcess(stdout: changedFilePath),
+    processRunner.mockProcessesForExecutable['git'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFilePath)),
     ];
 
     Error? commandError;
@@ -263,8 +262,8 @@ void main() {
         extraFiles: <String>[kReadmeExcerptConfigPath]);
 
     const String changedFilePath = 'packages/a_plugin/linux/CMakeLists.txt';
-    processRunner.mockProcessesForExecutable['git'] = <io.Process>[
-      MockProcess(stdout: changedFilePath),
+    processRunner.mockProcessesForExecutable['git'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(stdout: changedFilePath)),
     ];
 
     final List<String> output = await runCapturingPrint(
@@ -281,8 +280,8 @@ void main() {
     createFakePlugin('a_plugin', packagesDir,
         extraFiles: <String>[kReadmeExcerptConfigPath]);
 
-    processRunner.mockProcessesForExecutable['git'] = <io.Process>[
-      MockProcess(exitCode: 1)
+    processRunner.mockProcessesForExecutable['git'] = <FakeProcessInfo>[
+      FakeProcessInfo(MockProcess(exitCode: 1))
     ];
     Error? commandError;
     final List<String> output = await runCapturingPrint(
diff --git a/script/tool/test/update_release_info_command_test.dart b/script/tool/test/update_release_info_command_test.dart
index cfec93823f..0981a85f62 100644
--- a/script/tool/test/update_release_info_command_test.dart
+++ b/script/tool/test/update_release_info_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -386,10 +384,10 @@ $originalChangelog''';
     test('skips for "minimal" when there are no changes at all', () async {
       final RepositoryPackage package =
           createFakePackage('a_package', packagesDir, version: '1.0.1');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: '''
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: '''
 packages/different_package/lib/foo.dart
-'''),
+''')),
       ];
       final String originalChangelog = package.changelogFile.readAsStringSync();
 
@@ -414,11 +412,11 @@ packages/different_package/lib/foo.dart
     test('skips for "minimal" when there are only test changes', () async {
       final RepositoryPackage package =
           createFakePackage('a_package', packagesDir, version: '1.0.1');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: '''
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: '''
 packages/a_package/test/a_test.dart
 packages/a_package/example/integration_test/another_test.dart
-'''),
+''')),
       ];
       final String originalChangelog = package.changelogFile.readAsStringSync();
 
@@ -609,10 +607,10 @@ Some free-form text that isn't a list.
         () async {
       final RepositoryPackage package =
           createFakePackage('a_package', packagesDir, version: '1.0.1');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: '''
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: '''
 packages/a_package/lib/plugin.dart
-'''),
+''')),
       ];
 
       final List<String> output = await runCapturingPrint(runner, <String>[
@@ -634,10 +632,10 @@ packages/a_package/lib/plugin.dart
         () async {
       final RepositoryPackage package =
           createFakePackage('a_package', packagesDir, version: '1.0.1');
-      processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-        MockProcess(stdout: '''
+      processRunner.mockProcessesForExecutable['git-diff'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: '''
 packages/a_package/test/plugin_test.dart
-'''),
+''')),
       ];
 
       await runCapturingPrint(runner, <String>[
diff --git a/script/tool/test/util.dart b/script/tool/test/util.dart
index 7d50b41e6c..f19355f289 100644
--- a/script/tool/test/util.dart
+++ b/script/tool/test/util.dart
@@ -364,14 +364,37 @@ Future<List<String>> runCapturingPrint(
   return prints;
 }
 
+/// Information about a process to return from [RecordingProcessRunner].
+class FakeProcessInfo {
+  const FakeProcessInfo(this.process,
+      [this.expectedInitialArgs = const <String>[]]);
+
+  /// The process to return.
+  final io.Process process;
+
+  /// The expected start of the argument array for the call.
+  ///
+  /// This does not have to be a full list of arguments, only enough of the
+  /// start to ensure that the call is as expected.
+  final List<String> expectedInitialArgs;
+}
+
 /// A mock [ProcessRunner] which records process calls.
 class RecordingProcessRunner extends ProcessRunner {
   final List<ProcessCall> recordedCalls = <ProcessCall>[];
 
   /// Maps an executable to a list of processes that should be used for each
   /// successive call to it via [run], [runAndStream], or [start].
-  final Map<String, List<io.Process>> mockProcessesForExecutable =
-      <String, List<io.Process>>{};
+  ///
+  /// If `expectedInitialArgs` are provided for a fake process, trying to
+  /// return that process when the arguments don't match will throw a
+  /// [StateError]. This allows tests to enforce that the fake results are
+  /// for the expected calls when the process name itself isn't enough to tell
+  /// (e.g., multiple different `dart` or `flutter` calls), without going all
+  /// the way to a complex argument matching scheme that can make tests
+  /// difficult to write and debug.
+  final Map<String, List<FakeProcessInfo>> mockProcessesForExecutable =
+      <String, List<FakeProcessInfo>>{};
 
   @override
   Future<int> runAndStream(
@@ -381,7 +404,7 @@ class RecordingProcessRunner extends ProcessRunner {
     bool exitOnError = false,
   }) async {
     recordedCalls.add(ProcessCall(executable, args, workingDir?.path));
-    final io.Process? processToReturn = _getProcessToReturn(executable);
+    final io.Process? processToReturn = _getProcessToReturn(executable, args);
     final int exitCode =
         processToReturn == null ? 0 : await processToReturn.exitCode;
     if (exitOnError && (exitCode != 0)) {
@@ -403,7 +426,7 @@ class RecordingProcessRunner extends ProcessRunner {
   }) async {
     recordedCalls.add(ProcessCall(executable, args, workingDir?.path));
 
-    final io.Process? process = _getProcessToReturn(executable);
+    final io.Process? process = _getProcessToReturn(executable, args);
     final List<String>? processStdout =
         await process?.stdout.transform(stdoutEncoding.decoder).toList();
     final String stdout = processStdout?.join() ?? '';
@@ -427,13 +450,22 @@ class RecordingProcessRunner extends ProcessRunner {
       {Directory? workingDirectory}) async {
     recordedCalls.add(ProcessCall(executable, args, workingDirectory?.path));
     return Future<io.Process>.value(
-        _getProcessToReturn(executable) ?? MockProcess());
+        _getProcessToReturn(executable, args) ?? MockProcess());
   }
 
-  io.Process? _getProcessToReturn(String executable) {
-    final List<io.Process>? processes = mockProcessesForExecutable[executable];
-    if (processes != null && processes.isNotEmpty) {
-      return processes.removeAt(0);
+  io.Process? _getProcessToReturn(String executable, List<String> args) {
+    final List<FakeProcessInfo> fakes =
+        mockProcessesForExecutable[executable] ?? <FakeProcessInfo>[];
+    if (fakes.isNotEmpty) {
+      final FakeProcessInfo fake = fakes.removeAt(0);
+      if (args.length < fake.expectedInitialArgs.length ||
+          !listsEqual(args.sublist(0, fake.expectedInitialArgs.length),
+              fake.expectedInitialArgs)) {
+        throw StateError('Next fake process for $executable expects arguments '
+            '[${fake.expectedInitialArgs.join(', ')}] but was called with '
+            'arguments [${args.join(', ')}]');
+      }
+      return fake.process;
     }
     return null;
   }
diff --git a/script/tool/test/version_check_command_test.dart b/script/tool/test/version_check_command_test.dart
index 3346383fd3..b614d8cef5 100644
--- a/script/tool/test/version_check_command_test.dart
+++ b/script/tool/test/version_check_command_test.dart
@@ -95,8 +95,8 @@ void main() {
 
     test('allows valid version', () async {
       createFakePlugin('plugin', packagesDir, version: '2.0.0');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
       final List<String> output = await runCapturingPrint(
           runner, <String>['version-check', '--base-sha=main']);
@@ -118,8 +118,8 @@ void main() {
 
     test('denies invalid version', () async {
       createFakePlugin('plugin', packagesDir, version: '0.2.0');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 0.0.1'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 0.0.1')),
       ];
       Error? commandError;
       final List<String> output = await runCapturingPrint(
@@ -144,12 +144,13 @@ void main() {
 
     test('uses merge-base without explicit base-sha', () async {
       createFakePlugin('plugin', packagesDir, version: '2.0.0');
-      processRunner.mockProcessesForExecutable['git-merge-base'] = <io.Process>[
-        MockProcess(stdout: 'abc123'),
-        MockProcess(stdout: 'abc123'),
+      processRunner.mockProcessesForExecutable['git-merge-base'] =
+          <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'abc123')),
+        FakeProcessInfo(MockProcess(stdout: 'abc123')),
       ];
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
       final List<String> output =
           await runCapturingPrint(runner, <String>['version-check']);
@@ -187,8 +188,8 @@ void main() {
 
     test('allows likely reverts.', () async {
       createFakePlugin('plugin', packagesDir, version: '0.6.1');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 0.6.2'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 0.6.2')),
       ];
       final List<String> output = await runCapturingPrint(
           runner, <String>['version-check', '--base-sha=main']);
@@ -210,8 +211,8 @@ void main() {
 
     test('denies lower version that could not be a simple revert', () async {
       createFakePlugin('plugin', packagesDir, version: '0.5.1');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 0.6.2'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 0.6.2')),
       ];
 
       Error? commandError;
@@ -238,8 +239,8 @@ void main() {
     test('allows minor changes to platform interfaces', () async {
       createFakePlugin('plugin_platform_interface', packagesDir,
           version: '1.1.0');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
       final List<String> output = await runCapturingPrint(
           runner, <String>['version-check', '--base-sha=main']);
@@ -266,8 +267,8 @@ void main() {
         () async {
       createFakePlugin('plugin_platform_interface', packagesDir,
           version: '2.0.0');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
       Error? commandError;
       final List<String> output = await runCapturingPrint(
@@ -302,8 +303,8 @@ void main() {
         () async {
       createFakePlugin('plugin_platform_interface', packagesDir,
           version: '2.0.0');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
 
       final List<String> output = await runCapturingPrint(runner, <String>[
@@ -336,8 +337,8 @@ void main() {
         () async {
       createFakePlugin('plugin_platform_interface', packagesDir,
           version: '2.0.0');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
       final List<String> output = await runCapturingPrint(runner, <String>[
         'version-check',
@@ -473,8 +474,8 @@ void main() {
 * Some other changes.
 ''';
       plugin.changelogFile.writeAsStringSync(changelog);
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
 
       final List<String> output = await runCapturingPrint(
@@ -525,8 +526,8 @@ void main() {
       const String version = '1.0.1';
       final RepositoryPackage plugin =
           createFakePlugin('plugin', packagesDir, version: version);
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
 
       const String changelog = '''
@@ -562,8 +563,8 @@ void main() {
     test('fails if the version increases without replacing NEXT', () async {
       final RepositoryPackage plugin =
           createFakePlugin('plugin', packagesDir, version: '1.0.1');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
 
       const String changelog = '''
@@ -604,8 +605,8 @@ void main() {
 ''';
       plugin.changelogFile.writeAsStringSync(changelog);
       plugin.changelogFile.writeAsStringSync(changelog);
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.1'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.1')),
       ];
 
       final List<String> output = await runCapturingPrint(
@@ -656,8 +657,8 @@ void main() {
 * Some other changes.
 ''';
       plugin.changelogFile.writeAsStringSync(changelog);
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
 
       Error? commandError;
@@ -689,8 +690,8 @@ void main() {
 * Some changes.
 ''';
       plugin.changelogFile.writeAsStringSync(changelog);
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
 
       Error? commandError;
@@ -733,11 +734,13 @@ void main() {
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-          MockProcess(stdout: ''),
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '')),
         ];
 
         final List<String> output =
@@ -762,13 +765,15 @@ void main() {
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin/lib/plugin.dart
-'''),
+''')),
         ];
 
         Error? commandError;
@@ -797,15 +802,17 @@ packages/plugin/lib/plugin.dart
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin/lib/plugin.dart
 packages/plugin/CHANGELOG.md
 packages/plugin/pubspec.yaml
-'''),
+''')),
         ];
 
         final List<String> output =
@@ -828,14 +835,16 @@ packages/plugin/pubspec.yaml
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin_a/lib/plugin.dart
 tool/plugin/lib/plugin.dart
-'''),
+''')),
         ];
 
         final List<String> output =
@@ -858,17 +867,19 @@ tool/plugin/lib/plugin.dart
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin/example/android/lint-baseline.xml
 packages/plugin/example/android/src/androidTest/foo/bar/FooTest.java
 packages/plugin/example/ios/RunnerTests/Foo.m
 packages/plugin/example/ios/RunnerUITests/info.plist
 packages/plugin/CHANGELOG.md
-'''),
+''')),
         ];
 
         final List<String> output =
@@ -891,15 +902,17 @@ packages/plugin/CHANGELOG.md
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin/lib/plugin.dart
 packages/plugin/CHANGELOG.md
 packages/plugin/pubspec.yaml
-'''),
+''')),
         ];
 
         final List<String> output =
@@ -925,13 +938,15 @@ packages/plugin/pubspec.yaml
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin/example/lib/foo.dart
-'''),
+''')),
         ];
 
         Error? commandError;
@@ -960,14 +975,16 @@ packages/plugin/example/lib/foo.dart
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin/example/lib/foo.dart
 packages/plugin/CHANGELOG.md
-'''),
+''')),
         ];
 
         final List<String> output =
@@ -991,14 +1008,16 @@ packages/plugin/CHANGELOG.md
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin/example/lib/foo.dart
 packages/another_plugin/CHANGELOG.md
-'''),
+''')),
         ];
 
         Error? commandError;
@@ -1025,13 +1044,15 @@ packages/another_plugin/CHANGELOG.md
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
-          MockProcess(stdout: '''
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin/example/lib/foo.dart
-'''),
+''')),
         ];
 
         final List<String> output =
@@ -1061,21 +1082,23 @@ packages/plugin/example/lib/foo.dart
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
           // File list.
-          MockProcess(stdout: '''
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin/android/build.gradle
-'''),
+''')),
           // build.gradle diff
-          MockProcess(stdout: '''
+          FakeProcessInfo(MockProcess(stdout: '''
 -  androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
 -  testImplementation 'junit:junit:4.10.0'
 +  androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
 +  testImplementation 'junit:junit:4.13.2'
-'''),
+''')),
         ];
 
         final List<String> output =
@@ -1099,15 +1122,17 @@ packages/plugin/android/build.gradle
 * Some changes.
 ''';
         plugin.changelogFile.writeAsStringSync(changelog);
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
-        processRunner.mockProcessesForExecutable['git-diff'] = <io.Process>[
+        processRunner.mockProcessesForExecutable['git-diff'] =
+            <FakeProcessInfo>[
           // File list.
-          MockProcess(stdout: '''
+          FakeProcessInfo(MockProcess(stdout: '''
 packages/plugin/tool/run_tests.dart
 packages/plugin/run_tests.sh
-'''),
+''')),
         ];
 
         final List<String> output =
@@ -1207,8 +1232,8 @@ ${indentation}HTTP response: null
       mockHttpStatus = 404;
 
       createFakePlugin('plugin', packagesDir, version: '2.0.0');
-      processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-        MockProcess(stdout: 'version: 1.0.0'),
+      processRunner.mockProcessesForExecutable['git-show'] = <FakeProcessInfo>[
+        FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
       ];
       final List<String> result = await runCapturingPrint(runner,
           <String>['version-check', '--base-sha=main', '--against-pub']);
@@ -1226,8 +1251,9 @@ ${indentation}HTTP response: null
           'allow an otherwise-valid transition that also adds a pre-release component',
           () async {
         createFakePlugin('plugin', packagesDir, version: '2.0.0-dev');
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.0.0'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.0.0')),
         ];
         final List<String> output = await runCapturingPrint(
             runner, <String>['version-check', '--base-sha=main']);
@@ -1249,8 +1275,9 @@ ${indentation}HTTP response: null
 
       test('allow releasing a pre-release', () async {
         createFakePlugin('plugin', packagesDir, version: '1.2.0');
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.2.0-dev'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.2.0-dev')),
         ];
         final List<String> output = await runCapturingPrint(
             runner, <String>['version-check', '--base-sha=main']);
@@ -1276,8 +1303,9 @@ ${indentation}HTTP response: null
           'allow an otherwise-valid transition that also removes a pre-release component',
           () async {
         createFakePlugin('plugin', packagesDir, version: '2.0.0');
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.2.0-dev'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.2.0-dev')),
         ];
         final List<String> output = await runCapturingPrint(
             runner, <String>['version-check', '--base-sha=main']);
@@ -1299,8 +1327,9 @@ ${indentation}HTTP response: null
 
       test('allow changing only the pre-release version', () async {
         createFakePlugin('plugin', packagesDir, version: '1.2.0-dev.2');
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 1.2.0-dev.1'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 1.2.0-dev.1')),
         ];
         final List<String> output = await runCapturingPrint(
             runner, <String>['version-check', '--base-sha=main']);
@@ -1323,8 +1352,9 @@ ${indentation}HTTP response: null
       test('denies invalid version change that also adds a pre-release',
           () async {
         createFakePlugin('plugin', packagesDir, version: '0.2.0-dev');
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 0.0.1'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 0.0.1')),
         ];
         Error? commandError;
         final List<String> output = await runCapturingPrint(
@@ -1350,8 +1380,9 @@ ${indentation}HTTP response: null
       test('denies invalid version change that also removes a pre-release',
           () async {
         createFakePlugin('plugin', packagesDir, version: '0.2.0');
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 0.0.1-dev'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 0.0.1-dev')),
         ];
         Error? commandError;
         final List<String> output = await runCapturingPrint(
@@ -1376,8 +1407,9 @@ ${indentation}HTTP response: null
 
       test('denies invalid version change between pre-releases', () async {
         createFakePlugin('plugin', packagesDir, version: '0.2.0-dev');
-        processRunner.mockProcessesForExecutable['git-show'] = <io.Process>[
-          MockProcess(stdout: 'version: 0.0.1-dev'),
+        processRunner.mockProcessesForExecutable['git-show'] =
+            <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(stdout: 'version: 0.0.1-dev')),
         ];
         Error? commandError;
         final List<String> output = await runCapturingPrint(
diff --git a/script/tool/test/xcode_analyze_command_test.dart b/script/tool/test/xcode_analyze_command_test.dart
index 418c695f29..2caf906fc6 100644
--- a/script/tool/test/xcode_analyze_command_test.dart
+++ b/script/tool/test/xcode_analyze_command_test.dart
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'dart:io' as io;
-
 import 'package:args/command_runner.dart';
 import 'package:file/file.dart';
 import 'package:file/memory.dart';
@@ -170,8 +168,8 @@ void main() {
               platformIOS: const PlatformDetails(PlatformSupport.inline)
             });
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-          MockProcess(exitCode: 1)
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(exitCode: 1))
         ];
 
         Error? commandError;
@@ -300,8 +298,8 @@ void main() {
               platformMacOS: const PlatformDetails(PlatformSupport.inline),
             });
 
-        processRunner.mockProcessesForExecutable['xcrun'] = <io.Process>[
-          MockProcess(exitCode: 1)
+        processRunner.mockProcessesForExecutable['xcrun'] = <FakeProcessInfo>[
+          FakeProcessInfo(MockProcess(exitCode: 1))
         ];
 
         Error? commandError;