Skip to content

Commit e3008a4

Browse files
authored
Normalize Compact and Expanded reporters (#1325)
Working towards #1311 The `Compact` and `Expanded` reporters have a lot of code in common, along with many superficial, and a few not-superficial differences. Some of the impactful differences look like they may be bugs. Make it easier to understand both reporters and their differences by reducing the superficial changes. The JSON reporter shares less code with the others, but aim for a consistent field ordering there as well. - Avoid using `Configuration.current` from the compact reporter. This was never added in the expanded reporter to avoid a transitive import to `dart:io`. The pattern of being configured at construction is already baked in to the `ReporterFactory` typedef as is a more clear pattern than reading from a magic zone scoped variable. Add required constructor args for the compact reporter which match those in the expanded reporter. Remove the TODO. - Use the same pattern for setting the color escape code fields. In the future we will likely want to migrate to `package:io` for these. - Shuffle some fields so they are ordered consistently in both reporters. - Add a default for `_lastProgressPassed` to avoid making it nullable. - Add `_printPath` and `_printPlatform` fields in the compact reporter rather than read them lazily through the zone scoped configuration. - Make the arguments required for the constructors instead of adding defaults which are never used. - Use 2 slashs for comments.
1 parent 42786e3 commit e3008a4

File tree

4 files changed

+79
-48
lines changed

4 files changed

+79
-48
lines changed

pkgs/test_core/lib/src/runner/configuration/reporters.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,13 @@ final _allReporters = <String, ReporterDetails>{
3636
printPath: config.paths.length > 1 ||
3737
Directory(config.paths.single).existsSync(),
3838
printPlatform: config.suiteDefaults.runtimes.length > 1)),
39-
'compact': ReporterDetails('A single line, updated continuously.',
40-
(_, engine, sink) => CompactReporter.watch(engine, sink)),
39+
'compact': ReporterDetails(
40+
'A single line, updated continuously.',
41+
(config, engine, sink) => CompactReporter.watch(engine, sink,
42+
color: config.color,
43+
printPath: config.paths.length > 1 ||
44+
Directory(config.paths.single).existsSync(),
45+
printPlatform: config.suiteDefaults.runtimes.length > 1)),
4146
'json': ReporterDetails(
4247
'A machine-readable format (see https://bit.ly/2Z7J0OH).',
4348
(_, engine, sink) => JsonReporter.watch(engine, sink)),

pkgs/test_core/lib/src/runner/reporter/compact.dart

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import 'package:test_api/src/utils.dart'; // ignore: implementation_imports
1414
import 'package:test_api/src/utils.dart' as utils;
1515

1616
import '../../util/io.dart';
17-
import '../configuration.dart';
1817
import '../engine.dart';
1918
import '../load_exception.dart';
2019
import '../load_suite.dart';
@@ -23,40 +22,41 @@ import '../reporter.dart';
2322
/// A reporter that prints test results to the console in a single
2423
/// continuously-updating line.
2524
class CompactReporter implements Reporter {
26-
final _config = Configuration.current;
25+
/// Whether the reporter should emit terminal color escapes.
26+
final bool _color;
2727

2828
/// The terminal escape for green text, or the empty string if this is Windows
2929
/// or not outputting to a terminal.
30-
String get _green => _config.color ? '\u001b[32m' : '';
30+
final String _green;
3131

3232
/// The terminal escape for red text, or the empty string if this is Windows
3333
/// or not outputting to a terminal.
34-
String get _red => _config.color ? '\u001b[31m' : '';
34+
final String _red;
3535

3636
/// The terminal escape for yellow text, or the empty string if this is
3737
/// Windows or not outputting to a terminal.
38-
String get _yellow => _config.color ? '\u001b[33m' : '';
38+
final String _yellow;
3939

4040
/// The terminal escape for gray text, or the empty string if this is
4141
/// Windows or not outputting to a terminal.
42-
String get _gray => _config.color ? '\u001b[1;30m' : '';
42+
final String _gray;
4343

4444
/// The terminal escape for bold text, or the empty string if this is
4545
/// Windows or not outputting to a terminal.
46-
String get _bold => _config.color ? '\u001b[1m' : '';
46+
final String _bold;
4747

4848
/// The terminal escape for removing test coloring, or the empty string if
4949
/// this is Windows or not outputting to a terminal.
50-
String get _noColor => _config.color ? '\u001b[0m' : '';
51-
52-
/// Whether the path to each test's suite should be printed.
53-
final bool _printPath = Configuration.current.paths.length > 1 ||
54-
Directory(Configuration.current.paths.single).existsSync();
50+
final String _noColor;
5551

5652
/// The engine used to run the tests.
5753
final Engine _engine;
5854

59-
final StringSink _sink;
55+
/// Whether the path to each test's suite should be printed.
56+
final bool _printPath;
57+
58+
/// Whether the platform each test is running on should be printed.
59+
final bool _printPlatform;
6060

6161
/// A stopwatch that tracks the duration of the full run.
6262
final _stopwatch = Stopwatch();
@@ -69,9 +69,10 @@ class CompactReporter implements Reporter {
6969

7070
/// The size of `_engine.passed` last time a progress notification was
7171
/// printed.
72-
int? _lastProgressPassed;
72+
int _lastProgressPassed = 0;
7373

74-
/// The size of `_engine.skipped` last time a progress notification was printed.
74+
/// The size of `_engine.skipped` last time a progress notification was
75+
/// printed.
7576
int? _lastProgressSkipped;
7677

7778
/// The size of `_engine.failed` last time a progress notification was
@@ -101,16 +102,39 @@ class CompactReporter implements Reporter {
101102
/// The set of all subscriptions to various streams.
102103
final _subscriptions = <StreamSubscription>{};
103104

105+
final StringSink _sink;
106+
104107
/// Watches the tests run by [engine] and prints their results to the
105108
/// terminal.
106-
static CompactReporter watch(Engine engine, StringSink sink) =>
107-
CompactReporter._(engine, sink);
108-
109-
CompactReporter._(this._engine, this._sink) {
109+
///
110+
/// If [color] is `true`, this will use terminal colors; if it's `false`, it
111+
/// won't. If [printPath] is `true`, this will print the path name as part of
112+
/// the test description. Likewise, if [printPlatform] is `true`, this will
113+
/// print the platform as part of the test description.
114+
static CompactReporter watch(Engine engine, StringSink sink,
115+
{required bool color,
116+
required bool printPath,
117+
required bool printPlatform}) =>
118+
CompactReporter._(engine, sink,
119+
color: color, printPath: printPath, printPlatform: printPlatform);
120+
121+
CompactReporter._(this._engine, this._sink,
122+
{required bool color,
123+
required bool printPath,
124+
required bool printPlatform})
125+
: _printPath = printPath,
126+
_printPlatform = printPlatform,
127+
_color = color,
128+
_green = color ? '\u001b[32m' : '',
129+
_red = color ? '\u001b[31m' : '',
130+
_yellow = color ? '\u001b[33m' : '',
131+
_gray = color ? '\u001b[1;30m' : '',
132+
_bold = color ? '\u001b[1m' : '',
133+
_noColor = color ? '\u001b[0m' : '' {
110134
_subscriptions.add(_engine.onTestStarted.listen(_onTestStarted));
111135

112-
/// Convert the future to a stream so that the subscription can be paused or
113-
/// canceled.
136+
// Convert the future to a stream so that the subscription can be paused or
137+
// canceled.
114138
_subscriptions.add(_engine.success.asStream().listen(_onDone));
115139
}
116140

@@ -158,7 +182,7 @@ class CompactReporter implements Reporter {
158182
_stopwatchStarted = true;
159183
_stopwatch.start();
160184

161-
/// Keep updating the time even when nothing else is happening.
185+
// Keep updating the time even when nothing else is happening.
162186
_subscriptions.add(Stream.periodic(Duration(seconds: 1))
163187
.listen((_) => _progressLine(_lastProgressMessage!)));
164188
}
@@ -222,7 +246,7 @@ class CompactReporter implements Reporter {
222246
}
223247

224248
// TODO - what type is this?
225-
_sink.writeln(indent(error.toString(color: _config.color)));
249+
_sink.writeln(indent(error.toString(color: _color)));
226250

227251
// Only print stack traces for load errors that come from the user's code.
228252
if (error.innerError is! IOException &&
@@ -376,7 +400,7 @@ class CompactReporter implements Reporter {
376400
name = '${liveTest.suite.path}: $name';
377401
}
378402

379-
if (_config.suiteDefaults.runtimes.length > 1) {
403+
if (_printPlatform) {
380404
name = '[${liveTest.suite.platform.runtime.name}] $name';
381405
}
382406

pkgs/test_core/lib/src/runner/reporter/expanded.dart

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,6 @@ class ExpandedReporter implements Reporter {
8686

8787
final StringSink _sink;
8888

89-
// TODO(nweiz): Get configuration from [Configuration.current] once we have
90-
// cross-platform imports.
9189
/// Watches the tests run by [engine] and prints their results to the
9290
/// terminal.
9391
///
@@ -96,13 +94,16 @@ class ExpandedReporter implements Reporter {
9694
/// the test description. Likewise, if [printPlatform] is `true`, this will
9795
/// print the platform as part of the test description.
9896
static ExpandedReporter watch(Engine engine, StringSink sink,
99-
{bool color = true, bool printPath = true, bool printPlatform = true}) {
100-
return ExpandedReporter._(engine, sink,
101-
color: color, printPath: printPath, printPlatform: printPlatform);
102-
}
97+
{required bool color,
98+
required bool printPath,
99+
required bool printPlatform}) =>
100+
ExpandedReporter._(engine, sink,
101+
color: color, printPath: printPath, printPlatform: printPlatform);
103102

104103
ExpandedReporter._(this._engine, this._sink,
105-
{bool color = true, bool printPath = true, bool printPlatform = true})
104+
{required bool color,
105+
required bool printPath,
106+
required bool printPlatform})
106107
: _printPath = printPath,
107108
_printPlatform = printPlatform,
108109
_color = color,
@@ -114,8 +115,8 @@ class ExpandedReporter implements Reporter {
114115
_noColor = color ? '\u001b[0m' : '' {
115116
_subscriptions.add(_engine.onTestStarted.listen(_onTestStarted));
116117

117-
/// Convert the future to a stream so that the subscription can be paused or
118-
/// canceled.
118+
// Convert the future to a stream so that the subscription can be paused or
119+
// canceled.
119120
_subscriptions.add(_engine.success.asStream().listen(_onDone));
120121
}
121122

@@ -134,6 +135,7 @@ class ExpandedReporter implements Reporter {
134135
@override
135136
void resume() {
136137
if (!_paused) return;
138+
137139
_stopwatch.start();
138140

139141
for (var subscription in _subscriptions) {
@@ -206,7 +208,7 @@ class ExpandedReporter implements Reporter {
206208
}
207209

208210
// TODO - what type is this?
209-
_sink.writeln(indent((error as dynamic).toString(color: _color) as String));
211+
_sink.writeln(indent(error.toString(color: _color)));
210212

211213
// Only print stack traces for load errors that come from the user's code.
212214
if (error.innerError is! FormatException && error.innerError is! String) {

pkgs/test_core/lib/src/runner/reporter/json.dart

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ class JsonReporter implements Reporter {
3434
/// The engine used to run the tests.
3535
final Engine _engine;
3636

37-
final StringSink _sink;
38-
3937
/// A stopwatch that tracks the duration of the full run.
4038
final _stopwatch = Stopwatch();
4139

@@ -45,12 +43,6 @@ class JsonReporter implements Reporter {
4543
/// when the reporter is paused.
4644
var _stopwatchStarted = false;
4745

48-
/// Whether the reporter is paused.
49-
var _paused = false;
50-
51-
/// The set of all subscriptions to various streams.
52-
final _subscriptions = <StreamSubscription>{};
53-
5446
/// An expando that associates unique IDs with [LiveTest]s.
5547
final _liveTestIDs = <LiveTest, int>{};
5648

@@ -63,15 +55,23 @@ class JsonReporter implements Reporter {
6355
/// The next ID to associate with a [LiveTest].
6456
var _nextID = 0;
6557

58+
/// Whether the reporter is paused.
59+
var _paused = false;
60+
61+
/// The set of all subscriptions to various streams.
62+
final _subscriptions = <StreamSubscription>{};
63+
64+
final StringSink _sink;
65+
6666
/// Watches the tests run by [engine] and prints their results as JSON.
6767
static JsonReporter watch(Engine engine, StringSink sink) =>
6868
JsonReporter._(engine, sink);
6969

7070
JsonReporter._(this._engine, this._sink) : _config = Configuration.current {
7171
_subscriptions.add(_engine.onTestStarted.listen(_onTestStarted));
7272

73-
/// Convert the future to a stream so that the subscription can be paused or
74-
/// canceled.
73+
// Convert the future to a stream so that the subscription can be paused or
74+
// canceled.
7575
_subscriptions.add(_engine.success.asStream().listen(_onDone));
7676

7777
_subscriptions.add(_engine.onSuiteAdded.listen(null, onDone: () {
@@ -146,8 +146,8 @@ class JsonReporter implements Reporter {
146146
liveTest.suite.path!)
147147
});
148148

149-
/// Convert the future to a stream so that the subscription can be paused or
150-
/// canceled.
149+
// Convert the future to a stream so that the subscription can be paused or
150+
// canceled.
151151
_subscriptions.add(
152152
liveTest.onComplete.asStream().listen((_) => _onComplete(liveTest)));
153153

0 commit comments

Comments
 (0)