diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart index cc95de420f..6b9a12722b 100644 --- a/packages/flutter_tools/lib/src/commands/test.dart +++ b/packages/flutter_tools/lib/src/commands/test.dart @@ -111,6 +111,9 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { 'Instructions for connecting with a debugger are printed to the ' 'console once the test has started.', ) + ..addFlag('fail-fast', + help: 'Stop running tests after the first failure.', + ) ..addFlag('run-skipped', help: 'Run skipped tests instead of skipping them.', ) @@ -578,6 +581,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { reporter: stringArg('reporter'), fileReporter: stringArg('file-reporter'), timeout: stringArg('timeout'), + failFast: boolArg('fail-fast'), runSkipped: boolArg('run-skipped'), shardIndex: shardIndex, totalShards: totalShards, @@ -605,6 +609,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { reporter: stringArg('reporter'), fileReporter: stringArg('file-reporter'), timeout: stringArg('timeout'), + failFast: boolArg('fail-fast'), runSkipped: boolArg('run-skipped'), shardIndex: shardIndex, totalShards: totalShards, diff --git a/packages/flutter_tools/lib/src/test/runner.dart b/packages/flutter_tools/lib/src/test/runner.dart index bfa5c1de50..b9ad2f30b4 100644 --- a/packages/flutter_tools/lib/src/test/runner.dart +++ b/packages/flutter_tools/lib/src/test/runner.dart @@ -56,6 +56,7 @@ abstract class FlutterTestRunner { String? reporter, String? fileReporter, String? timeout, + bool failFast = false, bool runSkipped = false, int? shardIndex, int? totalShards, @@ -84,6 +85,7 @@ abstract class FlutterTestRunner { String? reporter, String? fileReporter, String? timeout, + bool failFast = false, bool runSkipped = false, int? shardIndex, int? totalShards, @@ -121,6 +123,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner { String? reporter, String? fileReporter, String? timeout, + bool failFast = false, bool runSkipped = false, int? shardIndex, int? totalShards, @@ -158,6 +161,8 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner { ...['--tags', tags], if (excludeTags != null) ...['--exclude-tags', excludeTags], + if (failFast) + '--fail-fast', if (runSkipped) '--run-skipped', if (totalShards != null) @@ -665,6 +670,7 @@ class SpawnPlugin extends PlatformPlugin { String? reporter, String? fileReporter, String? timeout, + bool failFast = false, bool runSkipped = false, int? shardIndex, int? totalShards, @@ -734,6 +740,8 @@ class SpawnPlugin extends PlatformPlugin { ...['--tags', tags], if (excludeTags != null) ...['--exclude-tags', excludeTags], + if (failFast) + '--fail-fast', if (runSkipped) '--run-skipped', if (totalShards != null) diff --git a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart index d3d955d98e..a925dae8e9 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart @@ -189,29 +189,6 @@ dev_dependencies: ProcessManager: () => FakeProcessManager.any(), }); - testUsingContext('Pipes test-randomize-ordering-seed to package:test', - () async { - final FakePackageTest fakePackageTest = FakePackageTest(); - - final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest); - final CommandRunner commandRunner = - createTestCommandRunner(testCommand); - - await commandRunner.run(const [ - 'test', - '--test-randomize-ordering-seed=random', - '--no-pub', - ]); - expect( - fakePackageTest.lastArgs, - contains('--test-randomize-ordering-seed=random'), - ); - }, overrides: { - FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), - Cache: () => Cache.test(processManager: FakeProcessManager.any()), - }); - testUsingContext( 'Confirmation that the reporter, timeout, and concurrency args are not set by default', () async { @@ -492,54 +469,26 @@ dev_dependencies: ProcessManager: () => FakeProcessManager.any(), }); - testUsingContext('Pipes start-paused to package:test', - () async { - final FakePackageTest fakePackageTest = FakePackageTest(); + group('Pipes to package:test', () { + Future expectPassesArgument(String value, [String? passValue]) async { + final FakePackageTest fakePackageTest = FakePackageTest(); + final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest); + final CommandRunner commandRunner = createTestCommandRunner(testCommand); - final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest); - final CommandRunner commandRunner = - createTestCommandRunner(testCommand); + await commandRunner.run(['test', '--no-pub', value]); + expect(fakePackageTest.lastArgs, contains(passValue ?? value)); + } - await commandRunner.run(const [ - 'test', - '--no-pub', - '--start-paused', - '--', - 'test/fake_test.dart', - ]); - expect( - fakePackageTest.lastArgs, - contains('--pause-after-load'), - ); - }, overrides: { - FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), - Cache: () => Cache.test(processManager: FakeProcessManager.any()), - }); - - testUsingContext('Pipes run-skipped to package:test', - () async { - final FakePackageTest fakePackageTest = FakePackageTest(); - - final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest); - final CommandRunner commandRunner = - createTestCommandRunner(testCommand); - - await commandRunner.run(const [ - 'test', - '--no-pub', - '--run-skipped', - '--', - 'test/fake_test.dart', - ]); - expect( - fakePackageTest.lastArgs, - contains('--run-skipped'), - ); - }, overrides: { - FileSystem: () => fs, - ProcessManager: () => FakeProcessManager.any(), - Cache: () => Cache.test(processManager: FakeProcessManager.any()), + testUsingContext('passes various CLI options through to package:test', () async { + await expectPassesArgument('--start-paused', '--pause-after-load'); + await expectPassesArgument('--fail-fast'); + await expectPassesArgument('--run-skipped'); + await expectPassesArgument('--test-randomize-ordering-seed=random'); + }, overrides: { + FileSystem: () => fs, + ProcessManager: () => FakeProcessManager.any(), + Cache: () => Cache.test(processManager: FakeProcessManager.any()), + }); }); testUsingContext('Pipes enable-vmService', () async { @@ -674,6 +623,7 @@ dev_dependencies: '--test-randomize-ordering-seed=random', '--tags=tag1', '--exclude-tags=tag2', + '--fail-fast', '--run-skipped', '--total-shards=1', '--shard-index=1', @@ -715,6 +665,7 @@ const List packageTestArgs = [ 'tag1', '--exclude-tags', 'tag2', + '--fail-fast', '--run-skipped', '--total-shards=1', '--shard-index=1', @@ -1466,6 +1417,7 @@ class FakeFlutterTestRunner implements FlutterTestRunner { String? reporter, String? fileReporter, String? timeout, + bool failFast = false, bool runSkipped = false, int? shardIndex, int? totalShards, @@ -1513,6 +1465,7 @@ class FakeFlutterTestRunner implements FlutterTestRunner { String? reporter, String? fileReporter, String? timeout, + bool failFast = false, bool runSkipped = false, int? shardIndex, int? totalShards,