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

Side by Side Diff: pkg/unittest/lib/unittest.dart

Issue 208273009: pkg/unittest: Removed references to expectAsync[Until]X in docs (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: more word smithing Created 6 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « pkg/unittest/lib/src/utils.dart ('k') | pkg/unittest/lib/vm_config.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 /** 5 /// Support for writing Dart unit tests.
6 * Support for writing Dart unit tests. 6 ///
7 * 7 /// For information on installing and importing this library, see the
8 * For information on installing and importing this library, see the 8 /// [unittest package on pub.dartlang.org]
9 * [unittest package on pub.dartlang.org] 9 /// (http://pub.dartlang.org/packages/unittest).
10 * (http://pub.dartlang.org/packages/unittest). 10 ///
11 * 11 /// **See also:**
12 * **See also:** 12 /// [Unit Testing with Dart]
13 * [Unit Testing with Dart] 13 /// (http://www.dartlang.org/articles/dart-unit-tests/)
14 * (http://www.dartlang.org/articles/dart-unit-tests/) 14 ///
15 * 15 /// ##Concepts
16 * ##Concepts 16 ///
17 * 17 /// * __Tests__: Tests are specified via the top-level function [test], they ca n be
18 * * __Tests__: Tests are specified via the top-level function [test], they can be 18 /// organized together using [group].
19 * organized together using [group]. 19 ///
20 * 20 /// * __Checks__: Test expectations can be specified via [expect]
21 * * __Checks__: Test expectations can be specified via [expect] 21 ///
22 * 22 /// * __Matchers__: [expect] assertions are written declaratively using the
23 * * __Matchers__: [expect] assertions are written declaratively using the 23 /// [Matcher] class.
24 * [Matcher] class. 24 ///
25 * 25 /// * __Configuration__: The framework can be adapted by setting
26 * * __Configuration__: The framework can be adapted by setting 26 /// [unittestConfiguration] with a [Configuration]. See the other libraries
27 * [unittestConfiguration] with a [Configuration]. See the other libraries 27 /// in the `unittest` package for alternative implementations of
28 * in the `unittest` package for alternative implementations of 28 /// [Configuration] including `compact_vm_config.dart`, `html_config.dart`
29 * [Configuration] including `compact_vm_config.dart`, `html_config.dart` and 29 /// and `html_enhanced_config.dart`.
30 * `html_enhanced_config.dart`. 30 ///
31 * 31 /// ##Examples
32 * ##Examples 32 ///
33 * 33 /// A trivial test:
34 * A trivial test: 34 ///
35 * 35 /// import 'package:unittest/unittest.dart';
36 * import 'package:unittest/unittest.dart'; 36 /// main() {
37 * main() { 37 /// test('this is a test', () {
38 * test('this is a test', () { 38 /// int x = 2 + 3;
39 * int x = 2 + 3; 39 /// expect(x, equals(5));
40 * expect(x, equals(5)); 40 /// });
41 * }); 41 /// }
42 * } 42 ///
43 * 43 /// Multiple tests:
44 * Multiple tests: 44 ///
45 * 45 /// import 'package:unittest/unittest.dart';
46 * import 'package:unittest/unittest.dart'; 46 /// main() {
47 * main() { 47 /// test('this is a test', () {
48 * test('this is a test', () { 48 /// int x = 2 + 3;
49 * int x = 2 + 3; 49 /// expect(x, equals(5));
50 * expect(x, equals(5)); 50 /// });
51 * }); 51 /// test('this is another test', () {
52 * test('this is another test', () { 52 /// int x = 2 + 3;
53 * int x = 2 + 3; 53 /// expect(x, equals(5));
54 * expect(x, equals(5)); 54 /// });
55 * }); 55 /// }
56 * } 56 ///
57 * 57 /// Multiple tests, grouped by category:
58 * Multiple tests, grouped by category: 58 ///
59 * 59 /// import 'package:unittest/unittest.dart';
60 * import 'package:unittest/unittest.dart'; 60 /// main() {
61 * main() { 61 /// group('group A', () {
62 * group('group A', () { 62 /// test('test A.1', () {
63 * test('test A.1', () { 63 /// int x = 2 + 3;
64 * int x = 2 + 3; 64 /// expect(x, equals(5));
65 * expect(x, equals(5)); 65 /// });
66 * }); 66 /// test('test A.2', () {
67 * test('test A.2', () { 67 /// int x = 2 + 3;
68 * int x = 2 + 3; 68 /// expect(x, equals(5));
69 * expect(x, equals(5)); 69 /// });
70 * }); 70 /// });
71 * }); 71 /// group('group B', () {
72 * group('group B', () { 72 /// test('this B.1', () {
73 * test('this B.1', () { 73 /// int x = 2 + 3;
74 * int x = 2 + 3; 74 /// expect(x, equals(5));
75 * expect(x, equals(5)); 75 /// });
76 * }); 76 /// });
77 * }); 77 /// }
78 * } 78 ///
79 * 79 /// Asynchronous tests: if callbacks expect between 0 and 6 positional
80 * Asynchronous tests: if callbacks expect between 0 and 2 positional arguments, 80 /// arguments, [expectAsync] will wrap a function into a new callback and will
81 * depending on the suffix of expectAsyncX(). expectAsyncX() will wrap a 81 /// not consider the test complete until that callback is run. A count argument
82 * function into a new callback and will not consider the test complete until 82 /// can be provided to specify the number of times the callback should be called
83 * that callback is run. A count argument can be provided to specify the number 83 /// (the default is 1).
84 * of times the callback should be called (the default is 1). 84 ///
85 * 85 /// import 'dart:async';
86 * import 'dart:async'; 86 /// import 'package:unittest/unittest.dart';
87 * import 'package:unittest/unittest.dart'; 87 /// void main() {
88 * void main() { 88 /// test('callback is executed once', () {
89 * test('callback is executed once', () { 89 /// // wrap the callback of an asynchronous call with [expectAsync] if
90 * // wrap the callback of an asynchronous call with [expectAsync0] if 90 /// // the callback takes 0 arguments...
91 * // the callback takes 0 arguments... 91 /// var timer = Timer.run(expectAsync(() {
92 * var timer = Timer.run(expectAsync0(() { 92 /// int x = 2 + 3;
93 * int x = 2 + 3; 93 /// expect(x, equals(5));
94 * expect(x, equals(5)); 94 /// }));
95 * })); 95 /// });
96 * }); 96 ///
97 * 97 /// test('callback is executed twice', () {
98 * test('callback is executed twice', () { 98 /// var callback = expectAsync(() {
99 * var callback = expectAsync0(() { 99 /// int x = 2 + 3;
100 * int x = 2 + 3; 100 /// expect(x, equals(5));
101 * expect(x, equals(5)); 101 /// }, count: 2); // <-- we can indicate multiplicity to [expectAsync]
102 * }, count: 2); // <-- we can indicate multiplicity to [expectAsync0] 102 /// Timer.run(callback);
103 * Timer.run(callback); 103 /// Timer.run(callback);
104 * Timer.run(callback); 104 /// });
105 * }); 105 /// }
106 * } 106 ///
107 * 107 /// There may be times when the number of times a callback should be called is
kevmoo 2014/03/25 01:01:34 This paragraph is tough to understand. Should we j
Siggi Cherem (dart-lang) 2014/03/25 17:33:18 Sure, an alternative here would be to explain it d
kevmoo 2014/03/25 19:43:48 I guess we can ponder. This delta is an improvemen
108 * expectAsyncX() will wrap the callback code and block the completion of the 108 /// non-deterministic. In this case a dummy callback can be created with
109 * test until the wrapped callback has been called the specified number of times 109 /// expectAsync((){}) and this can be called from the real callback when it is
110 * -- the default is 1. There may be times when the number of times a callback 110 /// finally complete.
111 * should be called is non-deterministic. In this case a dummy callback can be 111 ///
112 * created with expectAsync0((){}) and this can be called from the real callback 112 /// A variation on this is [expectAsyncUntil], which takes a callback as the
113 * when it is finally complete. 113 /// first parameter and a predicate function as the second parameter. After each
114 * 114 /// time the callback is called, the predicate function will be called. If it
115 * A variation on this is expectAsyncUntilX(), which takes a callback as the 115 /// returns `false` the test will still be considered incomplete.
116 * first parameter and a predicate function as the second parameter; after each 116 ///
117 * time * the callback is called, the predicate function will be called; if it 117 /// Test functions can return [Future]s, which provide another way of doing
118 * returns false the test will still be considered incomplete. 118 /// asynchronous tests. The test framework will handle exceptions thrown by
119 * 119 /// the Future, and will advance to the next test when the Future is complete.
120 * Test functions can return [Future]s, which provide another way of doing 120 ///
121 * asynchronous tests. The test framework will handle exceptions thrown by 121 /// import 'dart:async';
122 * the Future, and will advance to the next test when the Future is complete. 122 /// import 'package:unittest/unittest.dart';
123 * 123 /// void main() {
124 * import 'dart:async'; 124 /// test('test that time has passed', () {
125 * import 'package:unittest/unittest.dart'; 125 /// var duration = const Duration(milliseconds: 200);
126 * void main() { 126 /// var time = new DateTime.now();
127 * test('test that time has passed', () { 127 ///
128 * var duration = const Duration(milliseconds: 200); 128 /// return new Future.delayed(duration).then((_) {
129 * var time = new DateTime.now(); 129 /// var delta = new DateTime.now().difference(time);
130 * 130 ///
131 * return new Future.delayed(duration).then((_) { 131 /// expect(delta, greaterThanOrEqualTo(duration));
132 * var delta = new DateTime.now().difference(time); 132 /// });
133 * 133 /// });
134 * expect(delta, greaterThanOrEqualTo(duration)); 134 /// }
135 * });
136 * });
137 * }
138 *
139 * Note: Due to some language limitations we have to use different functions
140 * depending on the number of positional arguments of the callback. In the
141 * future, we plan to expose a single `expectAsync` function that can be used
142 * regardless of the number of positional arguments. This requires new langauge
143 * features or fixes to the current spec (e.g. see
144 * [Issue 2706](http://dartbug.com/2706)).
145 */
146 library unittest; 135 library unittest;
147 136
148 import 'dart:async'; 137 import 'dart:async';
149 import 'dart:collection'; 138 import 'dart:collection';
150 import 'dart:isolate'; 139 import 'dart:isolate';
151 import 'package:stack_trace/stack_trace.dart'; 140 import 'package:stack_trace/stack_trace.dart';
152 141
153 import 'package:matcher/matcher.dart' show DefaultFailureHandler, 142 import 'package:matcher/matcher.dart' show DefaultFailureHandler,
154 configureExpectFailureHandler, TestFailure, wrapAsync; 143 configureExpectFailureHandler, TestFailure, wrapAsync;
155 export 'package:matcher/matcher.dart'; 144 export 'package:matcher/matcher.dart';
156 145
157 import 'src/utils.dart'; 146 import 'src/utils.dart';
158 147
159 part 'src/configuration.dart'; 148 part 'src/configuration.dart';
160 part 'src/group_context.dart'; 149 part 'src/group_context.dart';
161 part 'src/simple_configuration.dart'; 150 part 'src/simple_configuration.dart';
162 part 'src/spread_args_helper.dart'; 151 part 'src/spread_args_helper.dart';
163 part 'src/test_case.dart'; 152 part 'src/test_case.dart';
164 153
165 Configuration _config; 154 Configuration _config;
166 155
167 /** 156 /// [Configuration] used by the unittest library. Note that if a
168 * [Configuration] used by the unittest library. Note that if a 157 /// configuration has not been set, calling this getter will create
169 * configuration has not been set, calling this getter will create 158 /// a default configuration.
170 * a default configuration.
171 */
172 Configuration get unittestConfiguration { 159 Configuration get unittestConfiguration {
173 if (_config == null) { 160 if (_config == null) {
174 _config = new Configuration(); 161 _config = new Configuration();
175 } 162 }
176 return _config; 163 return _config;
177 } 164 }
178 165
179 /** 166 /// Sets the [Configuration] used by the unittest library.
180 * Sets the [Configuration] used by the unittest library. 167 ///
181 * 168 /// Throws a [StateError] if there is an existing, incompatible value.
182 * Throws a [StateError] if there is an existing, incompatible value.
183 */
184 void set unittestConfiguration(Configuration value) { 169 void set unittestConfiguration(Configuration value) {
185 if (!identical(_config, value)) { 170 if (!identical(_config, value)) {
186 if (_config != null) { 171 if (_config != null) {
187 throw new StateError('unittestConfiguration has already been set'); 172 throw new StateError('unittestConfiguration has already been set');
188 } 173 }
189 _config = value; 174 _config = value;
190 } 175 }
191 } 176 }
192 177
193 /** 178 /// Can be called by tests to log status. Tests should use this
194 * Can be called by tests to log status. Tests should use this 179 /// instead of [print].
195 * instead of [print].
196 */
197 void logMessage(String message) => 180 void logMessage(String message) =>
198 _config.onLogMessage(currentTestCase, message); 181 _config.onLogMessage(currentTestCase, message);
199 182
200 /** Separator used between group names and test names. */ 183 /// Separator used between group names and test names.
201 String groupSep = ' '; 184 String groupSep = ' ';
202 185
203 final List<TestCase> _testCases = new List<TestCase>(); 186 final List<TestCase> _testCases = new List<TestCase>();
204 187
205 /** Tests executed in this suite. */ 188 /// Tests executed in this suite.
206 final List<TestCase> testCases = new UnmodifiableListView<TestCase>(_testCases); 189 final List<TestCase> testCases = new UnmodifiableListView<TestCase>(_testCases);
207 190
208 /** 191 /// Interval (in msecs) after which synchronous tests will insert an async
209 * Interval (in msecs) after which synchronous tests will insert an async 192 /// delay to allow DOM or other updates.
210 * delay to allow DOM or other updates.
211 */
212 const int BREATH_INTERVAL = 200; 193 const int BREATH_INTERVAL = 200;
213 194
214 /** 195 /// The set of tests to run can be restricted by using [solo_test] and
215 * The set of tests to run can be restricted by using [solo_test] and 196 /// [solo_group].
216 * [solo_group]. 197 /// As groups can be nested we use a counter to keep track of the nest level
217 * As groups can be nested we use a counter to keep track of the nest level 198 /// of soloing, and a flag to tell if we have seen any solo tests.
218 * of soloing, and a flag to tell if we have seen any solo tests.
219 */
220 int _soloNestingLevel = 0; 199 int _soloNestingLevel = 0;
221 bool _soloTestSeen = false; 200 bool _soloTestSeen = false;
222 201
223 // We use a 'dummy' context for the top level to eliminate null 202 // We use a 'dummy' context for the top level to eliminate null
224 // checks when querying the context. This allows us to easily 203 // checks when querying the context. This allows us to easily
225 // support top-level setUp/tearDown functions as well. 204 // support top-level setUp/tearDown functions as well.
226 final _rootContext = new _GroupContext(); 205 final _rootContext = new _GroupContext();
227 _GroupContext _currentContext = _rootContext; 206 _GroupContext _currentContext = _rootContext;
228 207
229 /** 208 /// Represents the index of the currently running test case
230 * Represents the index of the currently running test case 209 /// == -1 implies the test system is not running
231 * == -1 implies the test system is not running 210 /// == [number of test cases] is a short-lived state flagging that the last test
232 * == [number of test cases] is a short-lived state flagging that the last test 211 /// has completed
233 * has completed
234 */
235 int _currentTestCaseIndex = -1; 212 int _currentTestCaseIndex = -1;
236 213
237 /** [TestCase] currently being executed. */ 214 /// [TestCase] currently being executed.
238 TestCase get currentTestCase => 215 TestCase get currentTestCase =>
239 (_currentTestCaseIndex >= 0 && _currentTestCaseIndex < testCases.length) 216 (_currentTestCaseIndex >= 0 && _currentTestCaseIndex < testCases.length)
240 ? testCases[_currentTestCaseIndex] 217 ? testCases[_currentTestCaseIndex]
241 : null; 218 : null;
242 219
243 /** Whether the framework is in an initialized state. */ 220 /// Whether the framework is in an initialized state.
244 bool _initialized = false; 221 bool _initialized = false;
245 222
246 String _uncaughtErrorMessage = null; 223 String _uncaughtErrorMessage = null;
247 224
248 /** Time since we last gave non-sync code a chance to be scheduled. */ 225 /// Time since we last gave non-sync code a chance to be scheduled.
249 int _lastBreath = new DateTime.now().millisecondsSinceEpoch; 226 int _lastBreath = new DateTime.now().millisecondsSinceEpoch;
250 227
251 /* Test case result strings. */ 228 /* Test case result strings. */
252 // TODO(gram) we should change these constants to use a different string 229 // TODO(gram) we should change these constants to use a different string
253 // (so that writing 'FAIL' in the middle of a test doesn't 230 // (so that writing 'FAIL' in the middle of a test doesn't
254 // imply that the test fails). We can't do it without also changing 231 // imply that the test fails). We can't do it without also changing
255 // the testrunner and test.dart though. 232 // the testrunner and test.dart though.
256 /// Result string for a passing test case. 233 /// Result string for a passing test case.
257 const PASS = 'pass'; 234 const PASS = 'pass';
258 /// Result string for a failing test case. 235 /// Result string for a failing test case.
259 const FAIL = 'fail'; 236 const FAIL = 'fail';
260 /// Result string for an test case with an error. 237 /// Result string for an test case with an error.
261 const ERROR = 'error'; 238 const ERROR = 'error';
262 239
263 /** 240 /// Creates a new test case with the given description and body. The
264 * Creates a new test case with the given description and body. The 241 /// description will include the descriptions of any surrounding group()
265 * description will include the descriptions of any surrounding group() 242 /// calls.
266 * calls.
267 */
268 void test(String spec, TestFunction body) { 243 void test(String spec, TestFunction body) {
269 _requireNotRunning(); 244 _requireNotRunning();
270 ensureInitialized(); 245 ensureInitialized();
271 if (!_soloTestSeen || _soloNestingLevel > 0) { 246 if (!_soloTestSeen || _soloNestingLevel > 0) {
272 var testcase = new TestCase._internal(testCases.length + 1, _fullSpec(spec), 247 var testcase = new TestCase._internal(testCases.length + 1, _fullSpec(spec),
273 body); 248 body);
274 _testCases.add(testcase); 249 _testCases.add(testcase);
275 } 250 }
276 } 251 }
277 252
278 /** Convenience function for skipping a test. */ 253 /// Convenience function for skipping a test.
279 void skip_test(String spec, TestFunction body) {} 254 void skip_test(String spec, TestFunction body) {}
280 255
281 /** 256 /// Creates a new test case with the given description and body. The
282 * Creates a new test case with the given description and body. The 257 /// description will include the descriptions of any surrounding group()
283 * description will include the descriptions of any surrounding group() 258 /// calls.
284 * calls. 259 ///
285 * 260 /// If we use [solo_test] (or [solo_group]) instead of test, then all non-solo
286 * If we use [solo_test] (or [solo_group]) instead of test, then all non-solo 261 /// tests will be disabled. Note that if we use [solo_group], all tests in
287 * tests will be disabled. Note that if we use [solo_group], all tests in 262 /// the group will be enabled, regardless of whether they use [test] or
288 * the group will be enabled, regardless of whether they use [test] or 263 /// [solo_test], or whether they are in a nested [group] vs [solo_group]. Put
289 * [solo_test], or whether they are in a nested [group] vs [solo_group]. Put 264 /// another way, if there are any calls to [solo_test] or [solo_group] in a test
290 * another way, if there are any calls to [solo_test] or [solo_group] in a test 265 /// file, all tests that are not inside a [solo_group] will be disabled unless
291 * file, all tests that are not inside a [solo_group] will be disabled unless 266 /// they are [solo_test]s.
292 * they are [solo_test]s. 267 ///
293 * 268 /// [skip_test] and [skip_group] take precedence over soloing, by virtue of the
294 * [skip_test] and [skip_group] take precedence over soloing, by virtue of the 269 /// fact that they are effectively no-ops.
295 * fact that they are effectively no-ops.
296 */
297 void solo_test(String spec, TestFunction body) { 270 void solo_test(String spec, TestFunction body) {
298 _requireNotRunning(); 271 _requireNotRunning();
299 ensureInitialized(); 272 ensureInitialized();
300 if (!_soloTestSeen) { 273 if (!_soloTestSeen) {
301 _soloTestSeen = true; 274 _soloTestSeen = true;
302 // This is the first solo-ed test. Discard all tests up to now. 275 // This is the first solo-ed test. Discard all tests up to now.
303 _testCases.clear(); 276 _testCases.clear();
304 } 277 }
305 ++_soloNestingLevel; 278 ++_soloNestingLevel;
306 try { 279 try {
307 test(spec, body); 280 test(spec, body);
308 } finally { 281 } finally {
309 --_soloNestingLevel; 282 --_soloNestingLevel;
310 } 283 }
311 } 284 }
312 285
313 /** 286 /// Indicate that [callback] is expected to be called a [count] number of times
314 * Indicate that [callback] is expected to be called a [count] number of times 287 /// (by default 1). The unittest framework will wait for the callback to run the
315 * (by default 1). The unittest framework will wait for the callback to run the 288 /// specified [count] times before it continues with the following test. Using
316 * specified [count] times before it continues with the following test. Using 289 /// [expectAsync] will also ensure that errors that occur within [callback] are
317 * [expectAsync] will also ensure that errors that occur within [callback] are 290 /// tracked and reported. [callback] should take 0 positional arguments (named
318 * tracked and reported. [callback] should take 0 positional arguments (named 291 /// arguments are not supported). [id] can be used to provide more
319 * arguments are not supported). [id] can be used to provide more 292 /// descriptive error messages if the callback is called more often than
320 * descriptive error messages if the callback is called more often than 293 /// expected. [max] can be used to specify an upper bound on the number of
321 * expected. [max] can be used to specify an upper bound on the number of 294 /// calls; if this is exceeded the test will fail (or be marked as in error if
322 * calls; if this is exceeded the test will fail (or be marked as in error if 295 /// it was already complete). A value of 0 for [max] (the default) will set
323 * it was already complete). A value of 0 for [max] (the default) will set 296 /// the upper bound to the same value as [count]; i.e. the callback should be
324 * the upper bound to the same value as [count]; i.e. the callback should be 297 /// called exactly [count] times. A value of -1 for [max] will mean no upper
325 * called exactly [count] times. A value of -1 for [max] will mean no upper 298 /// bound.
326 * bound.
327 */
328 Function expectAsync(Function callback, 299 Function expectAsync(Function callback,
329 {int count: 1, int max: 0, String id}) => 300 {int count: 1, int max: 0, String id}) =>
330 new _SpreadArgsHelper(callback, count, max, id).func; 301 new _SpreadArgsHelper(callback, count, max, id).func;
331 302
332 /** 303 /// *Deprecated*
333 * *Deprecated* 304 ///
334 * 305 /// Use [expectAsync] instead.
335 * Use [expectAsync] instead.
336 */
337 @deprecated 306 @deprecated
338 Function expectAsync0(Function callback, 307 Function expectAsync0(Function callback,
339 {int count: 1, int max: 0, String id}) => 308 {int count: 1, int max: 0, String id}) =>
340 expectAsync(callback, count: count, max: max, id: id); 309 expectAsync(callback, count: count, max: max, id: id);
341 310
342 /** 311 /// *Deprecated*
343 * *Deprecated* 312 ///
344 * 313 /// Use [expectAsync] instead.
345 * Use [expectAsync] instead.
346 */
347 @deprecated 314 @deprecated
348 Function expectAsync1(Function callback, 315 Function expectAsync1(Function callback,
349 {int count: 1, int max: 0, String id}) => 316 {int count: 1, int max: 0, String id}) =>
350 expectAsync(callback, count: count, max: max, id: id); 317 expectAsync(callback, count: count, max: max, id: id);
351 318
352 /** 319 /// *Deprecated*
353 * *Deprecated* 320 ///
354 * 321 /// Use [expectAsync] instead.
355 * Use [expectAsync] instead.
356 */
357 @deprecated 322 @deprecated
358 Function expectAsync2(Function callback, 323 Function expectAsync2(Function callback,
359 {int count: 1, int max: 0, String id}) => 324 {int count: 1, int max: 0, String id}) =>
360 expectAsync(callback, count: count, max: max, id: id); 325 expectAsync(callback, count: count, max: max, id: id);
361 326
362 /** 327 /// Indicate that [callback] is expected to be called until [isDone] returns
363 * Indicate that [callback] is expected to be called until [isDone] returns 328 /// true. The unittest framework check [isDone] after each callback and only
364 * true. The unittest framework check [isDone] after each callback and only 329 /// when it returns true will it continue with the following test. Using
365 * when it returns true will it continue with the following test. Using 330 /// [expectAsyncUntil] will also ensure that errors that occur within
366 * [expectAsyncUntil] will also ensure that errors that occur within 331 /// [callback] are tracked and reported. [callback] should take 0 positional
367 * [callback] are tracked and reported. [callback] should take 0 positional 332 /// arguments (named arguments are not supported). [id] can be used to
368 * arguments (named arguments are not supported). [id] can be used to 333 /// identify the callback in error messages (for example if it is called
369 * identify the callback in error messages (for example if it is called 334 /// after the test case is complete).
370 * after the test case is complete).
371 */
372 Function expectAsyncUntil(Function callback, bool isDone(), {String id}) => 335 Function expectAsyncUntil(Function callback, bool isDone(), {String id}) =>
373 new _SpreadArgsHelper(callback, 0, -1, id, isDone: isDone).func; 336 new _SpreadArgsHelper(callback, 0, -1, id, isDone: isDone).func;
374 337
375 /** 338 /// *Deprecated*
376 * *Deprecated* 339 ///
377 * 340 /// Use [expectAsyncUntil] instead.
378 * Use [expectAsyncUntil] instead.
379 */
380 @deprecated 341 @deprecated
381 Function expectAsyncUntil0(Function callback, Function isDone, {String id}) => 342 Function expectAsyncUntil0(Function callback, Function isDone, {String id}) =>
382 expectAsyncUntil(callback, isDone, id: id); 343 expectAsyncUntil(callback, isDone, id: id);
383 344
384 /** 345 /// *Deprecated*
385 * *Deprecated* 346 ///
386 * 347 /// Use [expectAsyncUntil] instead.
387 * Use [expectAsyncUntil] instead.
388 */
389 @deprecated 348 @deprecated
390 Function expectAsyncUntil1(Function callback, Function isDone, {String id}) => 349 Function expectAsyncUntil1(Function callback, Function isDone, {String id}) =>
391 expectAsyncUntil(callback, isDone, id: id); 350 expectAsyncUntil(callback, isDone, id: id);
392 351
393 /** 352 /// *Deprecated*
394 * *Deprecated* 353 ///
395 * 354 /// Use [expectAsyncUntil] instead.
396 * Use [expectAsyncUntil] instead.
397 */
398 @deprecated 355 @deprecated
399 Function expectAsyncUntil2(Function callback, Function isDone, {String id}) => 356 Function expectAsyncUntil2(Function callback, Function isDone, {String id}) =>
400 expectAsyncUntil(callback, isDone, id: id); 357 expectAsyncUntil(callback, isDone, id: id);
401 358
402 /** 359 /// *Deprecated*
403 * *Deprecated* 360 ///
404 * 361 /// All tests are now run an isolated [Zone].
405 * All tests are now run an isolated [Zone]. 362 ///
406 * 363 /// You can safely remove calls to this method.
407 * You can safely remove calls to this method.
408 */
409 @deprecated 364 @deprecated
410 Function protectAsync0(Function callback, {String id}) { 365 Function protectAsync0(Function callback, {String id}) {
411 return callback; 366 return callback;
412 } 367 }
413 368
414 /** 369 /// *Deprecated*
415 * *Deprecated* 370 ///
416 * 371 /// All tests are now run an isolated [Zone].
417 * All tests are now run an isolated [Zone]. 372 ///
418 * 373 /// You can safely remove calls to this method.
419 * You can safely remove calls to this method.
420 */
421 @deprecated 374 @deprecated
422 Function protectAsync1(Function callback, {String id}) { 375 Function protectAsync1(Function callback, {String id}) {
423 return callback; 376 return callback;
424 } 377 }
425 378
426 /** 379 /// *Deprecated*
427 * *Deprecated* 380 ///
428 * 381 /// All tests are now run an isolated [Zone].
429 * All tests are now run an isolated [Zone]. 382 ///
430 * 383 /// You can safely remove calls to this method.
431 * You can safely remove calls to this method.
432 */
433 @deprecated 384 @deprecated
434 Function protectAsync2(Function callback, {String id}) { 385 Function protectAsync2(Function callback, {String id}) {
435 return callback; 386 return callback;
436 } 387 }
437 388
438 /** 389 /// Creates a new named group of tests. Calls to group() or test() within the
439 * Creates a new named group of tests. Calls to group() or test() within the 390 /// body of the function passed to this will inherit this group's description.
440 * body of the function passed to this will inherit this group's description.
441 */
442 void group(String description, void body()) { 391 void group(String description, void body()) {
443 ensureInitialized(); 392 ensureInitialized();
444 _requireNotRunning(); 393 _requireNotRunning();
445 _currentContext = new _GroupContext(_currentContext, description); 394 _currentContext = new _GroupContext(_currentContext, description);
446 try { 395 try {
447 body(); 396 body();
448 } catch (e, trace) { 397 } catch (e, trace) {
449 var stack = (trace == null) ? '' : ': ${trace.toString()}'; 398 var stack = (trace == null) ? '' : ': ${trace.toString()}';
450 _uncaughtErrorMessage = "${e.toString()}$stack"; 399 _uncaughtErrorMessage = "${e.toString()}$stack";
451 } finally { 400 } finally {
452 // Now that the group is over, restore the previous one. 401 // Now that the group is over, restore the previous one.
453 _currentContext = _currentContext.parent; 402 _currentContext = _currentContext.parent;
454 } 403 }
455 } 404 }
456 405
457 /** Like [skip_test], but for groups. */ 406 /// Like [skip_test], but for groups.
458 void skip_group(String description, void body()) {} 407 void skip_group(String description, void body()) {}
459 408
460 /** Like [solo_test], but for groups. */ 409 /// Like [solo_test], but for groups.
461 void solo_group(String description, void body()) { 410 void solo_group(String description, void body()) {
462 _requireNotRunning(); 411 _requireNotRunning();
463 ensureInitialized(); 412 ensureInitialized();
464 if (!_soloTestSeen) { 413 if (!_soloTestSeen) {
465 _soloTestSeen = true; 414 _soloTestSeen = true;
466 // This is the first solo-ed group. Discard all tests up to now. 415 // This is the first solo-ed group. Discard all tests up to now.
467 _testCases.clear(); 416 _testCases.clear();
468 } 417 }
469 ++_soloNestingLevel; 418 ++_soloNestingLevel;
470 try { 419 try {
471 group(description, body); 420 group(description, body);
472 } finally { 421 } finally {
473 --_soloNestingLevel; 422 --_soloNestingLevel;
474 } 423 }
475 } 424 }
476 425
477 /** 426 /// Register a [setUp] function for a test [group]. This function will
478 * Register a [setUp] function for a test [group]. This function will 427 /// be called before each test in the group is run.
479 * be called before each test in the group is run. 428 /// [setUp] and [tearDown] should be called within the [group] before any
480 * [setUp] and [tearDown] should be called within the [group] before any 429 /// calls to [test]. The [setupTest] function can be asynchronous; in this
481 * calls to [test]. The [setupTest] function can be asynchronous; in this 430 /// case it must return a [Future].
482 * case it must return a [Future].
483 */
484 void setUp(Function setupTest) { 431 void setUp(Function setupTest) {
485 _requireNotRunning(); 432 _requireNotRunning();
486 _currentContext.testSetup = setupTest; 433 _currentContext.testSetup = setupTest;
487 } 434 }
488 435
489 /** 436 /// Register a [tearDown] function for a test [group]. This function will
490 * Register a [tearDown] function for a test [group]. This function will 437 /// be called after each test in the group is run. Note that if groups
491 * be called after each test in the group is run. Note that if groups 438 /// are nested only the most locally scoped [teardownTest] function will be run.
492 * are nested only the most locally scoped [teardownTest] function will be run. 439 /// [setUp] and [tearDown] should be called within the [group] before any
493 * [setUp] and [tearDown] should be called within the [group] before any 440 /// calls to [test]. The [teardownTest] function can be asynchronous; in this
494 * calls to [test]. The [teardownTest] function can be asynchronous; in this 441 /// case it must return a [Future].
495 * case it must return a [Future].
496 */
497 void tearDown(Function teardownTest) { 442 void tearDown(Function teardownTest) {
498 _requireNotRunning(); 443 _requireNotRunning();
499 _currentContext.testTeardown = teardownTest; 444 _currentContext.testTeardown = teardownTest;
500 } 445 }
501 446
502 /** Advance to the next test case. */ 447 /// Advance to the next test case.
503 void _nextTestCase() { 448 void _nextTestCase() {
504 _currentTestCaseIndex++; 449 _currentTestCaseIndex++;
505 _runTest(); 450 _runTest();
506 } 451 }
507 452
508 /** Handle errors that happen outside the tests. */ 453 /// Handle errors that happen outside the tests.
509 // TODO(vsm): figure out how to expose the stack trace here 454 // TODO(vsm): figure out how to expose the stack trace here
510 // Currently e.message works in dartium, but not in dartc. 455 // Currently e.message works in dartium, but not in dartc.
511 void handleExternalError(e, String message, [stack]) { 456 void handleExternalError(e, String message, [stack]) {
512 var msg = '$message\nCaught $e'; 457 var msg = '$message\nCaught $e';
513 458
514 if (currentTestCase != null) { 459 if (currentTestCase != null) {
515 currentTestCase._error(msg, stack); 460 currentTestCase._error(msg, stack);
516 } else { 461 } else {
517 _uncaughtErrorMessage = "$msg: $stack"; 462 _uncaughtErrorMessage = "$msg: $stack";
518 } 463 }
519 } 464 }
520 465
521 /** 466 /// Filter the tests. [testFilter] can be a [RegExp], a [String] or a
522 * Filter the tests. [testFilter] can be a [RegExp], a [String] or a 467 /// predicate function. This is different to enabling/disabling tests
523 * predicate function. This is different to enabling/disabling tests 468 /// in that it removes the tests completely.
524 * in that it removes the tests completely.
525 */
526 void filterTests(testFilter) { 469 void filterTests(testFilter) {
527 var filterFunction; 470 var filterFunction;
528 if (testFilter is String) { 471 if (testFilter is String) {
529 RegExp re = new RegExp(testFilter); 472 RegExp re = new RegExp(testFilter);
530 filterFunction = (t) => re.hasMatch(t.description); 473 filterFunction = (t) => re.hasMatch(t.description);
531 } else if (testFilter is RegExp) { 474 } else if (testFilter is RegExp) {
532 filterFunction = (t) => testFilter.hasMatch(t.description); 475 filterFunction = (t) => testFilter.hasMatch(t.description);
533 } else if (testFilter is Function) { 476 } else if (testFilter is Function) {
534 filterFunction = testFilter; 477 filterFunction = testFilter;
535 } 478 }
536 _testCases.retainWhere(filterFunction); 479 _testCases.retainWhere(filterFunction);
537 } 480 }
538 481
539 /** Runs all queued tests, one at a time. */ 482 /// Runs all queued tests, one at a time.
540 void runTests() { 483 void runTests() {
541 _requireNotRunning(); 484 _requireNotRunning();
542 _ensureInitialized(false); 485 _ensureInitialized(false);
543 _currentTestCaseIndex = 0; 486 _currentTestCaseIndex = 0;
544 _config.onStart(); 487 _config.onStart();
545 _runTest(); 488 _runTest();
546 } 489 }
547 490
548 /** 491 /// *Deprecated*
549 * *Deprecated* 492 ///
550 * 493 /// All tests are now run an isolated [Zone].
551 * All tests are now run an isolated [Zone]. 494 ///
552 * 495 /// You can safely remove calls to this method.
553 * You can safely remove calls to this method.
554 */
555 @deprecated 496 @deprecated
556 guardAsync(Function tryBody) { 497 guardAsync(Function tryBody) {
557 return tryBody(); 498 return tryBody();
558 } 499 }
559 500
560 /** 501 /// Registers that an exception was caught for the current test.
561 * Registers that an exception was caught for the current test.
562 */
563 void registerException(e, [trace]) { 502 void registerException(e, [trace]) {
564 _registerException(currentTestCase, e, trace); 503 _registerException(currentTestCase, e, trace);
565 } 504 }
566 505
567 /** 506 /// Registers that an exception was caught for the current test.
568 * Registers that an exception was caught for the current test.
569 */
570 void _registerException(TestCase testCase, e, [trace]) { 507 void _registerException(TestCase testCase, e, [trace]) {
571 String message = (e is TestFailure) ? e.message : 'Caught $e'; 508 String message = (e is TestFailure) ? e.message : 'Caught $e';
572 if (testCase.result == null) { 509 if (testCase.result == null) {
573 testCase._fail(message, trace); 510 testCase._fail(message, trace);
574 } else { 511 } else {
575 testCase._error(message, trace); 512 testCase._error(message, trace);
576 } 513 }
577 } 514 }
578 515
579 /** 516 /// Runs the next test.
580 * Runs the next test.
581 */
582 void _runTest() { 517 void _runTest() {
583 if (_currentTestCaseIndex >= testCases.length) { 518 if (_currentTestCaseIndex >= testCases.length) {
584 assert(_currentTestCaseIndex == testCases.length); 519 assert(_currentTestCaseIndex == testCases.length);
585 _completeTests(); 520 _completeTests();
586 } else { 521 } else {
587 var testCase = testCases[_currentTestCaseIndex]; 522 var testCase = testCases[_currentTestCaseIndex];
588 Future f = runZoned(testCase._run, onError: (error, stack) { 523 Future f = runZoned(testCase._run, onError: (error, stack) {
589 // TODO(kevmoo) Do a better job of flagging these are async errors. 524 // TODO(kevmoo) Do a better job of flagging these are async errors.
590 // https://code.google.com/p/dart/issues/detail?id=16530 525 // https://code.google.com/p/dart/issues/detail?id=16530
591 _registerException(testCase, error, stack); 526 _registerException(testCase, error, stack);
(...skipping 19 matching lines...) Expand all
611 if ((now - _lastBreath) >= BREATH_INTERVAL) { 546 if ((now - _lastBreath) >= BREATH_INTERVAL) {
612 _lastBreath = now; 547 _lastBreath = now;
613 Timer.run(_nextTestCase); 548 Timer.run(_nextTestCase);
614 } else { 549 } else {
615 scheduleMicrotask(_nextTestCase); // Schedule the next test. 550 scheduleMicrotask(_nextTestCase); // Schedule the next test.
616 } 551 }
617 }); 552 });
618 } 553 }
619 } 554 }
620 555
621 /** Publish results on the page and notify controller. */ 556 /// Publish results on the page and notify controller.
622 void _completeTests() { 557 void _completeTests() {
623 if (!_initialized) return; 558 if (!_initialized) return;
624 int passed = 0; 559 int passed = 0;
625 int failed = 0; 560 int failed = 0;
626 int errors = 0; 561 int errors = 0;
627 562
628 for (TestCase t in testCases) { 563 for (TestCase t in testCases) {
629 switch (t.result) { 564 switch (t.result) {
630 case PASS: passed++; break; 565 case PASS: passed++; break;
631 case FAIL: failed++; break; 566 case FAIL: failed++; break;
632 case ERROR: errors++; break; 567 case ERROR: errors++; break;
633 } 568 }
634 } 569 }
635 _config.onSummary(passed, failed, errors, testCases, _uncaughtErrorMessage); 570 _config.onSummary(passed, failed, errors, testCases, _uncaughtErrorMessage);
636 _config.onDone(passed > 0 && failed == 0 && errors == 0 && 571 _config.onDone(passed > 0 && failed == 0 && errors == 0 &&
637 _uncaughtErrorMessage == null); 572 _uncaughtErrorMessage == null);
638 _initialized = false; 573 _initialized = false;
639 _currentTestCaseIndex = -1; 574 _currentTestCaseIndex = -1;
640 } 575 }
641 576
642 String _fullSpec(String spec) { 577 String _fullSpec(String spec) {
643 var group = '${_currentContext.fullName}'; 578 var group = '${_currentContext.fullName}';
644 if (spec == null) return group; 579 if (spec == null) return group;
645 return group != '' ? '$group$groupSep$spec' : spec; 580 return group != '' ? '$group$groupSep$spec' : spec;
646 } 581 }
647 582
648 /** 583 /// Lazily initializes the test library if not already initialized.
649 * Lazily initializes the test library if not already initialized.
650 */
651 void ensureInitialized() { 584 void ensureInitialized() {
652 _ensureInitialized(true); 585 _ensureInitialized(true);
653 } 586 }
654 587
655 void _ensureInitialized(bool configAutoStart) { 588 void _ensureInitialized(bool configAutoStart) {
656 if (_initialized) { 589 if (_initialized) {
657 return; 590 return;
658 } 591 }
659 _initialized = true; 592 _initialized = true;
660 // Hook our async guard into the matcher library. 593 // Hook our async guard into the matcher library.
661 wrapAsync = (f, [id]) => expectAsync(f, id: id); 594 wrapAsync = (f, [id]) => expectAsync(f, id: id);
662 595
663 _uncaughtErrorMessage = null; 596 _uncaughtErrorMessage = null;
664 597
665 unittestConfiguration.onInit(); 598 unittestConfiguration.onInit();
666 599
667 if (configAutoStart && _config.autoStart) { 600 if (configAutoStart && _config.autoStart) {
668 // Immediately queue the suite up. It will run after a timeout (i.e. after 601 // Immediately queue the suite up. It will run after a timeout (i.e. after
669 // main() has returned). 602 // main() has returned).
670 scheduleMicrotask(runTests); 603 scheduleMicrotask(runTests);
671 } 604 }
672 } 605 }
673 606
674 /** Select a solo test by ID. */ 607 /// Select a solo test by ID.
675 void setSoloTest(int id) => _testCases.retainWhere((t) => t.id == id); 608 void setSoloTest(int id) => _testCases.retainWhere((t) => t.id == id);
676 609
677 /** Enable/disable a test by ID. */ 610 /// Enable/disable a test by ID.
678 void _setTestEnabledState(int testId, bool state) { 611 void _setTestEnabledState(int testId, bool state) {
679 // Try fast path first. 612 // Try fast path first.
680 if (testCases.length > testId && testCases[testId].id == testId) { 613 if (testCases.length > testId && testCases[testId].id == testId) {
681 testCases[testId]._enabled = state; 614 testCases[testId]._enabled = state;
682 } else { 615 } else {
683 for (var i = 0; i < testCases.length; i++) { 616 for (var i = 0; i < testCases.length; i++) {
684 if (testCases[i].id == testId) { 617 if (testCases[i].id == testId) {
685 testCases[i]._enabled = state; 618 testCases[i]._enabled = state;
686 break; 619 break;
687 } 620 }
688 } 621 }
689 } 622 }
690 } 623 }
691 624
692 /** Enable a test by ID. */ 625 /// Enable a test by ID.
693 void enableTest(int testId) => _setTestEnabledState(testId, true); 626 void enableTest(int testId) => _setTestEnabledState(testId, true);
694 627
695 /** Disable a test by ID. */ 628 /// Disable a test by ID.
696 void disableTest(int testId) => _setTestEnabledState(testId, false); 629 void disableTest(int testId) => _setTestEnabledState(testId, false);
697 630
698 /** Signature for a test function. */ 631 /// Signature for a test function.
699 typedef dynamic TestFunction(); 632 typedef dynamic TestFunction();
700 633
701 /** 634 /// A flag that controls whether we hide unittest and core library details in
702 * A flag that controls whether we hide unittest and core library details in 635 /// exception stacks.
703 * exception stacks. 636 ///
704 * 637 /// Useful to disable when debugging unittest or matcher customizations.
705 * Useful to disable when debugging unittest or matcher customizations.
706 */
707 bool formatStacks = true; 638 bool formatStacks = true;
708 639
709 /** 640 /// A flag that controls whether we try to filter out irrelevant frames from
710 * A flag that controls whether we try to filter out irrelevant frames from 641 /// the stack trace. Requires formatStacks to be set.
711 * the stack trace. Requires formatStacks to be set.
712 */
713 bool filterStacks = true; 642 bool filterStacks = true;
714 643
715 void _requireNotRunning() { 644 void _requireNotRunning() {
716 if (_currentTestCaseIndex != -1) { 645 if (_currentTestCaseIndex != -1) {
717 throw new StateError('Not allowed when tests are running.'); 646 throw new StateError('Not allowed when tests are running.');
718 } 647 }
719 } 648 }
720 649
721 /** 650 /// Returns a Trace object from a StackTrace object or a String, or the
722 * Returns a Trace object from a StackTrace object or a String, or the 651 /// unchanged input if formatStacks is false;
723 * unchanged input if formatStacks is false;
724 */
725 Trace _getTrace(stack) { 652 Trace _getTrace(stack) {
726 Trace trace; 653 Trace trace;
727 if (stack == null || !formatStacks) return null; 654 if (stack == null || !formatStacks) return null;
728 if (stack is String) { 655 if (stack is String) {
729 trace = new Trace.parse(stack); 656 trace = new Trace.parse(stack);
730 } else if (stack is StackTrace) { 657 } else if (stack is StackTrace) {
731 trace = new Trace.from(stack); 658 trace = new Trace.from(stack);
732 } else { 659 } else {
733 throw new Exception('Invalid stack type ${stack.runtimeType} for $stack.'); 660 throw new Exception('Invalid stack type ${stack.runtimeType} for $stack.');
734 } 661 }
735 662
736 if (!filterStacks) return trace; 663 if (!filterStacks) return trace;
737 664
738 // Format the stack trace by removing everything above TestCase._runTest, 665 // Format the stack trace by removing everything above TestCase._runTest,
739 // which is usually going to be irrelevant. Also fold together unittest and 666 // which is usually going to be irrelevant. Also fold together unittest and
740 // core library calls so only the function the user called is visible. 667 // core library calls so only the function the user called is visible.
741 return new Trace(trace.frames.takeWhile((frame) { 668 return new Trace(trace.frames.takeWhile((frame) {
742 return frame.package != 'unittest' || frame.member != 'TestCase._runTest'; 669 return frame.package != 'unittest' || frame.member != 'TestCase._runTest';
743 })).terse.foldFrames((frame) => frame.package == 'unittest' || frame.isCore); 670 })).terse.foldFrames((frame) => frame.package == 'unittest' || frame.isCore);
744 } 671 }
OLDNEW
« no previous file with comments | « pkg/unittest/lib/src/utils.dart ('k') | pkg/unittest/lib/vm_config.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698