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

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

Issue 10441104: New expectation functions plus convert old tests to use these. (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
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]
16 * [Expectation]), [expectThrow], or using assertions with the [Expect] 16 * * Matchers: [expect] assertions are written declaratively using [Matcher]s
17 * class.
18 * * Configuration: The framework can be adapted by calling [configure] with a 17 * * Configuration: The framework can be adapted by calling [configure] with a
19 * [Configuration]. Common configurations can be found in this package 18 * [Configuration]. Common configurations can be found in this package
20 * under: 'dom\_config.dart', 'html\_config.dart', and 'vm\_config.dart'. 19 * under: 'dom\_config.dart' (deprecated), 'html\_config.dart' (for running
20 * tests compiled to Javascript in a browser), and 'vm\_config.dart' (for
21 * running native Dart tests on the VM).
21 * 22 *
22 * ##Examples## 23 * ##Examples##
23 * 24 *
24 * A trivial test: 25 * A trivial test:
25 * 26 *
26 * #import('path-to-dart/lib/unittest/unitest.dart'); 27 * #import('path-to-dart/lib/unittest/unitest.dart');
27 * main() { 28 * main() {
28 * test('this is a test', () { 29 * test('this is a test', () {
29 * int x = 2 + 3; 30 * int x = 2 + 3;
30 * expect(x).equals(5); 31 * expect(x, equals(5));
31 * }); 32 * });
32 * } 33 * }
33 * 34 *
34 * Multiple tests: 35 * Multiple tests:
35 * 36 *
36 * #import('path-to-dart/lib/unittest/unitest.dart'); 37 * #import('path-to-dart/lib/unittest/unitest.dart');
37 * main() { 38 * main() {
38 * test('this is a test', () { 39 * test('this is a test', () {
39 * int x = 2 + 3; 40 * int x = 2 + 3;
40 * expect(x).equals(5); 41 * expect(x, equals(5));
41 * }); 42 * });
42 * test('this is another test', () { 43 * test('this is another test', () {
43 * int x = 2 + 3; 44 * int x = 2 + 3;
44 * expect(x).equals(5); 45 * expect(x, equals(5));
45 * }); 46 * });
46 * } 47 * }
47 * 48 *
48 * Multiple tests, grouped by category: 49 * Multiple tests, grouped by category:
49 * 50 *
50 * #import('path-to-dart/lib/unittest/unitest.dart'); 51 * #import('path-to-dart/lib/unittest/unitest.dart');
51 * main() { 52 * main() {
52 * group('group A', () { 53 * group('group A', () {
53 * test('test A.1', () { 54 * test('test A.1', () {
54 * int x = 2 + 3; 55 * int x = 2 + 3;
55 * expect(x).equals(5); 56 * expect(x, equals(5));
56 * }); 57 * });
57 * test('test A.2', () { 58 * test('test A.2', () {
58 * int x = 2 + 3; 59 * int x = 2 + 3;
59 * expect(x).equals(5); 60 * expect(x, equals(5));
60 * }); 61 * });
61 * }); 62 * });
62 * group('group B', () { 63 * group('group B', () {
63 * test('this B.1', () { 64 * test('this B.1', () {
64 * int x = 2 + 3; 65 * int x = 2 + 3;
65 * expect(x).equals(5); 66 * expect(x, equals(5));
66 * }); 67 * });
67 * }); 68 * });
68 * } 69 * }
69 * 70 *
70 * Asynchronous tests: if callbacks expect between 0 and 2 positional arguments. 71 * Asynchronous tests: if callbacks expect between 0 and 2 positional arguments,
72 * depending on the suffix of expectAsyncX(). expectAsyncX() will wrap a
73 * function into a new callback and will not consider the test complete until
74 * that callback is run. A count argument can be provided to specify the number
75 * of times the callback should be called (the default is 1).
71 * 76 *
72 * #import('path-to-dart/lib/unittest/unitest.dart'); 77 * #import('path-to-dart/lib/unittest/unitest.dart');
73 * #import('dart:dom_deprecated'); 78 * #import('dart:dom_deprecated');
74 * main() { 79 * main() {
75 * test('calllback is executed once', () { 80 * test('calllback is executed once', () {
76 * // wrap the callback of an asynchronous call with [expectAsync0] if 81 * // wrap the callback of an asynchronous call with [expectAsync0] if
77 * // the callback takes 0 arguments... 82 * // the callback takes 0 arguments...
78 * window.setTimeout(expectAsync0(() { 83 * window.setTimeout(expectAsync0(() {
79 * int x = 2 + 3; 84 * int x = 2 + 3;
80 * expect(x).equals(5); 85 * expect(x, equals(5));
81 * }), 0); 86 * }), 0);
82 * }); 87 * });
83 * 88 *
84 * test('calllback is executed twice', () { 89 * test('calllback is executed twice', () {
85 * var callback = expectAsync0(() { 90 * var callback = expectAsync0(() {
86 * int x = 2 + 3; 91 * int x = 2 + 3;
87 * expect(x).equals(5); 92 * expect(x, equals(5));
88 * }, count: 2); // <-- we can indicate multiplicity to [expectAsync0] 93 * }, count: 2); // <-- we can indicate multiplicity to [expectAsync0]
89 * window.setTimeout(callback, 0); 94 * window.setTimeout(callback, 0);
90 * window.setTimeout(callback, 0); 95 * window.setTimeout(callback, 0);
91 * }); 96 * });
92 * } 97 * }
93 * 98 *
99 * expectAsyncX() will wrap the callback code in a try/catch handler to handle
100 * exceptions (treated as test failures). There may be times when the number of
101 * times a callback should be called is non-deterministic. In this case a dummy
102 * callback can be created with expectAsync0((){}) and this can be called from
103 * the real callback when it is finally complete. In this case the body of the
104 * callback should be protected within a call to guardAsync(); this will ensure
105 * that exceptions are properly handled.
106 *
94 * Note: due to some language limitations we have to use different functions 107 * 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 108 * 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 109 * 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 110 * regardless of the number of positional arguments. This requires new langauge
98 * features or fixes to the current spec (e.g. see 111 * features or fixes to the current spec (e.g. see
99 * [Issue 2706](http://dartbug.com/2706)). 112 * [Issue 2706](http://dartbug.com/2706)).
100 * 113 *
101 * Meanwhile, we plan to add this alternative API for callbacks of more than 2 114 * 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, 115 * arguments or that take named parameters. (this is not implemented yet,
103 * but will be coming here soon). 116 * but will be coming here soon).
104 * 117 *
105 * #import('path-to-dart/lib/unittest/unitest.dart'); 118 * #import('path-to-dart/lib/unittest/unitest.dart');
106 * #import('dart:dom_deprecated'); 119 * #import('dart:dom_deprecated');
107 * main() { 120 * main() {
108 * test('calllback is executed', () { 121 * test('calllback is executed', () {
109 * // indicate ahead of time that an async callback is expected. 122 * // indicate ahead of time that an async callback is expected.
110 * var async = startAsync(); 123 * var async = startAsync();
111 * window.setTimeout(() { 124 * window.setTimeout(() {
112 * // Guard the body of the callback, so errors are propagated 125 * // Guard the body of the callback, so errors are propagated
113 * // correctly 126 * // correctly
114 * guardAsync(() { 127 * guardAsync(() {
115 * int x = 2 + 3; 128 * int x = 2 + 3;
116 * expect(x).equals(5); 129 * expect(x, equals(5));
117 * }); 130 * });
118 * // indicate that the asynchronous callback was invoked. 131 * // indicate that the asynchronous callback was invoked.
119 * async.complete(); 132 * async.complete();
120 * }), 0); 133 * }), 0);
121 * }); 134 * });
122 * 135 *
123 */ 136 */
124 #library('unittest'); 137 #library('unittest');
125 138
126 #import('dart:isolate'); 139 #import('dart:isolate');
127 140
141 #source('collection_matchers.dart');
128 #source('config.dart'); 142 #source('config.dart');
129 #source('expectation.dart'); 143 #source('core_matchers.dart');
144 #source('description.dart');
145 #source('expect.dart');
146 #source('interfaces.dart');
147 #source('map_matchers.dart');
148 #source('matcher.dart');
149 #source('numeric_matchers.dart');
150 #source('operator_matchers.dart');
151 #source('string_matchers.dart');
130 #source('test_case.dart'); 152 #source('test_case.dart');
131 153
132 /** [Configuration] used by the unittest library. */ 154 /** [Configuration] used by the unittest library. */
133 Configuration _config = null; 155 Configuration _config = null;
134 156
135 /** Set the [Configuration] used by the unittest library. */ 157 /** Set the [Configuration] used by the unittest library. */
136 void configure(Configuration config) { 158 void configure(Configuration config) {
137 _config = config; 159 _config = config;
138 } 160 }
139 161
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 int _state = _UNINITIALIZED; 194 int _state = _UNINITIALIZED;
173 String _uncaughtErrorMessage = null; 195 String _uncaughtErrorMessage = null;
174 196
175 final _PASS = 'pass'; 197 final _PASS = 'pass';
176 final _FAIL = 'fail'; 198 final _FAIL = 'fail';
177 final _ERROR = 'error'; 199 final _ERROR = 'error';
178 200
179 /** If set, then all other test cases will be ignored. */ 201 /** If set, then all other test cases will be ignored. */
180 TestCase _soloTest; 202 TestCase _soloTest;
181 203
182 /** Creates an expectation for the given value. */
183 Expectation expect(value) => new Expectation(value);
184
185 /** 204 /**
186 * Evaluates the [function] and validates that it throws an exception. If 205 * (Deprecated) Evaluates the [function] and validates that it throws an
187 * [callback] is provided, then it will be invoked with the thrown exception. 206 * exception. If [callback] is provided, then it will be invoked with the
188 * The callback may do any validation it wants. In addition, if it returns 207 * thrown exception. The callback may do any validation it wants. In addition,
189 * `false`, that also indicates an expectation failure. 208 * if it returns `false`, that also indicates an expectation failure.
190 */ 209 */
191 void expectThrow(function, [bool callback(exception)]) { 210 void expectThrow(function, [bool callback(exception)]) {
192 bool threw = false; 211 bool threw = false;
193 try { 212 try {
194 function(); 213 function();
195 } catch (var e) { 214 } catch (var e) {
196 threw = true; 215 threw = true;
197 216
198 // Also let the callback look at it. 217 // Also let the callback look at it.
199 if (callback != null) { 218 if (callback != null) {
(...skipping 15 matching lines...) Expand all
215 * description will include the descriptions of any surrounding group() 234 * description will include the descriptions of any surrounding group()
216 * calls. 235 * calls.
217 */ 236 */
218 void test(String spec, TestFunction body) { 237 void test(String spec, TestFunction body) {
219 ensureInitialized(); 238 ensureInitialized();
220 239
221 _tests.add(new TestCase(_tests.length + 1, _fullSpec(spec), body, 0)); 240 _tests.add(new TestCase(_tests.length + 1, _fullSpec(spec), body, 0));
222 } 241 }
223 242
224 /** 243 /**
225 * Creates a new async test case with the given description and body. The 244 * (Deprecated) Creates a new async test case with the given description
226 * description will include the descriptions of any surrounding group() 245 * and body. The description will include the descriptions of any surrounding
227 * calls. 246 * group() calls.
228 */ 247 */
229 // TODO(sigmund): deprecate this API 248 // TODO(sigmund): deprecate this API
230 void asyncTest(String spec, int callbacks, TestFunction body) { 249 void asyncTest(String spec, int callbacks, TestFunction body) {
231 ensureInitialized(); 250 ensureInitialized();
232 251
233 final testCase = new TestCase( 252 final testCase = new TestCase(
234 _tests.length + 1, _fullSpec(spec), body, callbacks); 253 _tests.length + 1, _fullSpec(spec), body, callbacks);
235 _tests.add(testCase); 254 _tests.add(testCase);
236 255
237 if (callbacks < 1) { 256 if (callbacks < 1) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 return guardAsync( 346 return guardAsync(
328 () => _incrementCall() ? callback(arg1, arg2) : null, 347 () => _incrementCall() ? callback(arg1, arg2) : null,
329 () { if (calls == expectedCalls) callbackDone(); }); 348 () { if (calls == expectedCalls) callbackDone(); });
330 } 349 }
331 350
332 /** Returns false if we exceded the number of expected calls. */ 351 /** Returns false if we exceded the number of expected calls. */
333 bool _incrementCall() { 352 bool _incrementCall() {
334 calls++; 353 calls++;
335 if (calls > expectedCalls) { 354 if (calls > expectedCalls) {
336 testCase.error( 355 testCase.error(
337 'Callback called more times than expected ($expectedCalls)', 356 'Callback called more times than expected ($calls > $expectedCalls)',
338 ''); 357 '');
339 _state = _UNCAUGHT_ERROR; 358 _state = _UNCAUGHT_ERROR;
340 return false; 359 return false;
341 } 360 }
342 return true; 361 return true;
343 } 362 }
344 } 363 }
345 364
346 /** 365 /**
347 * Indicate that [callback] is expected to be called a [count] number of times 366 * Indicate that [callback] is expected to be called a [count] number of times
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 body(); 420 body();
402 } finally { 421 } finally {
403 // Now that the group is over, restore the previous one. 422 // Now that the group is over, restore the previous one.
404 _currentGroup = oldGroup; 423 _currentGroup = oldGroup;
405 } 424 }
406 } 425 }
407 426
408 /** Called by subclasses to indicate that an asynchronous test completed. */ 427 /** Called by subclasses to indicate that an asynchronous test completed. */
409 void callbackDone() { 428 void callbackDone() {
410 // TODO (gram): we defer this to give the nextBatch recursive 429 // TODO (gram): we defer this to give the nextBatch recursive
411 // stack a chance to unwind. This is a temporary hack but 430 // 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 431 // really a bunch of code here needs to be fixed. We have a
413 // single array that is being iterated through by nextBatch(), 432 // single array that is being iterated through by nextBatch(),
414 // which is recursively invoked in the case of async tests that 433 // which is recursively invoked in the case of async tests that
415 // run synchronously. Bad things can then happen. 434 // run synchronously. Bad things can then happen.
416 _defer(() { 435 _defer(() {
417 _callbacksCalled++; 436 _callbacksCalled++;
418 if (_currentTest < _tests.length) { 437 if (_currentTest < _tests.length) {
419 final testCase = _tests[_currentTest]; 438 final testCase = _tests[_currentTest];
420 if (_callbacksCalled > testCase.callbacks) { 439 if (_callbacksCalled > testCase.callbacks) {
421 final expected = testCase.callbacks; 440 final expected = testCase.callbacks;
422 testCase.error( 441 testCase.error(
423 'More calls to callbackDone() than expected. ' 442 'More calls to callbackDone() than expected. '
424 'Actual: ${_callbacksCalled}, expected: ${expected}', ''); 443 'Actual: ${_callbacksCalled}, expected: ${expected}', '');
425 _state = _UNCAUGHT_ERROR; 444 _state = _UNCAUGHT_ERROR;
426 } else if ((_callbacksCalled == testCase.callbacks) && 445 } else if ((_callbacksCalled == testCase.callbacks) &&
427 (_state != _RUNNING_TEST)) { 446 (_state != _RUNNING_TEST)) {
428 if (testCase.result == null) testCase.pass(); 447 if (testCase.result == null) {
448 testCase.pass();
449 }
429 _currentTest++; 450 _currentTest++;
430 _testRunner(); 451 _testRunner();
431 } 452 }
432 } 453 }
433 }); 454 });
434 } 455 }
435 456
436 /** Menchanism to notify that an error was caught outside of this library. */ 457 /**
458 * Utility function that can be used to notify the test framework that an
459 * error was caught outside of this library.
460 */
437 void reportTestError(String msg, String trace) { 461 void reportTestError(String msg, String trace) {
438 if (_currentTest < _tests.length) { 462 if (_currentTest < _tests.length) {
439 final testCase = _tests[_currentTest]; 463 final testCase = _tests[_currentTest];
440 testCase.error(msg, trace); 464 testCase.error(msg, trace);
441 _state = _UNCAUGHT_ERROR; 465 _state = _UNCAUGHT_ERROR;
442 if (testCase.callbacks > 0) { 466 if (testCase.callbacks > 0) {
443 _currentTest++; 467 _currentTest++;
444 _testRunner(); 468 _testRunner();
445 } 469 }
446 } else { 470 } else {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 } 604 }
581 _config.onInit(); 605 _config.onInit();
582 606
583 // Immediately queue the suite up. It will run after a timeout (i.e. after 607 // Immediately queue the suite up. It will run after a timeout (i.e. after
584 // main() has returned). 608 // main() has returned).
585 _defer(_runTests); 609 _defer(_runTests);
586 } 610 }
587 611
588 /** Signature for a test function. */ 612 /** Signature for a test function. */
589 typedef void TestFunction(); 613 typedef void TestFunction();
OLDNEW
« no previous file with comments | « lib/unittest/string_matchers.dart ('k') | samples/tests/samples/lib/observable/abstract_observable_tests.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698