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

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

Issue 10830128: Ability to guard callbacks that may never get called. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 // as default values to named arguments. 316 // as default values to named arguments.
317 final _sentinel = const _Sentinel(); 317 final _sentinel = const _Sentinel();
318 318
319 /** Simulates spread arguments using named arguments. */ 319 /** Simulates spread arguments using named arguments. */
320 // TODO(sigmund): remove this class and simply use a closure with named 320 // TODO(sigmund): remove this class and simply use a closure with named
321 // arguments (if still applicable). 321 // arguments (if still applicable).
322 class _SpreadArgsHelper { 322 class _SpreadArgsHelper {
323 Function _callback; 323 Function _callback;
324 int _expectedCalls; 324 int _expectedCalls;
325 int _calls = 0; 325 int _calls = 0;
326 int _testNum;
326 TestCase _testCase; 327 TestCase _testCase;
327 Function _shouldCallBack; 328 Function _shouldCallBack;
328 Function _isDone; 329 Function _isDone;
329 330
330 _init(Function callback, Function shouldCallBack, Function isDone, 331 _init(Function callback, Function shouldCallBack, Function isDone,
331 [expectedCalls = 0]) { 332 [expectedCalls = 0]) {
332 ensureInitialized(); 333 ensureInitialized();
333 assert(_currentTest < _tests.length); 334 assert(_currentTest < _tests.length);
334 _callback = callback; 335 _callback = callback;
335 _shouldCallBack = shouldCallBack; 336 _shouldCallBack = shouldCallBack;
336 _isDone = isDone; 337 _isDone = isDone;
337 _expectedCalls = expectedCalls; 338 _expectedCalls = expectedCalls;
339 _testNum = _currentTest;
338 _testCase = _tests[_currentTest]; 340 _testCase = _tests[_currentTest];
339 if (expectedCalls > 0) { 341 if (expectedCalls > 0) {
340 _testCase.callbacks++; 342 _testCase.callbacks++;
341 } 343 }
342 } 344 }
343 345
344 _SpreadArgsHelper(callback, shouldCallBack, isDone) { 346 _SpreadArgsHelper(callback, shouldCallBack, isDone) {
345 _init(callback, shouldCallBack, isDone); 347 _init(callback, shouldCallBack, isDone);
346 } 348 }
347 349
348 _SpreadArgsHelper.fixedCallCount(callback, expectedCalls) { 350 _SpreadArgsHelper.fixedCallCount(callback, expectedCalls) {
349 _init(callback, _checkCallCount, _allCallsDone, expectedCalls); 351 _init(callback, _checkCallCount, _allCallsDone, expectedCalls);
350 } 352 }
351 353
352 _SpreadArgsHelper.variableCallCount(callback, isDone) { 354 _SpreadArgsHelper.variableCallCount(callback, isDone) {
353 _init(callback, _always, isDone, 1); 355 _init(callback, _always, isDone, 1);
354 } 356 }
355 357
358 _SpreadArgsHelper.optionalCalls(callback) {
359 _init(callback, _always, () => false, 0);
360 }
361
356 _after() { 362 _after() {
357 if (_isDone()) { 363 if (_isDone()) {
358 _handleAllCallbacksDone(); 364 _handleAllCallbacksDone();
359 } 365 }
360 } 366 }
361 367
362 _allCallsDone() => _calls == _expectedCalls; 368 _allCallsDone() => _calls == _expectedCalls;
363 369
364 _always() { 370 _always() {
365 // Always run except if the test is done. 371 // Always run except if the test is done.
(...skipping 25 matching lines...) Expand all
391 } else if (arg4 == _sentinel) { 397 } else if (arg4 == _sentinel) {
392 return _callback(arg0, arg1, arg2, arg3); 398 return _callback(arg0, arg1, arg2, arg3);
393 } else { 399 } else {
394 _testCase.error( 400 _testCase.error(
395 'unittest lib does not support callbacks with more than' 401 'unittest lib does not support callbacks with more than'
396 ' 4 arguments.', 402 ' 4 arguments.',
397 ''); 403 '');
398 _state = _UNCAUGHT_ERROR; 404 _state = _UNCAUGHT_ERROR;
399 } 405 }
400 }, 406 },
401 _after); 407 _after, _testNum);
402 } 408 }
403 409
404 invoke0() { 410 invoke0() {
405 return guardAsync( 411 return guardAsync(
406 () { 412 () {
407 ++_calls; 413 ++_calls;
408 if (_shouldCallBack()) { 414 if (_shouldCallBack()) {
409 return _callback(); 415 return _callback();
410 } 416 }
411 }, 417 },
412 _after); 418 _after, _testNum);
413 } 419 }
414 420
415 invoke1(arg1) { 421 invoke1(arg1) {
416 return guardAsync( 422 return guardAsync(
417 () { 423 () {
418 ++_calls; 424 ++_calls;
419 if (_shouldCallBack()) { 425 if (_shouldCallBack()) {
420 return _callback(arg1); 426 return _callback(arg1);
421 } 427 }
422 }, 428 },
423 _after); 429 _after, _testNum);
424 } 430 }
425 431
426 invoke2(arg1, arg2) { 432 invoke2(arg1, arg2) {
427 return guardAsync( 433 return guardAsync(
428 () { 434 () {
429 ++_calls; 435 ++_calls;
430 if (_shouldCallBack()) { 436 if (_shouldCallBack()) {
431 return _callback(arg1, arg2); 437 return _callback(arg1, arg2);
432 } 438 }
433 }, 439 },
434 _after); 440 _after, _testNum);
435 } 441 }
436 442
437 /** Returns false if we exceded the number of expected calls. */ 443 /** Returns false if we exceded the number of expected calls. */
438 bool _checkCallCount() { 444 bool _checkCallCount() {
439 if (_calls > _expectedCalls) { 445 if (_calls > _expectedCalls) {
440 _testCase.error( 446 _testCase.error(
441 'Callback called more times than expected ' 447 'Callback called more times than expected '
442 '($_calls > $_expectedCalls).', 448 '($_calls > $_expectedCalls).',
443 ''); 449 '');
444 _state = _UNCAUGHT_ERROR; 450 _state = _UNCAUGHT_ERROR;
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 526
521 /** 527 /**
522 * Like [expectAsyncUntil0] but [callback] should take 2 positional arguments. 528 * Like [expectAsyncUntil0] but [callback] should take 2 positional arguments.
523 */ 529 */
524 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 530 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
525 Function expectAsyncUntil2(Function callback, Function isDone) { 531 Function expectAsyncUntil2(Function callback, Function isDone) {
526 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke2; 532 return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke2;
527 } 533 }
528 534
529 /** 535 /**
536 * Wraps the [callback] in a new function and returns that function. The new
537 * function will be able to handle exceptions by directing them to the correct
538 * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
539 * might optionally be called but may never be called during the test.
540 * [callback] should take between 0 and 4 positional arguments (named arguments
541 * are not supported).
542 */
543 Function _protectAsync(Function callback) {
544 return new _SpreadArgsHelper.optionalCalls(callback).invoke;
545 }
546
547 /**
548 * Wraps the [callback] in a new function and returns that function. The new
549 * function will be able to handle exceptions by directing them to the correct
550 * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
551 * might optionally be called but may never be called during the test.
552 * [callback] should take 0 positional arguments (named arguments are not
553 * supported).
554 */
555 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
556 Function protectAsync0(Function callback) {
557 return new _SpreadArgsHelper.optionalCalls(callback).invoke0;
558 }
559
560 /**
561 * Like [protectAsync0] but [callback] should take 1 positional argument.
562 */
563 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
564 Function protectAsync1(Function callback) {
565 return new _SpreadArgsHelper.optionalCalls(callback).invoke1;
566 }
567
568 /**
569 * Like [protectAsync0] but [callback] should take 2 positional arguments.
570 */
571 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
572 Function protectAsync2(Function callback) {
573 return new _SpreadArgsHelper.optionalCalls(callback).invoke2;
574 }
575
576 /**
530 * Creates a new named group of tests. Calls to group() or test() within the 577 * Creates a new named group of tests. Calls to group() or test() within the
531 * body of the function passed to this will inherit this group's description. 578 * body of the function passed to this will inherit this group's description.
532 */ 579 */
533 void group(String description, void body()) { 580 void group(String description, void body()) {
534 ensureInitialized(); 581 ensureInitialized();
535 582
536 // Concatenate the new group. 583 // Concatenate the new group.
537 final parentGroup = _currentGroup; 584 final parentGroup = _currentGroup;
538 if (_currentGroup != '') { 585 if (_currentGroup != '') {
539 // Add a space. 586 // Add a space.
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 for (var i = 0; i < _tests.length; i++) { 729 for (var i = 0; i < _tests.length; i++) {
683 _tests[i].callbacks = 0; // Note - won't work with old asyncTests. 730 _tests[i].callbacks = 0; // Note - won't work with old asyncTests.
684 } 731 }
685 runTests(); 732 runTests();
686 } 733 }
687 734
688 /** 735 /**
689 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update 736 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update
690 * the [_currentTest] status accordingly. 737 * the [_currentTest] status accordingly.
691 */ 738 */
692 guardAsync(tryBody, [finallyBody]) { 739 guardAsync(tryBody, [finallyBody, testNum = -1]) {
740 if (testNum < 0) testNum = _currentTest;
693 try { 741 try {
694 return tryBody(); 742 return tryBody();
695 } catch (var e, var trace) { 743 } catch (var e, var trace) {
696 registerException(e, trace); 744 registerException(testNum, e, trace);
697 } finally { 745 } finally {
698 _state = _READY; 746 _state = _READY;
699 if (finallyBody != null) finallyBody(); 747 if (finallyBody != null) finallyBody();
700 } 748 }
701 } 749 }
702 750
703 /** 751 /**
704 * Registers that an exception was caught for the current test. 752 * Registers that an exception was caught for the current test.
705 */ 753 */
706 registerException(e, [trace]) { 754 registerException(testNum, e, [trace]) {
707 if (e is ExpectException) { 755 if (_tests[testNum].result == null) {
708 Expect.isTrue(_currentTest < _tests.length); 756 if (e is ExpectException) {
709 if (_state != _UNCAUGHT_ERROR) { 757 _tests[testNum].fail(e.message, trace == null ? '' : trace.toString());
710 _tests[_currentTest].fail(e.message, 758 } else {
711 trace == null ? '' : trace.toString()); 759 _tests[testNum].fail('Caught $e', trace == null ? '' : trace.toString());
712 } 760 }
713 } else { 761 } else {
714 if (_state == _RUNNING_TEST) { 762 _tests[testNum].error('Caught $e', trace == null ? '' : trace.toString());
715 // If a random exception is thrown from within a test, we consider that
716 // a test failure too. A test case implicitly has an expectation that it
717 // will run to completion without an uncaught exception being thrown.
718 _tests[_currentTest].fail('Caught $e',
719 trace == null ? '' : trace.toString());
720 } else if (_state != _UNCAUGHT_ERROR) {
721 _tests[_currentTest].error('Caught $e',
722 trace == null ? '' : trace.toString());
723 }
724 } 763 }
725 _nextTestCase(); 764 if (testNum == _currentTest) {
765 _nextTestCase();
766 }
726 } 767 }
727 768
728 /** 769 /**
729 * Runs a batch of tests, yielding whenever an asynchronous test starts 770 * Runs a batch of tests, yielding whenever an asynchronous test starts
730 * running. Tests will resume executing when such asynchronous test calls 771 * running. Tests will resume executing when such asynchronous test calls
731 * [done] or if it fails with an exception. 772 * [done] or if it fails with an exception.
732 */ 773 */
733 _nextBatch() { 774 _nextBatch() {
734 while (_currentTest < _tests.length) { 775 while (_currentTest < _tests.length) {
735 final testCase = _tests[_currentTest]; 776 final testCase = _tests[_currentTest];
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 } 874 }
834 875
835 /** Enable a test by ID. */ 876 /** Enable a test by ID. */
836 void enableTest(int testId) => _setTestEnabledState(testId, true); 877 void enableTest(int testId) => _setTestEnabledState(testId, true);
837 878
838 /** Disable a test by ID. */ 879 /** Disable a test by ID. */
839 void disableTest(int testId) => _setTestEnabledState(testId, false); 880 void disableTest(int testId) => _setTestEnabledState(testId, false);
840 881
841 /** Signature for a test function. */ 882 /** Signature for a test function. */
842 typedef void TestFunction(); 883 typedef void TestFunction();
OLDNEW
« no previous file with comments | « no previous file | tests/lib/unittest/unittest_test.dart » ('j') | tests/lib/unittest/unittest_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698