add a line to re-run the failed test after each failure in the compact reporter (#1736)
Closes https://github.com/dart-lang/test/issues/1734
Example output:
<img width="906" alt="Screen Shot 2022-06-28 at 11 00 32 AM" src="https://user-images.githubusercontent.com/984921/176251403-63a99464-6de2-42ad-a85e-1c794d434c00.png">
diff --git a/pkgs/test/CHANGELOG.md b/pkgs/test/CHANGELOG.md
index 0626919..c613763 100644
--- a/pkgs/test/CHANGELOG.md
+++ b/pkgs/test/CHANGELOG.md
@@ -2,6 +2,8 @@
* Make the labels for test loading more readable in the compact and expanded
reporters, use gray instead of black.
+* Print a command to re-run the failed test after each failure in the compact
+ reporter.
* Fix the package config path used when running pre-compiled vm tests.
## 1.21.3
diff --git a/pkgs/test/test/runner/compact_reporter_test.dart b/pkgs/test/test/runner/compact_reporter_test.dart
index b8ef11a..ba0ff02 100644
--- a/pkgs/test/test/runner/compact_reporter_test.dart
+++ b/pkgs/test/test/runner/compact_reporter_test.dart
@@ -5,7 +5,9 @@
@TestOn('vm')
import 'dart:async';
+import 'dart:io';
+import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;
@@ -426,6 +428,42 @@
For example, 'dart test --chain-stack-traces'.''',
chainStackTraces: false);
});
+
+ group('gives users a way to re-run failed tests', () {
+ final executablePath = p.absolute(Platform.resolvedExecutable);
+
+ test('with simple names', () {
+ return _expectReport('''
+ test('failure', () {
+ expect(1, equals(2));
+ });''', '''
+ +0: loading test.dart
+ +0: failure
+ +0 -1: failure [E]
+ Expected: <2>
+ Actual: <1>
+
+ To run this test again: $executablePath test test.dart -p vm --plain-name 'failure'
+
+ +0 -1: Some tests failed.''');
+ });
+
+ test('escapes names containing single quotes', () {
+ return _expectReport('''
+ test("failure with a ' in the name", () {
+ expect(1, equals(2));
+ });''', '''
+ +0: loading test.dart
+ +0: failure with a ' in the name
+ +0 -1: failure with a ' in the name [E]
+ Expected: <2>
+ Actual: <1>
+
+ To run this test again: $executablePath test test.dart -p vm --plain-name 'failure with a '\\'' in the name'
+
+ +0 -1: Some tests failed.''');
+ });
+ });
}
Future<void> _expectReport(String tests, String expected,
diff --git a/pkgs/test_core/CHANGELOG.md b/pkgs/test_core/CHANGELOG.md
index 6728e44..f94fbd1 100644
--- a/pkgs/test_core/CHANGELOG.md
+++ b/pkgs/test_core/CHANGELOG.md
@@ -2,6 +2,8 @@
* Make the labels for test loading more readable in the compact and expanded
reporters, use gray instead of black.
+* Print a command to re-run the failed test after each failure in the compact
+ reporter.
* Fix the package config path used when running pre-compiled vm tests.
## 0.4.15
diff --git a/pkgs/test_core/lib/src/runner/reporter/compact.dart b/pkgs/test_core/lib/src/runner/reporter/compact.dart
index 509ff36..d4a1ba7 100644
--- a/pkgs/test_core/lib/src/runner/reporter/compact.dart
+++ b/pkgs/test_core/lib/src/runner/reporter/compact.dart
@@ -40,6 +40,10 @@
/// Windows or not outputting to a terminal.
final String _gray;
+ /// The terminal escape code for cyan text, or the empty string if this is
+ /// Windows or not outputting to a terminal.
+ final String _cyan;
+
/// The terminal escape for bold text, or the empty string if this is
/// Windows or not outputting to a terminal.
final String _bold;
@@ -132,6 +136,7 @@
_red = color ? '\u001b[31m' : '',
_yellow = color ? '\u001b[33m' : '',
_gray = color ? '\u001b[90m' : '',
+ _cyan = color ? '\u001b[36m' : '',
_bold = color ? '\u001b[1m' : '',
_noColor = color ? '\u001b[0m' : '' {
_subscriptions.add(_engine.onTestStarted.listen(_onTestStarted));
@@ -214,6 +219,16 @@
if (message.type == MessageType.skip) text = ' $_yellow$text$_noColor';
_sink.writeln(text);
}));
+
+ liveTest.onComplete.then((_) {
+ var result = liveTest.state.result;
+ if (result != Result.error && result != Result.failure) return;
+ _sink.writeln('');
+ _sink.writeln('$_bold${_cyan}To run this test again:$_noColor '
+ '${Platform.executable} test ${liveTest.suite.path} '
+ '-p ${liveTest.suite.platform.runtime.identifier} '
+ "--plain-name '${liveTest.test.name.replaceAll("'", r"'\''")}'");
+ });
}
/// A callback called when [liveTest]'s state becomes [state].