diff --git a/packages/flutter_tools/lib/src/commands/test.dart b/packages/flutter_tools/lib/src/commands/test.dart index 7c5c774c7f..4b4b722113 100644 --- a/packages/flutter_tools/lib/src/commands/test.dart +++ b/packages/flutter_tools/lib/src/commands/test.dart @@ -208,6 +208,11 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { 'json': 'A machine-readable format. See: https://dart.dev/go/test-docs/json_reporter.md', }, ) + ..addOption('file-reporter', + help: 'Enable an additional reporter writing test results to a file.\n' + 'Should be in the form :, ' + 'Example: "json:reports/tests.json".' + ) ..addOption('timeout', help: 'The default test timeout, specified either ' 'in seconds (e.g. "60s"), ' @@ -463,6 +468,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { web: stringArgDeprecated('platform') == 'chrome', randomSeed: stringArgDeprecated('test-randomize-ordering-seed'), reporter: stringArgDeprecated('reporter'), + fileReporter: stringArg('file-reporter'), timeout: stringArgDeprecated('timeout'), runSkipped: boolArgDeprecated('run-skipped'), shardIndex: shardIndex, diff --git a/packages/flutter_tools/lib/src/test/runner.dart b/packages/flutter_tools/lib/src/test/runner.dart index 02789aa0ea..d38ccd5009 100644 --- a/packages/flutter_tools/lib/src/test/runner.dart +++ b/packages/flutter_tools/lib/src/test/runner.dart @@ -45,6 +45,7 @@ abstract class FlutterTestRunner { bool web = false, String? randomSeed, String? reporter, + String? fileReporter, String? timeout, bool runSkipped = false, int? shardIndex, @@ -82,6 +83,7 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner { bool web = false, String? randomSeed, String? reporter, + String? fileReporter, String? timeout, bool runSkipped = false, int? shardIndex, @@ -103,6 +105,8 @@ class _FlutterTestRunnerImpl implements FlutterTestRunner { ...['-r', 'json'] else if (reporter != null) ...['-r', reporter], + if (fileReporter != null) + '--file-reporter=$fileReporter', if (timeout != null) ...['--timeout', timeout], '--concurrency=$concurrency', 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 4eba15ec00..08adce15ee 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/test_test.dart @@ -804,6 +804,41 @@ dev_dependencies: ProcessManager: () => FakeProcessManager.any(), }); }); + + group('File Reporter', () { + testUsingContext('defaults to unset null value', () async { + final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0); + + final TestCommand testCommand = TestCommand(testRunner: testRunner); + final CommandRunner commandRunner = createTestCommandRunner(testCommand); + + await commandRunner.run(const [ + 'test', + '--no-pub', + ]); + expect(testRunner.lastFileReporterValue, null); + }, overrides: { + FileSystem: () => fs, + ProcessManager: () => FakeProcessManager.any(), + }); + + testUsingContext('when set --file-reporter value is passed on', () async { + final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0); + + final TestCommand testCommand = TestCommand(testRunner: testRunner); + final CommandRunner commandRunner = createTestCommandRunner(testCommand); + + await commandRunner.run(const [ + 'test', + '--no-pub', + '--file-reporter=json:out.jsonl' + ]); + expect(testRunner.lastFileReporterValue, 'json:out.jsonl'); + }, overrides: { + FileSystem: () => fs, + ProcessManager: () => FakeProcessManager.any(), + }); + }); } class FakeFlutterTestRunner implements FlutterTestRunner { @@ -813,6 +848,7 @@ class FakeFlutterTestRunner implements FlutterTestRunner { Duration? leastRunTime; bool? lastEnableObservatoryValue; late DebuggingOptions lastDebuggingOptionsValue; + String? lastFileReporterValue; String? lastReporterOption; @override @@ -839,6 +875,7 @@ class FakeFlutterTestRunner implements FlutterTestRunner { bool web = false, String? randomSeed, String? reporter, + String? fileReporter, String? timeout, bool runSkipped = false, int? shardIndex, @@ -849,6 +886,7 @@ class FakeFlutterTestRunner implements FlutterTestRunner { }) async { lastEnableObservatoryValue = enableObservatory; lastDebuggingOptionsValue = debuggingOptions; + lastFileReporterValue = fileReporter; lastReporterOption = reporter; if (leastRunTime != null) {