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

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

Issue 10544167: Some unit test fixes (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 *
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 class _Sentinel { 287 class _Sentinel {
288 const _Sentinel(); 288 const _Sentinel();
289 } 289 }
290 290
291 // TODO(sigmund): make a singleton const field when frog supports passing those 291 // TODO(sigmund): make a singleton const field when frog supports passing those
292 // as default values to named arguments. 292 // as default values to named arguments.
293 final _sentinel = const _Sentinel(); 293 final _sentinel = const _Sentinel();
294 294
295 /** Simulates spread arguments using named arguments. */ 295 /** Simulates spread arguments using named arguments. */
296 // TODO(sigmund): remove this class and simply use a closure with named 296 // TODO(sigmund): remove this class and simply use a closure with named
297 // arguments inside [_expectAsync], once bug 282 is fixed or frog is replaced by 297 // arguments inside [_expectAsync], once bug 282 is fixed or frog is replaced by
eub 2012/06/15 21:02:49 "now that frog is replaced by dart2js" :)
gram 2012/06/15 21:25:55 I tweaked the comment a bit. I'm not sure it makes
298 // dart2js. 298 // dart2js.
299 class _SpreadArgsHelper { 299 class _SpreadArgsHelper {
300 Function callback; 300 Function _callback;
301 int expectedCalls; 301 int _expectedCalls;
302 int calls = 0; 302 int _calls = 0;
303 TestCase testCase; 303 TestCase _testCase;
304 _SpreadArgsHelper(this.callback, this.expectedCalls) { 304 Function _shouldCallBack;
305 Expect.isTrue(_currentTest < _tests.length); 305 Function _isDone;
306 testCase = _tests[_currentTest]; 306
307 testCase.callbacks++; 307 _init(Function callback, Function shouldCallBack, Function isDone,
308 [expectedCalls = 0]) {
309 assert(_currentTest < _tests.length);
310 _callback = callback;
311 _shouldCallBack = shouldCallBack;
312 _isDone = isDone;
313 _expectedCalls = expectedCalls;
314 _testCase = _tests[_currentTest];
315 if (expectedCalls > 0) {
316 _testCase.callbacks++;
317 }
318 }
319
320 _SpreadArgsHelper(callback, shouldCallBack, isDone) {
321 _init(callback, shouldCallBack, isDone);
322 }
323
324 _SpreadArgsHelper.fixedCallCount(callback, expectedCalls) {
325 _init(callback, _checkCallCount, _allCallsDone, expectedCalls);
326 }
327
328 _SpreadArgsHelper.variableCallCount(callback, isDone) {
329 _init(callback, _always, isDone);
330 }
331
332 _after() {
333 if (_isDone()) {
334 _handleAllCallbacksDone();
335 }
336 }
337
338 _allCallsDone() => _calls == _expectedCalls;
339
340 _always() {
341 // Always run except if the test is done.
342 if (_testCase.isComplete) {
343 _testCase.error(
344 'Callback called after already being marked as done ($_calls)',
345 '');
346 _state = _UNCAUGHT_ERROR;
347 return false;
348 } else {
349 return true;
350 }
308 } 351 }
309 352
310 invoke([arg0 = _sentinel, arg1 = _sentinel, arg2 = _sentinel, 353 invoke([arg0 = _sentinel, arg1 = _sentinel, arg2 = _sentinel,
311 arg3 = _sentinel, arg4 = _sentinel]) { 354 arg3 = _sentinel, arg4 = _sentinel]) {
312 return guardAsync(() { 355 return guardAsync(() {
313 if (!_incrementCall()) { 356 ++_calls;
357 if (!_shouldCallBack()) {
314 return; 358 return;
315 } else if (arg0 == _sentinel) { 359 } else if (arg0 == _sentinel) {
316 return callback(); 360 return _callback();
317 } else if (arg1 == _sentinel) { 361 } else if (arg1 == _sentinel) {
318 return callback(arg0); 362 return _callback(arg0);
319 } else if (arg2 == _sentinel) { 363 } else if (arg2 == _sentinel) {
320 return callback(arg0, arg1); 364 return _callback(arg0, arg1);
321 } else if (arg3 == _sentinel) { 365 } else if (arg3 == _sentinel) {
322 return callback(arg0, arg1, arg2); 366 return _callback(arg0, arg1, arg2);
323 } else if (arg4 == _sentinel) { 367 } else if (arg4 == _sentinel) {
324 return callback(arg0, arg1, arg2, arg3); 368 return _callback(arg0, arg1, arg2, arg3);
325 } else { 369 } else {
326 testCase.error( 370 _testCase.error(
327 'unittest lib does not support callbacks with more than 4 arguments', 371 'unittest lib does not support callbacks with more than 4 arguments',
328 ''); 372 '');
329 _state = _UNCAUGHT_ERROR; 373 _state = _UNCAUGHT_ERROR;
330 } 374 }
331 }, () { if (calls == expectedCalls) callbackDone(); }); 375 },
376 _after);
332 } 377 }
333 378
334 invoke0() { 379 invoke0() {
335 return guardAsync( 380 return guardAsync(
336 () => _incrementCall() ? callback() : null, 381 () {
337 () { if (calls == expectedCalls) callbackDone(); }); 382 ++_calls;
383 if (_shouldCallBack()) {
384 return _callback();
385 }
386 },
387 _after);
338 } 388 }
339 389
340 invoke1(arg1) { 390 invoke1(arg1) {
341 return guardAsync( 391 return guardAsync(
342 () => _incrementCall() ? callback(arg1) : null, 392 () {
343 () { if (calls == expectedCalls) callbackDone(); }); 393 ++_calls;
394 if (_shouldCallBack()) {
395 return _callback(arg1);
396 }
397 },
398 _after);
344 } 399 }
345 400
346 invoke2(arg1, arg2) { 401 invoke2(arg1, arg2) {
347 return guardAsync( 402 return guardAsync(
348 () => _incrementCall() ? callback(arg1, arg2) : null, 403 () {
349 () { if (calls == expectedCalls) callbackDone(); }); 404 ++_calls;
405 if (_shouldCallBack()) {
406 return _callback(arg1, arg2);
407 }
408 },
409 _after);
350 } 410 }
351 411
352 /** Returns false if we exceded the number of expected calls. */ 412 /** Returns false if we exceded the number of expected calls. */
353 bool _incrementCall() { 413 bool _checkCallCount() {
354 calls++; 414 if (_calls > _expectedCalls) {
355 if (calls > expectedCalls) { 415 _testCase.error(
356 testCase.error( 416 'Callback called more times than expected '
357 'Callback called more times than expected ($calls > $expectedCalls)', 417 '($_calls > $_expectedCalls)',
358 ''); 418 '');
359 _state = _UNCAUGHT_ERROR; 419 _state = _UNCAUGHT_ERROR;
360 return false; 420 return false;
361 } 421 }
362 return true; 422 return true;
363 } 423 }
364 } 424 }
365 425
366 /** 426 /**
367 * Indicate that [callback] is expected to be called a [count] number of times 427 * Indicate that [callback] is expected to be called a [count] number of times
368 * (by default 1). The unittest framework will wait for the callback to run the 428 * (by default 1). The unittest framework will wait for the callback to run the
369 * specified [count] times before it continues with the following test. Using 429 * specified [count] times before it continues with the following test. Using
370 * [_expectAsync] will also ensure that errors that occur within [callback] are 430 * [_expectAsync] will also ensure that errors that occur within [callback] are
371 * tracked and reported. [callback] should take between 0 and 4 positional 431 * tracked and reported. [callback] should take between 0 and 4 positional
372 * arguments (named arguments are not supported here). 432 * arguments (named arguments are not supported here).
373 */ 433 */
374 Function _expectAsync(Function callback, [int count = 1]) { 434 Function _expectAsync(Function callback, [int count = 1]) {
375 return new _SpreadArgsHelper(callback, count).invoke; 435 return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke;
376 } 436 }
377 437
378 /** 438 /**
379 * Indicate that [callback] is expected to be called a [count] number of times 439 * Indicate that [callback] is expected to be called a [count] number of times
380 * (by default 1). The unittest framework will wait for the callback to run the 440 * (by default 1). The unittest framework will wait for the callback to run the
381 * specified [count] times before it continues with the following test. Using 441 * specified [count] times before it continues with the following test. Using
382 * [expectAsync0] will also ensure that errors that occur within [callback] are 442 * [expectAsync0] will also ensure that errors that occur within [callback] are
383 * tracked and reported. [callback] should take 0 positional arguments (named 443 * tracked and reported. [callback] should take 0 positional arguments (named
384 * arguments are not supported). 444 * arguments are not supported).
385 */ 445 */
386 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 446 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
387 Function expectAsync0(Function callback, [int count = 1]) { 447 Function expectAsync0(Function callback, [int count = 1]) {
388 return new _SpreadArgsHelper(callback, count).invoke0; 448 return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke0;
389 } 449 }
390 450
391 /** Like [expectAsync0] but [callback] should take 1 positional argument. */ 451 /** Like [expectAsync0] but [callback] should take 1 positional argument. */
392 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 452 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
393 Function expectAsync1(Function callback, [int count = 1]) { 453 Function expectAsync1(Function callback, [int count = 1]) {
394 return new _SpreadArgsHelper(callback, count).invoke1; 454 return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke1;
395 } 455 }
396 456
397 /** Like [expectAsync0] but [callback] should take 2 positional arguments. */ 457 /** Like [expectAsync0] but [callback] should take 2 positional arguments. */
398 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 458 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
399 Function expectAsync2(Function callback, [int count = 1]) { 459 Function expectAsync2(Function callback, [int count = 1]) {
400 return new _SpreadArgsHelper(callback, count).invoke2; 460 return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke2;
461 }
462
463 /**
464 * Indicate that [callback] is expected to be called until [isDone] returns
465 * true. The unittest framework checks [isDone] after each callback and only
466 * when it returns true will it continue with the following test. Using
467 * [expectAsyncUntil] will also ensure that errors that occur within
468 * [callback] are tracked and reported. [callback] should take between 0 and
469 * 4 positional arguments (named arguments are not supported).
470 */
471 Function _expectAsyncUntil(Function callback, Function isDone) {
472 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke;
473 }
474
475 /**
476 * Indicate that [callback] is expected to be called until [isDone] returns
477 * true. The unittest framework check [isDone] after each callback and only
478 * when it returns true will it continue with the following test. Using
479 * [expectAsyncUntil0] will also ensure that errors that occur within
480 * [callback] are tracked and reported. [callback] should take 0 positional
481 * arguments (named arguments are not supported).
482 */
483 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
484 Function expectAsyncUntil0(Function callback, Function isDone) {
485 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke0;
486 }
487
488 /**
489 * Like [expectAsyncUntil0] but [callback] should take 1 positional argument.
490 */
491 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
492 Function expectAsyncUntil1(Function callback, Function isDone) {
493 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke1;
494 }
495
496 /**
497 * Like [expectAsyncUntil0] but [callback] should take 2 positional arguments.
498 */
499 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
500 Function expectAsyncUntil2(Function callback, Function isDone) {
501 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke2;
401 } 502 }
402 503
403 /** 504 /**
404 * Creates a new named group of tests. Calls to group() or test() within the 505 * Creates a new named group of tests. Calls to group() or test() within the
405 * body of the function passed to this will inherit this group's description. 506 * body of the function passed to this will inherit this group's description.
406 */ 507 */
407 void group(String description, void body()) { 508 void group(String description, void body()) {
408 ensureInitialized(); 509 ensureInitialized();
409 510
410 // Concatenate the new group. 511 // Concatenate the new group.
411 final oldGroup = _currentGroup; 512 final oldGroup = _currentGroup;
412 if (_currentGroup != '') { 513 if (_currentGroup != '') {
413 // Add a space. 514 // Add a space.
414 _currentGroup = '$_currentGroup $description'; 515 _currentGroup = '$_currentGroup $description';
415 } else { 516 } else {
416 // The first group. 517 // The first group.
417 _currentGroup = description; 518 _currentGroup = description;
418 } 519 }
419 520
420 try { 521 try {
421 body(); 522 body();
422 } finally { 523 } finally {
423 // Now that the group is over, restore the previous one. 524 // Now that the group is over, restore the previous one.
424 _currentGroup = oldGroup; 525 _currentGroup = oldGroup;
425 } 526 }
426 } 527 }
427 528
428 /** Called by subclasses to indicate that an asynchronous test completed. */ 529 /** Called by subclasses to indicate that an asynchronous test completed. */
429 void callbackDone() { 530 void _handleAllCallbacksDone() {
430 // TODO (gram): we defer this to give the nextBatch recursive 531 // TODO (gram): we defer this to give the nextBatch recursive
431 // stack a chance to unwind. This is a temporary hack but 532 // stack a chance to unwind. This is a temporary hack but
432 // really a bunch of code here needs to be fixed. We have a 533 // really a bunch of code here needs to be fixed. We have a
433 // single array that is being iterated through by nextBatch(), 534 // single array that is being iterated through by nextBatch(),
434 // which is recursively invoked in the case of async tests that 535 // which is recursively invoked in the case of async tests that
435 // run synchronously. Bad things can then happen. 536 // run synchronously. Bad things can then happen.
436 _defer(() { 537 _defer(() {
437 _callbacksCalled++; 538 _callbacksCalled++;
438 if (_currentTest < _tests.length) { 539 if (_currentTest < _tests.length) {
439 final testCase = _tests[_currentTest]; 540 final testCase = _tests[_currentTest];
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 * Runs a batch of tests, yielding whenever an asynchronous test starts 636 * Runs a batch of tests, yielding whenever an asynchronous test starts
536 * running. Tests will resume executing when such asynchronous test calls 637 * running. Tests will resume executing when such asynchronous test calls
537 * [done] or if it fails with an exception. 638 * [done] or if it fails with an exception.
538 */ 639 */
539 _nextBatch() { 640 _nextBatch() {
540 while (_currentTest < _tests.length) { 641 while (_currentTest < _tests.length) {
541 final testCase = _tests[_currentTest]; 642 final testCase = _tests[_currentTest];
542 guardAsync(() { 643 guardAsync(() {
543 _callbacksCalled = 0; 644 _callbacksCalled = 0;
544 _state = _RUNNING_TEST; 645 _state = _RUNNING_TEST;
545
546 testCase.test(); 646 testCase.test();
547 647
548 if (_state != _UNCAUGHT_ERROR) { 648 if (_state != _UNCAUGHT_ERROR) {
549 if (testCase.callbacks == _callbacksCalled) { 649 if (testCase.callbacks == _callbacksCalled) {
550 testCase.pass(); 650 testCase.pass();
551 } 651 }
552 } 652 }
553 }); 653 });
554 654
555 if (!testCase.isComplete && testCase.callbacks > 0) return; 655 if (!testCase.isComplete && testCase.callbacks > 0) return;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 throw new ExpectException(message); 689 throw new ExpectException(message);
590 } 690 }
591 691
592 /** 692 /**
593 * Lazily initializes the test library if not already initialized. 693 * Lazily initializes the test library if not already initialized.
594 */ 694 */
595 ensureInitialized() { 695 ensureInitialized() {
596 if (_state != _UNINITIALIZED) return; 696 if (_state != _UNINITIALIZED) return;
597 697
598 _tests = <TestCase>[]; 698 _tests = <TestCase>[];
699 _uncaughtErrorMessage = null;
700 _currentTest = 0;
599 _currentGroup = ''; 701 _currentGroup = '';
600 _state = _READY; 702 _state = _READY;
601 _testRunner = _nextBatch; 703 _testRunner = _nextBatch;
602 704
603 if (_config == null) { 705 if (_config == null) {
604 _config = new Configuration(); 706 _config = new Configuration();
605 } 707 }
606 _config.onInit(); 708 _config.onInit();
607 709
608 // Immediately queue the suite up. It will run after a timeout (i.e. after 710 // Immediately queue the suite up. It will run after a timeout (i.e. after
609 // main() has returned). 711 // main() has returned).
610 _defer(_runTests); 712 _defer(_runTests);
611 } 713 }
612 714
613 /** Signature for a test function. */ 715 /** Signature for a test function. */
614 typedef void TestFunction(); 716 typedef void TestFunction();
717
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698