Skip to content

Commit 386429e

Browse files
Merge branch 'main' into vgv-ai-bot/issue-360
2 parents 1f7cea8 + 1c4a302 commit 386429e

11 files changed

Lines changed: 725 additions & 540 deletions

File tree

.github/workflows/site.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
uses: actions/checkout@v7
2626

2727
- name: ⚙️ Setup Node
28-
uses: actions/setup-node@v6
28+
uses: actions/setup-node@v7
2929
with:
3030
node-version: 20.x
3131
cache: npm

.github/workflows/site_deploy.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
uses: actions/checkout@v7
2020

2121
- name: ⚙️ Setup Node
22-
uses: actions/setup-node@v6
22+
uses: actions/setup-node@v7
2323
with:
2424
node-version: 20.x
2525
cache: npm

lib/src/cli/git_cli.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Git {
2525
try {
2626
await _Cmd.run('git', [
2727
'ls-remote',
28+
'--get-url',
2829
'$remote',
2930
'--exit-code',
3031
], logger: logger);

lib/src/commands/dart/commands/dart_test_command.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class DartTestOptions {
2828
required this.reportOn,
2929
required this.runSkipped,
3030
required this.checkIgnore,
31+
required this.fileReporter,
3132
});
3233

3334
/// Parses [ArgResults] into a [DartTestOptions] instance.
@@ -61,6 +62,7 @@ class DartTestOptions {
6162
.toList();
6263
final runSkipped = argResults['run-skipped'] as bool;
6364
final checkIgnore = argResults['check-ignore'] as bool;
65+
final fileReporter = argResults['file-reporter'] as String?;
6466
final rest = argResults.rest;
6567

6668
return DartTestOptions._(
@@ -80,6 +82,7 @@ class DartTestOptions {
8082
reportOn: reportOn,
8183
runSkipped: runSkipped,
8284
checkIgnore: checkIgnore,
85+
fileReporter: fileReporter,
8386
rest: rest,
8487
);
8588
}
@@ -133,6 +136,10 @@ class DartTestOptions {
133136
/// Whether to check for and respect coverage ignore comments.
134137
final bool checkIgnore;
135138

139+
/// Additional reporter that writes test results to a file, expressed as
140+
/// `<name>:<path>` (e.g. `json:reports/tests.json`).
141+
final String? fileReporter;
142+
136143
/// The remaining arguments passed to the `dart test` command.
137144
final List<String> rest;
138145
}
@@ -281,6 +288,13 @@ class DartTestCommand extends Command<int> {
281288
help:
282289
'Whether to check for and respect coverage ignore comments '
283290
'(e.g. // coverage:ignore-line).',
291+
)
292+
..addOption(
293+
'file-reporter',
294+
help:
295+
'Enable an additional reporter writing test results to a file. '
296+
'Should be in the form <name>:<path> (e.g. "json:reports/tests.json").',
297+
valueHelp: 'name:path',
284298
);
285299
}
286300

@@ -347,6 +361,8 @@ This command should be run from the root of your Dart project.''');
347361
if (options.runSkipped) '--run-skipped',
348362
if (options.platform != null) ...['--platform', options.platform!],
349363
if (options.platform == null) ...['-j', options.concurrency],
364+
if (options.fileReporter != null)
365+
'--file-reporter=${options.fileReporter}',
350366
...options.rest,
351367
],
352368
reportOn: options.reportOn.isEmpty ? null : options.reportOn,

lib/src/commands/test/test.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class FlutterTestOptions {
3232
required this.runSkipped,
3333
required this.flavor,
3434
required this.timeout,
35+
required this.fileReporter,
3536
required this.rest,
3637
});
3738

@@ -151,6 +152,7 @@ class FlutterTestOptions {
151152
final effectiveTimeout = timeoutSeconds != null
152153
? Duration(seconds: timeoutSeconds)
153154
: null;
155+
final fileReporter = argResults['file-reporter'] as String?;
154156
final rest = argResults.rest;
155157

156158
return FlutterTestOptions._(
@@ -174,6 +176,7 @@ class FlutterTestOptions {
174176
runSkipped: runSkipped,
175177
flavor: flavor,
176178
timeout: effectiveTimeout,
179+
fileReporter: fileReporter,
177180
rest: rest,
178181
);
179182
}
@@ -240,6 +243,10 @@ class FlutterTestOptions {
240243
/// Maximum time to let tests run before killing the process.
241244
final Duration? timeout;
242245

246+
/// Additional reporter that writes test results to a file, expressed as
247+
/// `<name>:<path>` (e.g. `json:reports/tests.json`).
248+
final String? fileReporter;
249+
243250
/// The remaining arguments passed to the test command.
244251
final List<String> rest;
245252
}
@@ -445,6 +452,13 @@ class TestCommand extends Command<int> {
445452
'Maximum seconds to let tests run before killing the process. '
446453
'Useful when tests hang due to an unbounded pumpAndSettle() call.',
447454
valueHelp: 'seconds',
455+
)
456+
..addOption(
457+
'file-reporter',
458+
help:
459+
'Enable an additional reporter writing test results to a file. '
460+
'Should be in the form <name>:<path> (e.g. "json:reports/tests.json").',
461+
valueHelp: 'name:path',
448462
);
449463
}
450464

@@ -536,6 +550,8 @@ This command should be run from the root of your Flutter project.''');
536550
'--no-pub',
537551
if (options.timeout != null)
538552
'--timeout=${options.timeout!.inSeconds}s',
553+
if (options.fileReporter != null)
554+
'--file-reporter=${options.fileReporter}',
539555
...options.rest,
540556
],
541557
);

site/docs/commands/test.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,25 @@ very_good test [arguments]
4848
--fail-fast Stop running tests after the first failure.
4949
--timeout=<seconds> Maximum seconds to let tests run before killing the process.
5050
Useful when tests hang due to an unbounded pumpAndSettle() call.
51+
--file-reporter=<name:path> Enable an additional reporter writing test results to a file.
52+
Should be in the form <name>:<path> (e.g. "json:reports/tests.json").
5153

5254
Run "very_good help" to see global options.
5355
```
5456

57+
### Machine-readable test reports
58+
59+
If you need a machine-readable summary of your test results (for example to feed a CI tool or convert to JUnit XML), use `--file-reporter`. It maps directly to the `--file-reporter` flag from `flutter test` and `dart test`, and writes the report to a file instead of stdout — so it stays compatible with `very_good test`'s optimization and progress rendering.
60+
61+
```sh
62+
# Emits reports/tests.json alongside the normal test output.
63+
very_good test --coverage --file-reporter json:reports/tests.json
64+
```
65+
66+
:::info
67+
`--reporter` and `--machine` are intentionally not exposed: they replace stdout with a machine-readable stream, which prevents `very_good test` from rendering progress and picking up failures. `--file-reporter` gives you the same machine-readable content without that trade-off.
68+
:::
69+
5570
:::tip
5671
For **Dart** projects, use **`very_good dart test`** instead.
5772

0 commit comments

Comments
 (0)