Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Side by Side Diff: lib/src/runner/reporter/json.dart

Issue 2066113002: Add location information to the JSON reporter. (Closed) Base URL: git@github.com:dart-lang/test@master
Patch Set: Don't emit line numbers for JS without --js-trace. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:async'; 5 import 'dart:async';
6 import 'dart:convert'; 6 import 'dart:convert';
7 7
8 import '../../backend/group.dart'; 8 import '../../backend/group.dart';
9 import '../../backend/group_entry.dart';
9 import '../../backend/live_test.dart'; 10 import '../../backend/live_test.dart';
10 import '../../backend/metadata.dart'; 11 import '../../backend/metadata.dart';
11 import '../../backend/suite.dart'; 12 import '../../backend/suite.dart';
12 import '../../frontend/expect.dart'; 13 import '../../frontend/expect.dart';
13 import '../../utils.dart'; 14 import '../../utils.dart';
14 import '../engine.dart'; 15 import '../engine.dart';
15 import '../load_suite.dart'; 16 import '../load_suite.dart';
16 import '../reporter.dart'; 17 import '../reporter.dart';
17 import '../version.dart'; 18 import '../version.dart';
18 19
19 /// A reporter that prints machine-readable JSON-formatted test results. 20 /// A reporter that prints machine-readable JSON-formatted test results.
20 class JsonReporter implements Reporter { 21 class JsonReporter implements Reporter {
21 /// Whether to use verbose stack traces. 22 /// Whether to use verbose stack traces.
22 final bool _verboseTrace; 23 final bool _verboseTrace;
23 24
25 /// Whether to emit location information for JS tests.
26 final bool _jsLocations;
27
24 /// The engine used to run the tests. 28 /// The engine used to run the tests.
25 final Engine _engine; 29 final Engine _engine;
26 30
27 /// A stopwatch that tracks the duration of the full run. 31 /// A stopwatch that tracks the duration of the full run.
28 final _stopwatch = new Stopwatch(); 32 final _stopwatch = new Stopwatch();
29 33
30 /// Whether we've started [_stopwatch]. 34 /// Whether we've started [_stopwatch].
31 /// 35 ///
32 /// We can't just use `_stopwatch.isRunning` because the stopwatch is stopped 36 /// We can't just use `_stopwatch.isRunning` because the stopwatch is stopped
33 /// when the reporter is paused. 37 /// when the reporter is paused.
(...skipping 12 matching lines...) Expand all
46 final _suiteIDs = new Map<Suite, int>(); 50 final _suiteIDs = new Map<Suite, int>();
47 51
48 /// An expando that associates unique IDs with [Group]s. 52 /// An expando that associates unique IDs with [Group]s.
49 final _groupIDs = new Map<Group, int>(); 53 final _groupIDs = new Map<Group, int>();
50 54
51 /// The next ID to associate with a [LiveTest]. 55 /// The next ID to associate with a [LiveTest].
52 var _nextID = 0; 56 var _nextID = 0;
53 57
54 /// Watches the tests run by [engine] and prints their results as JSON. 58 /// Watches the tests run by [engine] and prints their results as JSON.
55 /// 59 ///
56 /// If [verboseTrace] is `true`, this will print core library frames. 60 /// If [verboseTrace] is `true`, this will print core library frames. If
57 static JsonReporter watch(Engine engine, {bool verboseTrace: false}) { 61 /// [jsLocations] is `false`, this will not emit location information for JS
58 return new JsonReporter._(engine, verboseTrace: verboseTrace); 62 /// tests.
63 static JsonReporter watch(Engine engine, {bool verboseTrace: false,
64 bool jsLocations: true}) {
65 return new JsonReporter._(engine,
66 verboseTrace: verboseTrace, jsLocations: jsLocations);
59 } 67 }
60 68
61 JsonReporter._(this._engine, {bool verboseTrace: false}) 69 JsonReporter._(this._engine, {bool verboseTrace: false,
62 : _verboseTrace = verboseTrace { 70 bool jsLocations: true})
71 : _verboseTrace = verboseTrace,
72 _jsLocations = jsLocations {
63 _subscriptions.add(_engine.onTestStarted.listen(_onTestStarted)); 73 _subscriptions.add(_engine.onTestStarted.listen(_onTestStarted));
64 74
65 /// Convert the future to a stream so that the subscription can be paused or 75 /// Convert the future to a stream so that the subscription can be paused or
66 /// canceled. 76 /// canceled.
67 _subscriptions.add(_engine.success.asStream().listen(_onDone)); 77 _subscriptions.add(_engine.success.asStream().listen(_onDone));
68 78
69 _subscriptions.add(_engine.onSuiteAdded.listen(null, onDone: () { 79 _subscriptions.add(_engine.onSuiteAdded.listen(null, onDone: () {
70 _emit("allSuites", { 80 _emit("allSuites", {
71 "count": _engine.addedSuites.length 81 "count": _engine.addedSuites.length
72 }); 82 });
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 _stopwatchStarted = true; 123 _stopwatchStarted = true;
114 _stopwatch.start(); 124 _stopwatch.start();
115 } 125 }
116 126
117 var suiteID = _idForSuite(liveTest.suite); 127 var suiteID = _idForSuite(liveTest.suite);
118 128
119 // Don't emit groups for load suites. They're always empty and they provide 129 // Don't emit groups for load suites. They're always empty and they provide
120 // unnecessary clutter. 130 // unnecessary clutter.
121 var groupIDs = liveTest.suite is LoadSuite 131 var groupIDs = liveTest.suite is LoadSuite
122 ? [] 132 ? []
123 : _idsForGroups(liveTest.groups, suiteID); 133 : _idsForGroups(liveTest.groups, liveTest.suite);
124 134
125 var id = _nextID++; 135 var id = _nextID++;
126 _liveTestIDs[liveTest] = id; 136 _liveTestIDs[liveTest] = id;
127 _emit("testStart", { 137 _emit("testStart", {
128 "test": { 138 "test": _addFrameInfo({
129 "id": id, 139 "id": id,
130 "name": liveTest.test.name, 140 "name": liveTest.test.name,
131 "suiteID": suiteID, 141 "suiteID": suiteID,
132 "groupIDs": groupIDs, 142 "groupIDs": groupIDs,
133 "metadata": _serializeMetadata(liveTest.test.metadata) 143 "metadata": _serializeMetadata(liveTest.test.metadata)
134 } 144 }, liveTest.test, liveTest.suite.platform)
135 }); 145 });
136 146
137 /// Convert the future to a stream so that the subscription can be paused or 147 /// Convert the future to a stream so that the subscription can be paused or
138 /// canceled. 148 /// canceled.
139 _subscriptions.add(liveTest.onComplete.asStream().listen((_) => 149 _subscriptions.add(liveTest.onComplete.asStream().listen((_) =>
140 _onComplete(liveTest))); 150 _onComplete(liveTest)));
141 151
142 _subscriptions.add(liveTest.onError.listen((error) => 152 _subscriptions.add(liveTest.onError.listen((error) =>
143 _onError(liveTest, error.error, error.stackTrace))); 153 _onError(liveTest, error.error, error.stackTrace)));
144 154
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 } 186 }
177 }); 187 });
178 return id; 188 return id;
179 } 189 }
180 190
181 /// Returns a list of the IDs for all the groups in [groups], which are 191 /// Returns a list of the IDs for all the groups in [groups], which are
182 /// contained in the suite identified by [suiteID]. 192 /// contained in the suite identified by [suiteID].
183 /// 193 ///
184 /// If a group doesn't have an ID yet, this assigns one and emits a new event 194 /// If a group doesn't have an ID yet, this assigns one and emits a new event
185 /// for that group. 195 /// for that group.
186 List<int> _idsForGroups(Iterable<Group> groups, int suiteID) { 196 List<int> _idsForGroups(Iterable<Group> groups, Suite suite) {
187 int parentID; 197 int parentID;
188 return groups.map((group) { 198 return groups.map((group) {
189 if (_groupIDs.containsKey(group)) { 199 if (_groupIDs.containsKey(group)) {
190 parentID = _groupIDs[group]; 200 parentID = _groupIDs[group];
191 return parentID; 201 return parentID;
192 } 202 }
193 203
194 var id = _nextID++; 204 var id = _nextID++;
195 _groupIDs[group] = id; 205 _groupIDs[group] = id;
196 206
197 _emit("group", { 207 _emit("group", {
198 "group": { 208 "group": _addFrameInfo({
199 "id": id, 209 "id": id,
200 "suiteID": suiteID, 210 "suiteID": _idForSuite(suite),
201 "parentID": parentID, 211 "parentID": parentID,
202 "name": group.name, 212 "name": group.name,
203 "metadata": _serializeMetadata(group.metadata), 213 "metadata": _serializeMetadata(group.metadata),
204 "testCount": group.testCount 214 "testCount": group.testCount
205 } 215 }, group, suite.platform)
206 }); 216 });
207 parentID = id; 217 parentID = id;
208 return id; 218 return id;
209 }).toList(); 219 }).toList();
210 } 220 }
211 221
212 /// Serializes [metadata] into a JSON-protocol-compatible map. 222 /// Serializes [metadata] into a JSON-protocol-compatible map.
213 Map _serializeMetadata(Metadata metadata) => 223 Map _serializeMetadata(Metadata metadata) =>
214 {"skip": metadata.skip, "skipReason": metadata.skipReason}; 224 {"skip": metadata.skip, "skipReason": metadata.skipReason};
215 225
(...skipping 26 matching lines...) Expand all
242 252
243 _emit("done", {"success": success}); 253 _emit("done", {"success": success});
244 } 254 }
245 255
246 /// Emits an event with the given type and attributes. 256 /// Emits an event with the given type and attributes.
247 void _emit(String type, Map attributes) { 257 void _emit(String type, Map attributes) {
248 attributes["type"] = type; 258 attributes["type"] = type;
249 attributes["time"] = _stopwatch.elapsed.inMilliseconds; 259 attributes["time"] = _stopwatch.elapsed.inMilliseconds;
250 print(JSON.encode(attributes)); 260 print(JSON.encode(attributes));
251 } 261 }
262
263 /// Modifies [map] to include line, column, and URL information from the first
264 /// frame of [entry.trace].
265 ///
266 /// Returns [map].
267 Map<String, dynamic> _addFrameInfo(Map<String, dynamic> map,
268 GroupEntry entry, TestPlatform platform) {
kevmoo 2016/06/15 19:50:38 no import for `TestPlatform` class
nweiz 2016/06/15 20:35:39 Done.
269 var frame = entry.trace?.frames?.first;
270 if (!_jsLocations && platform.isJS) frame = null;
271
272 map["line"] = frame?.line;
273 map["column"] = frame?.column;
274 map["url"] = frame?.uri?.toString();
275 return map;
276 }
252 } 277 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698