[tools] Switch to `flutter test` (#4348)
For non-web platforms, `flutter drive` is deprecated. This switches those platforms from `flutter drive` to `flutter test`. This makes the logic to check for test driver files web-specific, since `flutter test` doesn't require a driver.
Removes support for the legacy test-in-test_driver-directory structure, which is no longer used anywhere in the repository.
Also includes a minor drive-by fix to the way we do process output, noticed while manually testing. Instead of adding all stdout, and only then adding all stderr, this adds both then waits for both, which should allow interleaving of stdout and stderr in the terminal.
Fixes https://github.com/flutter/flutter/issues/105634
diff --git a/script/tool/lib/src/common/process_runner.dart b/script/tool/lib/src/common/process_runner.dart
index 429761e..7556b55 100644
--- a/script/tool/lib/src/common/process_runner.dart
+++ b/script/tool/lib/src/common/process_runner.dart
@@ -36,8 +36,10 @@
'Running command: "$executable ${args.join(' ')}" in ${workingDir?.path ?? io.Directory.current.path}');
final io.Process process = await io.Process.start(executable, args,
workingDirectory: workingDir?.path);
- await io.stdout.addStream(process.stdout);
- await io.stderr.addStream(process.stderr);
+ await Future.wait(<Future<dynamic>>[
+ io.stdout.addStream(process.stdout),
+ io.stderr.addStream(process.stderr),
+ ]);
if (exitOnError && await process.exitCode != 0) {
final String error =
_getErrorString(executable, args, workingDir: workingDir);
diff --git a/script/tool/lib/src/drive_examples_command.dart b/script/tool/lib/src/drive_examples_command.dart
index 279fdce..9bbfd35 100644
--- a/script/tool/lib/src/drive_examples_command.dart
+++ b/script/tool/lib/src/drive_examples_command.dart
@@ -17,7 +17,7 @@
const int _exitNoPlatformFlags = 2;
const int _exitNoAvailableDevice = 3;
-/// A command to run the example applications for packages via Flutter driver.
+/// A command to run the integration tests for a package's example applications.
class DriveExamplesCommand extends PackageLoopingCommand {
/// Creates an instance of the drive command.
DriveExamplesCommand(
@@ -50,11 +50,9 @@
final String name = 'drive-examples';
@override
- final String description = 'Runs driver tests for package example apps.\n\n'
- 'For each *_test.dart in test_driver/ it drives an application with '
- 'either the corresponding test in test_driver (for example, '
- 'test_driver/app_test.dart would match test_driver/app.dart), or the '
- '*_test.dart files in integration_test/.\n\n'
+ final String description = 'Runs Dart integration tests for example apps.\n\n'
+ "This runs all tests in each example's integration_test directory, "
+ 'via "flutter test" on most platforms, and "flutter drive" on web.\n\n'
'This command requires "flutter" to be in your path.';
Map<String, List<String>> _targetDeviceFlags = const <String, List<String>>{};
@@ -164,53 +162,53 @@
'Skipping $exampleName; does not support any requested platforms.');
continue;
}
+
++supportedExamplesFound;
- final List<File> drivers = await _getDrivers(example);
- if (drivers.isEmpty) {
- print('No driver tests found for $exampleName');
+ final List<File> testTargets = await _getIntegrationTests(example);
+ if (testTargets.isEmpty) {
+ print('No integration_test/*.dart files found for $exampleName.');
continue;
}
- for (final File driver in drivers) {
- final List<File> testTargets = <File>[];
+ // Check files for known problematic patterns.
+ testTargets
+ .where((File file) => !_validateIntegrationTest(file))
+ .forEach((File file) {
+ // Report the issue, but continue with the test as the validation
+ // errors don't prevent running.
+ errors.add('${file.basename} failed validation');
+ });
- // Try to find a matching app to drive without the _test.dart
- // TODO(stuartmorgan): Migrate all remaining uses of this legacy
- // approach (currently only video_player) and remove support for it:
- // https://github.com/flutter/flutter/issues/85224.
- final File? legacyTestFile = _getLegacyTestFileForTestDriver(driver);
- if (legacyTestFile != null) {
- testTargets.add(legacyTestFile);
- } else {
- for (final File testFile in await _getIntegrationTests(example)) {
- // Check files for known problematic patterns.
- final bool passesValidation = _validateIntegrationTest(testFile);
- if (!passesValidation) {
- // Report the issue, but continue with the test as the validation
- // errors don't prevent running.
- errors.add('${testFile.basename} failed validation');
- }
- testTargets.add(testFile);
- }
- }
+ // `flutter test` doesn't yet support web integration tests, so fall back
+ // to `flutter drive`.
+ final bool useFlutterDrive = getBoolArg(platformWeb);
- if (testTargets.isEmpty) {
- final String driverRelativePath =
- getRelativePosixPath(driver, from: package.directory);
- printError(
- 'Found $driverRelativePath, but no integration_test/*_test.dart files.');
- errors.add('No test files for $driverRelativePath');
+ final List<File> drivers;
+ if (useFlutterDrive) {
+ drivers = await _getDrivers(example);
+ if (drivers.isEmpty) {
+ print('No driver found for $exampleName');
continue;
}
+ } else {
+ drivers = <File>[];
+ }
- testsRan = true;
- final List<File> failingTargets = await _driveTests(
- example, driver, testTargets,
- deviceFlags: deviceFlags);
- for (final File failingTarget in failingTargets) {
- errors.add(
- getRelativePosixPath(failingTarget, from: package.directory));
+ testsRan = true;
+ if (useFlutterDrive) {
+ for (final File driver in drivers) {
+ final List<File> failingTargets = await _driveTests(
+ example, driver, testTargets,
+ deviceFlags: deviceFlags);
+ for (final File failingTarget in failingTargets) {
+ errors.add(
+ getRelativePosixPath(failingTarget, from: package.directory));
+ }
+ }
+ } else {
+ if (!await _runTests(example, deviceFlags: deviceFlags)) {
+ errors.add('Integration tests failed.');
}
}
}
@@ -224,7 +222,7 @@
} else {
return PackageResult.skip(supportedExamplesFound == 0
? 'No example supports requested platform(s).'
- : 'No example is configured for driver tests.');
+ : 'No example is configured for integration tests.');
}
}
return errors.isEmpty
@@ -295,16 +293,6 @@
return drivers;
}
- File? _getLegacyTestFileForTestDriver(File testDriver) {
- final String testName = testDriver.basename.replaceAll(
- RegExp(r'_test.dart$'),
- '.dart',
- );
- final File testFile = testDriver.parent.childFile(testName);
-
- return testFile.existsSync() ? testFile : null;
- }
-
Future<List<File>> _getIntegrationTests(RepositoryPackage example) async {
final List<File> tests = <File>[];
final Directory integrationTestDir =
@@ -378,4 +366,31 @@
}
return failures;
}
+
+ /// Uses `flutter test integration_test` to run [example], returning the
+ /// success of the test run.
+ ///
+ /// [deviceFlags] should contain the flags to run the test on a specific
+ /// target device (plus any supporting device-specific flags). E.g.:
+ /// - `['-d', 'macos']` for driving for macOS.
+ /// - `['-d', 'web-server', '--web-port=<port>', '--browser-name=<browser>]`
+ /// for web
+ Future<bool> _runTests(
+ RepositoryPackage example, {
+ required List<String> deviceFlags,
+ }) async {
+ final String enableExperiment = getStringArg(kEnableExperiment);
+
+ final int exitCode = await processRunner.runAndStream(
+ flutterCommand,
+ <String>[
+ 'test',
+ ...deviceFlags,
+ if (enableExperiment.isNotEmpty)
+ '--enable-experiment=$enableExperiment',
+ 'integration_test',
+ ],
+ workingDir: example.directory);
+ return exitCode == 0;
+ }
}
diff --git a/script/tool/test/drive_examples_command_test.dart b/script/tool/test/drive_examples_command_test.dart
index 81056db..203d525 100644
--- a/script/tool/test/drive_examples_command_test.dart
+++ b/script/tool/test/drive_examples_command_test.dart
@@ -190,91 +190,6 @@
);
});
- test('driving under folder "test_driver"', () async {
- final RepositoryPackage plugin = createFakePlugin(
- 'plugin',
- packagesDir,
- extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
- 'example/android/android.java',
- 'example/ios/ios.m',
- ],
- platformSupport: <String, PlatformDetails>{
- platformAndroid: const PlatformDetails(PlatformSupport.inline),
- platformIOS: const PlatformDetails(PlatformSupport.inline),
- },
- );
-
- final Directory pluginExampleDirectory = getExampleDir(plugin);
-
- setMockFlutterDevicesOutput();
- final List<String> output =
- await runCapturingPrint(runner, <String>['drive-examples', '--ios']);
-
- expect(
- output,
- containsAllInOrder(<Matcher>[
- contains('Running for plugin'),
- contains('No issues found!'),
- ]),
- );
-
- expect(
- processRunner.recordedCalls,
- orderedEquals(<ProcessCall>[
- ProcessCall(getFlutterCommand(mockPlatform),
- const <String>['devices', '--machine'], null),
- ProcessCall(
- getFlutterCommand(mockPlatform),
- const <String>[
- 'drive',
- '-d',
- _fakeIOSDevice,
- '--driver',
- 'test_driver/plugin_test.dart',
- '--target',
- 'test_driver/plugin.dart'
- ],
- pluginExampleDirectory.path),
- ]));
- });
-
- test('driving under folder "test_driver" when test files are missing"',
- () async {
- setMockFlutterDevicesOutput();
- createFakePlugin(
- 'plugin',
- packagesDir,
- extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/android/android.java',
- 'example/ios/ios.m',
- ],
- platformSupport: <String, PlatformDetails>{
- platformAndroid: const PlatformDetails(PlatformSupport.inline),
- platformIOS: const PlatformDetails(PlatformSupport.inline),
- },
- );
-
- Error? commandError;
- final List<String> output = await runCapturingPrint(
- runner, <String>['drive-examples', '--android'],
- errorHandler: (Error e) {
- commandError = e;
- });
-
- expect(commandError, isA<ToolExit>());
- expect(
- output,
- containsAllInOrder(<Matcher>[
- contains('Running for plugin'),
- contains('No driver tests were run (1 example(s) found).'),
- contains('No test files for example/test_driver/plugin_test.dart'),
- ]),
- );
- });
-
test('a plugin without any integration test files is reported as an error',
() async {
setMockFlutterDevicesOutput();
@@ -351,14 +266,11 @@
);
});
- test(
- 'driving under folder "test_driver" when targets are under "integration_test"',
- () async {
+ test('tests an iOS plugin', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/integration_test.dart',
'example/integration_test/bar_test.dart',
'example/integration_test/foo_test.dart',
'example/integration_test/ignore_me.dart',
@@ -393,25 +305,10 @@
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
- 'drive',
+ 'test',
'-d',
_fakeIOSDevice,
- '--driver',
- 'test_driver/integration_test.dart',
- '--target',
- 'integration_test/bar_test.dart',
- ],
- pluginExampleDirectory.path),
- ProcessCall(
- getFlutterCommand(mockPlatform),
- const <String>[
- 'drive',
- '-d',
- _fakeIOSDevice,
- '--driver',
- 'test_driver/integration_test.dart',
- '--target',
- 'integration_test/foo_test.dart',
+ 'integration_test',
],
pluginExampleDirectory.path),
]));
@@ -419,8 +316,7 @@
test('driving when plugin does not support Linux is a no-op', () async {
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
]);
final List<String> output = await runCapturingPrint(runner, <String>[
@@ -442,13 +338,12 @@
expect(processRunner.recordedCalls, <ProcessCall>[]);
});
- test('driving on a Linux plugin', () async {
+ test('tests a Linux plugin', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
'example/linux/linux.cc',
],
platformSupport: <String, PlatformDetails>{
@@ -477,13 +372,10 @@
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
- 'drive',
+ 'test',
'-d',
'linux',
- '--driver',
- 'test_driver/plugin_test.dart',
- '--target',
- 'test_driver/plugin.dart'
+ 'integration_test',
],
pluginExampleDirectory.path),
]));
@@ -491,8 +383,7 @@
test('driving when plugin does not suppport macOS is a no-op', () async {
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
]);
final List<String> output = await runCapturingPrint(runner, <String>[
@@ -514,13 +405,12 @@
expect(processRunner.recordedCalls, <ProcessCall>[]);
});
- test('driving on a macOS plugin', () async {
+ test('tests a macOS plugin', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
'example/macos/macos.swift',
],
platformSupport: <String, PlatformDetails>{
@@ -549,13 +439,10 @@
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
- 'drive',
+ 'test',
'-d',
'macos',
- '--driver',
- 'test_driver/plugin_test.dart',
- '--target',
- 'test_driver/plugin.dart'
+ 'integration_test',
],
pluginExampleDirectory.path),
]));
@@ -563,8 +450,7 @@
test('driving when plugin does not suppport web is a no-op', () async {
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
]);
final List<String> output = await runCapturingPrint(runner, <String>[
@@ -585,13 +471,13 @@
expect(processRunner.recordedCalls, <ProcessCall>[]);
});
- test('driving a web plugin', () async {
+ test('drives a web plugin', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
+ 'example/test_driver/integration_test.dart',
'example/web/index.html',
],
platformSupport: <String, PlatformDetails>{
@@ -626,21 +512,21 @@
'--web-port=7357',
'--browser-name=chrome',
'--driver',
- 'test_driver/plugin_test.dart',
+ 'test_driver/integration_test.dart',
'--target',
- 'test_driver/plugin.dart'
+ 'integration_test/plugin_test.dart',
],
pluginExampleDirectory.path),
]));
});
- test('driving a web plugin with CHROME_EXECUTABLE', () async {
+ test('drives a web plugin with CHROME_EXECUTABLE', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
+ 'example/test_driver/integration_test.dart',
'example/web/index.html',
],
platformSupport: <String, PlatformDetails>{
@@ -678,9 +564,9 @@
'--browser-name=chrome',
'--chrome-binary=/path/to/chrome',
'--driver',
- 'test_driver/plugin_test.dart',
+ 'test_driver/integration_test.dart',
'--target',
- 'test_driver/plugin.dart'
+ 'integration_test/plugin_test.dart',
],
pluginExampleDirectory.path),
]));
@@ -688,8 +574,7 @@
test('driving when plugin does not suppport Windows is a no-op', () async {
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
]);
final List<String> output = await runCapturingPrint(runner, <String>[
@@ -711,13 +596,12 @@
expect(processRunner.recordedCalls, <ProcessCall>[]);
});
- test('driving on a Windows plugin', () async {
+ test('tests a Windows plugin', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
'example/windows/windows.cpp',
],
platformSupport: <String, PlatformDetails>{
@@ -746,25 +630,21 @@
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
- 'drive',
+ 'test',
'-d',
'windows',
- '--driver',
- 'test_driver/plugin_test.dart',
- '--target',
- 'test_driver/plugin.dart'
+ 'integration_test',
],
pluginExampleDirectory.path),
]));
});
- test('driving on an Android plugin', () async {
+ test('tests an Android plugin', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
'example/android/android.java',
],
platformSupport: <String, PlatformDetails>{
@@ -796,25 +676,21 @@
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
- 'drive',
+ 'test',
'-d',
_fakeAndroidDevice,
- '--driver',
- 'test_driver/plugin_test.dart',
- '--target',
- 'test_driver/plugin.dart'
+ 'integration_test',
],
pluginExampleDirectory.path),
]));
});
- test('driving on an Android plugin with alias', () async {
+ test('tests an Android plugin with "apk" alias', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
'example/android/android.java',
],
platformSupport: <String, PlatformDetails>{
@@ -846,13 +722,10 @@
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
- 'drive',
+ 'test',
'-d',
_fakeAndroidDevice,
- '--driver',
- 'test_driver/plugin_test.dart',
- '--target',
- 'test_driver/plugin.dart'
+ 'integration_test',
],
pluginExampleDirectory.path),
]));
@@ -863,8 +736,7 @@
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
],
platformSupport: <String, PlatformDetails>{
platformMacOS: const PlatformDetails(PlatformSupport.inline),
@@ -896,8 +768,7 @@
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
],
platformSupport: <String, PlatformDetails>{
platformMacOS: const PlatformDetails(PlatformSupport.inline),
@@ -951,8 +822,7 @@
'plugin',
packagesDir,
extraFiles: <String>[
- 'example/test_driver/plugin_test.dart',
- 'example/test_driver/plugin.dart',
+ 'example/integration_test/plugin_test.dart',
'example/android/android.java',
'example/ios/ios.m',
],
@@ -979,14 +849,11 @@
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
- 'drive',
+ 'test',
'-d',
_fakeIOSDevice,
'--enable-experiment=exp1',
- '--driver',
- 'test_driver/plugin_test.dart',
- '--target',
- 'test_driver/plugin.dart'
+ 'integration_test',
],
pluginExampleDirectory.path),
]));
@@ -1021,7 +888,7 @@
);
});
- test('fails when no driver is present', () async {
+ test('web fails when no driver is present', () async {
createFakePlugin(
'plugin',
packagesDir,
@@ -1046,7 +913,7 @@
output,
containsAllInOrder(<Matcher>[
contains('Running for plugin'),
- contains('No driver tests found for plugin/example'),
+ contains('No driver found for plugin/example'),
contains('No driver tests were run (1 example(s) found).'),
contains('The following packages had errors:'),
contains(' plugin:\n'
@@ -1055,7 +922,7 @@
);
});
- test('fails when no integration tests are present', () async {
+ test('web fails when no integration tests are present', () async {
createFakePlugin(
'plugin',
packagesDir,
@@ -1079,18 +946,15 @@
output,
containsAllInOrder(<Matcher>[
contains('Running for plugin'),
- contains('Found example/test_driver/integration_test.dart, but no '
- 'integration_test/*_test.dart files.'),
contains('No driver tests were run (1 example(s) found).'),
contains('The following packages had errors:'),
contains(' plugin:\n'
- ' No test files for example/test_driver/integration_test.dart\n'
' No tests ran (use --exclude if this is intentional)'),
]),
);
});
- test('reports test failures', () async {
+ test('"flutter drive" reports test failures', () async {
final RepositoryPackage plugin = createFakePlugin(
'plugin',
packagesDir,
@@ -1098,10 +962,10 @@
'example/test_driver/integration_test.dart',
'example/integration_test/bar_test.dart',
'example/integration_test/foo_test.dart',
- 'example/macos/macos.swift',
+ 'example/web/index.html',
],
platformSupport: <String, PlatformDetails>{
- platformMacOS: const PlatformDetails(PlatformSupport.inline),
+ platformWeb: const PlatformDetails(PlatformSupport.inline),
},
);
@@ -1109,17 +973,14 @@
processRunner
.mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
<FakeProcessInfo>[
- // No mock for 'devices', since it's running for macOS.
- FakeProcessInfo(
- MockProcess(exitCode: 1), <String>['drive']), // 'drive' #1
- FakeProcessInfo(
- MockProcess(exitCode: 1), <String>['drive']), // 'drive' #2
+ // Fail both bar_test.dart and foo_test.dart.
+ FakeProcessInfo(MockProcess(exitCode: 1), <String>['drive']),
+ FakeProcessInfo(MockProcess(exitCode: 1), <String>['drive']),
];
Error? commandError;
- final List<String> output =
- await runCapturingPrint(runner, <String>['drive-examples', '--macos'],
- errorHandler: (Error e) {
+ final List<String> output = await runCapturingPrint(
+ runner, <String>['drive-examples', '--web'], errorHandler: (Error e) {
commandError = e;
});
@@ -1144,7 +1005,9 @@
const <String>[
'drive',
'-d',
- 'macos',
+ 'web-server',
+ '--web-port=7357',
+ '--browser-name=chrome',
'--driver',
'test_driver/integration_test.dart',
'--target',
@@ -1156,7 +1019,9 @@
const <String>[
'drive',
'-d',
- 'macos',
+ 'web-server',
+ '--web-port=7357',
+ '--browser-name=chrome',
'--driver',
'test_driver/integration_test.dart',
'--target',
@@ -1166,6 +1031,61 @@
]));
});
+ test('"flutter test" reports test failures', () async {
+ final RepositoryPackage plugin = createFakePlugin(
+ 'plugin',
+ packagesDir,
+ extraFiles: <String>[
+ 'example/integration_test/bar_test.dart',
+ 'example/integration_test/foo_test.dart',
+ 'example/macos/macos.swift',
+ ],
+ platformSupport: <String, PlatformDetails>{
+ platformMacOS: const PlatformDetails(PlatformSupport.inline),
+ },
+ );
+
+ // Simulate failure from `flutter test`.
+ processRunner
+ .mockProcessesForExecutable[getFlutterCommand(mockPlatform)] =
+ <FakeProcessInfo>[
+ FakeProcessInfo(MockProcess(exitCode: 1), <String>['test']),
+ ];
+
+ Error? commandError;
+ final List<String> output =
+ await runCapturingPrint(runner, <String>['drive-examples', '--macos'],
+ errorHandler: (Error e) {
+ commandError = e;
+ });
+
+ expect(commandError, isA<ToolExit>());
+ expect(
+ output,
+ containsAllInOrder(<Matcher>[
+ contains('Running for plugin'),
+ contains('The following packages had errors:'),
+ contains(' plugin:\n'
+ ' Integration tests failed.'),
+ ]),
+ );
+
+ final Directory pluginExampleDirectory = getExampleDir(plugin);
+ expect(
+ processRunner.recordedCalls,
+ orderedEquals(<ProcessCall>[
+ ProcessCall(
+ getFlutterCommand(mockPlatform),
+ const <String>[
+ 'test',
+ '-d',
+ 'macos',
+ 'integration_test',
+ ],
+ pluginExampleDirectory.path),
+ ]));
+ });
+
group('packages', () {
test('can be driven', () async {
final RepositoryPackage package =
@@ -1301,7 +1221,8 @@
output,
containsAllInOrder(<Matcher>[
contains('Running for a_package'),
- contains('SKIPPING: No example is configured for driver tests.'),
+ contains(
+ 'SKIPPING: No example is configured for integration tests.'),
]),
);