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

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

Issue 10449091: Removed asyncTest and improved comments. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/html/fileapi_test.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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 /**
6 * A library for writing dart unit tests. 6 * A library for writing dart unit tests.
7 * 7 *
8 * To import this library, specify the relative path to 8 * To import this library, specify the relative path to
9 * lib/unittest/unittest.dart. 9 * lib/unittest/unittest.dart.
10 * 10 *
11 * ##Concepts## 11 * ##Concepts##
12 * 12 *
13 * * Tests: Tests are specified via the top-level function [test], they can be 13 * * Tests: Tests are specified via the top-level function [test], they can be
14 * organized together using [group]. 14 * organized together using [group].
15 * * Checks: Test expectations can be specified via [expect] (see methods in 15 * * Checks: Test expectations can be specified via [expect] (see methods in
16 * [Expectation]), [expectThrow], or using assertions with the [Expect] 16 * [Expectation]), [expectThrow], or using assertions with the [Expect]
17 * class. 17 * class.
18 * * Configuration: The framework can be adapted by calling [configure] with a 18 * * Configuration: The framework can be adapted by calling [configure] with a
19 * [Configuration]. Common configurations can be found in this package 19 * [Configuration]. Common configurations can be found in this package
20 * under: 'dom\_config.dart', 'html\_config.dart', and 'vm\_config.dart'. 20 * under: 'dom\_config.dart' (deprecated), 'html\_config.dart' (for running
21 * tests compiled to Javascript in a browser), and 'vm\_config.dart' (for
22 * running native Dart tests on the VM).
21 * 23 *
22 * ##Examples## 24 * ##Examples##
23 * 25 *
24 * A trivial test: 26 * A trivial test:
25 * 27 *
26 * #import('path-to-dart/lib/unittest/unitest.dart'); 28 * #import('path-to-dart/lib/unittest/unitest.dart');
27 * main() { 29 * main() {
28 * test('this is a test', () { 30 * test('this is a test', () {
29 * int x = 2 + 3; 31 * int x = 2 + 3;
30 * expect(x).equals(5); 32 * expect(x).equals(5);
(...skipping 29 matching lines...) Expand all
60 * }); 62 * });
61 * }); 63 * });
62 * group('group B', () { 64 * group('group B', () {
63 * test('this B.1', () { 65 * test('this B.1', () {
64 * int x = 2 + 3; 66 * int x = 2 + 3;
65 * expect(x).equals(5); 67 * expect(x).equals(5);
66 * }); 68 * });
67 * }); 69 * });
68 * } 70 * }
69 * 71 *
70 * Asynchronous tests: if callbacks expect between 0 and 2 positional arguments. 72 * Asynchronous tests: if callbacks expect between 0 and 2 positional arguments,
73 * depending on the suffix of expectAsyncX(). expectAsyncX() will wrap a
74 * function into a new callback and will not consider the test complete until
75 * that callback is run. A count argument can be provided to specify the number
76 * of times the callback should be called (the default is 1).
71 * 77 *
72 * #import('path-to-dart/lib/unittest/unitest.dart'); 78 * #import('path-to-dart/lib/unittest/unitest.dart');
73 * #import('dart:dom_deprecated'); 79 * #import('dart:dom_deprecated');
74 * main() { 80 * main() {
75 * test('calllback is executed once', () { 81 * test('calllback is executed once', () {
76 * // wrap the callback of an asynchronous call with [expectAsync0] if 82 * // wrap the callback of an asynchronous call with [expectAsync0] if
77 * // the callback takes 0 arguments... 83 * // the callback takes 0 arguments...
78 * window.setTimeout(expectAsync0(() { 84 * window.setTimeout(expectAsync0(() {
79 * int x = 2 + 3; 85 * int x = 2 + 3;
80 * expect(x).equals(5); 86 * expect(x).equals(5);
81 * }), 0); 87 * }), 0);
82 * }); 88 * });
83 * 89 *
84 * test('calllback is executed twice', () { 90 * test('calllback is executed twice', () {
85 * var callback = expectAsync0(() { 91 * var callback = expectAsync0(() {
86 * int x = 2 + 3; 92 * int x = 2 + 3;
87 * expect(x).equals(5); 93 * expect(x).equals(5);
88 * }, count: 2); // <-- we can indicate multiplicity to [expectAsync0] 94 * }, count: 2); // <-- we can indicate multiplicity to [expectAsync0]
89 * window.setTimeout(callback, 0); 95 * window.setTimeout(callback, 0);
90 * window.setTimeout(callback, 0); 96 * window.setTimeout(callback, 0);
91 * }); 97 * });
92 * } 98 * }
93 * 99 *
100 * expectAsyncX() will wrap the callback code in a try/catch handler to handle
101 * exceptions (treated as test failures). There may be times when the number of
102 * times a callback should be called is non-deterministic. In this case a dummy
103 * callback can be created with expectAsync0((){}) and this can be called from
104 * the real callback when it is finally complete. In this case the body of the
105 * callback should be protected within a call to guardAsync(); this will ensure
106 * that exceptions are properly handled.
107 *
94 * Note: due to some language limitations we have to use different functions 108 * Note: due to some language limitations we have to use different functions
95 * depending on the number of positional arguments of the callback. In the 109 * depending on the number of positional arguments of the callback. In the
96 * future, we plan to expose a single `expectAsync` function that can be used 110 * future, we plan to expose a single `expectAsync` function that can be used
97 * regardless of the number of positional arguments. This requires new langauge 111 * regardless of the number of positional arguments. This requires new langauge
98 * features or fixes to the current spec (e.g. see 112 * features or fixes to the current spec (e.g. see
99 * [Issue 2706](http://dartbug.com/2706)). 113 * [Issue 2706](http://dartbug.com/2706)).
100 * 114 *
101 * Meanwhile, we plan to add this alternative API for callbacks of more than 2 115 * Meanwhile, we plan to add this alternative API for callbacks of more than 2
102 * arguments or that take named parameters. (this is not implemented yet, 116 * arguments or that take named parameters. (this is not implemented yet,
103 * but will be coming here soon). 117 * but will be coming here soon).
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 * description will include the descriptions of any surrounding group() 229 * description will include the descriptions of any surrounding group()
216 * calls. 230 * calls.
217 */ 231 */
218 void test(String spec, TestFunction body) { 232 void test(String spec, TestFunction body) {
219 ensureInitialized(); 233 ensureInitialized();
220 234
221 _tests.add(new TestCase(_tests.length + 1, _fullSpec(spec), body, 0)); 235 _tests.add(new TestCase(_tests.length + 1, _fullSpec(spec), body, 0));
222 } 236 }
223 237
224 /** 238 /**
225 * Creates a new async test case with the given description and body. The
226 * description will include the descriptions of any surrounding group()
227 * calls.
228 */
229 // TODO(sigmund): deprecate this API
230 void asyncTest(String spec, int callbacks, TestFunction body) {
231 ensureInitialized();
232
233 final testCase = new TestCase(
234 _tests.length + 1, _fullSpec(spec), body, callbacks);
235 _tests.add(testCase);
236
237 if (callbacks < 1) {
238 testCase.error(
239 'Async tests must wait for at least one callback ', '');
240 }
241 }
242
243 /**
244 * Creates a new test case with the given description and body. The 239 * Creates a new test case with the given description and body. The
245 * description will include the descriptions of any surrounding group() 240 * description will include the descriptions of any surrounding group()
246 * calls. 241 * calls.
247 * 242 *
248 * "solo_" means that this will be the only test that is run. All other tests 243 * "solo_" means that this will be the only test that is run. All other tests
249 * will be skipped. This is a convenience function to let you quickly isolate 244 * will be skipped. This is a convenience function to let you quickly isolate
250 * a single test by adding "solo_" before it to temporarily disable all other 245 * a single test by adding "solo_" before it to temporarily disable all other
251 * tests. 246 * tests.
252 */ 247 */
253 void solo_test(String spec, TestFunction body) { 248 void solo_test(String spec, TestFunction body) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 } else if (arg3 == _sentinel) { 296 } else if (arg3 == _sentinel) {
302 return callback(arg0, arg1, arg2); 297 return callback(arg0, arg1, arg2);
303 } else if (arg4 == _sentinel) { 298 } else if (arg4 == _sentinel) {
304 return callback(arg0, arg1, arg2, arg3); 299 return callback(arg0, arg1, arg2, arg3);
305 } else { 300 } else {
306 testCase.error( 301 testCase.error(
307 'unittest lib does not support callbacks with more than 4 arguments', 302 'unittest lib does not support callbacks with more than 4 arguments',
308 ''); 303 '');
309 _state = _UNCAUGHT_ERROR; 304 _state = _UNCAUGHT_ERROR;
310 } 305 }
311 }, () { if (calls == expectedCalls) callbackDone(); }); 306 }, () { if (calls == expectedCalls) _callbackDone(); });
312 } 307 }
313 308
314 invoke0() { 309 invoke0() {
315 return guardAsync( 310 return guardAsync(
316 () => _incrementCall() ? callback() : null, 311 () => _incrementCall() ? callback() : null,
317 () { if (calls == expectedCalls) callbackDone(); }); 312 () { if (calls == expectedCalls) _callbackDone(); });
318 } 313 }
319 314
320 invoke1(arg1) { 315 invoke1(arg1) {
321 return guardAsync( 316 return guardAsync(
322 () => _incrementCall() ? callback(arg1) : null, 317 () => _incrementCall() ? callback(arg1) : null,
323 () { if (calls == expectedCalls) callbackDone(); }); 318 () { if (calls == expectedCalls) _callbackDone(); });
324 } 319 }
325 320
326 invoke2(arg1, arg2) { 321 invoke2(arg1, arg2) {
327 return guardAsync( 322 return guardAsync(
328 () => _incrementCall() ? callback(arg1, arg2) : null, 323 () => _incrementCall() ? callback(arg1, arg2) : null,
329 () { if (calls == expectedCalls) callbackDone(); }); 324 () { if (calls == expectedCalls) _callbackDone(); });
330 } 325 }
331 326
332 /** Returns false if we exceded the number of expected calls. */ 327 /** Returns false if we exceded the number of expected calls. */
333 bool _incrementCall() { 328 bool _incrementCall() {
334 calls++; 329 calls++;
335 if (calls > expectedCalls) { 330 if (calls > expectedCalls) {
336 testCase.error( 331 testCase.error(
337 'Callback called more times than expected ($expectedCalls)', 332 'Callback called more times than expected ($expectedCalls)',
338 ''); 333 '');
339 _state = _UNCAUGHT_ERROR; 334 _state = _UNCAUGHT_ERROR;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 394
400 try { 395 try {
401 body(); 396 body();
402 } finally { 397 } finally {
403 // Now that the group is over, restore the previous one. 398 // Now that the group is over, restore the previous one.
404 _currentGroup = oldGroup; 399 _currentGroup = oldGroup;
405 } 400 }
406 } 401 }
407 402
408 /** Called by subclasses to indicate that an asynchronous test completed. */ 403 /** Called by subclasses to indicate that an asynchronous test completed. */
409 void callbackDone() { 404 void _callbackDone() {
410 // TODO (gram): we defer this to give the nextBatch recursive 405 // TODO (gram): we defer this to give the nextBatch recursive
411 // stack a chance to unwind. This is a temporary hack but 406 // stack a chance to unwind. This is a temporary hack but
412 // really a bunch of code here needs to be fixed. We have a 407 // really a bunch of code here needs to be fixed. We have a
413 // single array that is being iterated through by nextBatch(), 408 // single array that is being iterated through by nextBatch(),
414 // which is recursively invoked in the case of async tests that 409 // which is recursively invoked in the case of async tests that
415 // run synchronously. Bad things can then happen. 410 // run synchronously. Bad things can then happen.
416 _defer(() { 411 _defer(() {
417 _callbacksCalled++; 412 _callbacksCalled++;
418 if (_currentTest < _tests.length) { 413 if (_currentTest < _tests.length) {
419 final testCase = _tests[_currentTest]; 414 final testCase = _tests[_currentTest];
420 if (_callbacksCalled > testCase.callbacks) { 415 if (_callbacksCalled > testCase.callbacks) {
421 final expected = testCase.callbacks; 416 final expected = testCase.callbacks;
422 testCase.error( 417 testCase.error(
423 'More calls to callbackDone() than expected. ' 418 'More calls to _callbackDone() than expected. '
424 'Actual: ${_callbacksCalled}, expected: ${expected}', ''); 419 'Actual: ${_callbacksCalled}, expected: ${expected}', '');
425 _state = _UNCAUGHT_ERROR; 420 _state = _UNCAUGHT_ERROR;
426 } else if ((_callbacksCalled == testCase.callbacks) && 421 } else if ((_callbacksCalled == testCase.callbacks) &&
427 (_state != _RUNNING_TEST)) { 422 (_state != _RUNNING_TEST)) {
428 if (testCase.result == null) testCase.pass(); 423 if (testCase.result == null) testCase.pass();
429 _currentTest++; 424 _currentTest++;
430 _testRunner(); 425 _testRunner();
431 } 426 }
432 } 427 }
433 }); 428 });
434 } 429 }
435 430
436 /** Menchanism to notify that an error was caught outside of this library. */ 431 /**
432 * Utility function that can be used to notify the test framework that an
433 * error was caught outside of this library.
434 */
437 void reportTestError(String msg, String trace) { 435 void reportTestError(String msg, String trace) {
438 if (_currentTest < _tests.length) { 436 if (_currentTest < _tests.length) {
439 final testCase = _tests[_currentTest]; 437 final testCase = _tests[_currentTest];
440 testCase.error(msg, trace); 438 testCase.error(msg, trace);
441 _state = _UNCAUGHT_ERROR; 439 _state = _UNCAUGHT_ERROR;
442 if (testCase.callbacks > 0) { 440 if (testCase.callbacks > 0) {
443 _currentTest++; 441 _currentTest++;
444 _testRunner(); 442 _testRunner();
445 } 443 }
446 } else { 444 } else {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 } 578 }
581 _config.onInit(); 579 _config.onInit();
582 580
583 // Immediately queue the suite up. It will run after a timeout (i.e. after 581 // Immediately queue the suite up. It will run after a timeout (i.e. after
584 // main() has returned). 582 // main() has returned).
585 _defer(_runTests); 583 _defer(_runTests);
586 } 584 }
587 585
588 /** Signature for a test function. */ 586 /** Signature for a test function. */
589 typedef void TestFunction(); 587 typedef void TestFunction();
OLDNEW
« no previous file with comments | « no previous file | tests/html/fileapi_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698