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

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

Issue 13464020: unittest: big cleanup, tightened test semantics (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fix breaks, remove toplevel _currentTestCaseIndex entirely Created 7 years, 8 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 | no next file » | 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 /**
6 * A library for writing dart unit tests. 6 * A library for writing dart unit tests.
7 * 7 *
8 * To import this library, install the 8 * To import this library, install the
9 * [unittest package](http://pub.dartlang.org/packages/unittest) via the pub 9 * [unittest package](http://pub.dartlang.org/packages/unittest) via the pub
10 * package manager. See the [Getting Started](http://pub.dartlang.org/doc) 10 * package manager. See the [Getting Started](http://pub.dartlang.org/doc)
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 206
207 /** Get the list of tests. */ 207 /** Get the list of tests. */
208 final List<TestCase> testCases = new UnmodifiableListView(_testCases); 208 final List<TestCase> testCases = new UnmodifiableListView(_testCases);
209 209
210 /** Setup function called before each test in a group */ 210 /** Setup function called before each test in a group */
211 Function _testSetup; 211 Function _testSetup;
212 212
213 /** Teardown function called after each test in a group */ 213 /** Teardown function called after each test in a group */
214 Function _testTeardown; 214 Function _testTeardown;
215 215
216 int _currentTestCaseIndex = 0; 216 TestCase _currentTestCase = null;
217 217
218 /** [TestCase] currently being executed. */ 218 /** [TestCase] currently being executed. */
219 TestCase get currentTestCase => 219 TestCase get currentTestCase => _currentTestCase;
220 (_currentTestCaseIndex >= 0 && _currentTestCaseIndex < _testCases.length)
221 ? _testCases[_currentTestCaseIndex]
222 : null;
223 220
224 /** Whether the framework is in an initialized state. */ 221 /** Whether the framework is in an initialized state. */
225 bool _initialized = false; 222 bool _initialized = false;
226 223
227 String _uncaughtErrorMessage = null; 224 String _uncaughtErrorMessage = null;
228 225
229 /** Test case result strings. */ 226 /** Test case result strings. */
230 // TODO(gram) we should change these constants to use a different string 227 // TODO(gram) we should change these constants to use a different string
231 // (so that writing 'FAIL' in the middle of a test doesn't 228 // (so that writing 'FAIL' in the middle of a test doesn't
232 // imply that the test fails). We can't do it without also changing 229 // imply that the test fails). We can't do it without also changing
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 } 284 }
288 285
289 /** Simulates spread arguments using named arguments. */ 286 /** Simulates spread arguments using named arguments. */
290 // TODO(sigmund): remove this class and simply use a closure with named 287 // TODO(sigmund): remove this class and simply use a closure with named
291 // arguments (if still applicable). 288 // arguments (if still applicable).
292 class _SpreadArgsHelper { 289 class _SpreadArgsHelper {
293 final Function callback; 290 final Function callback;
294 final int minExpectedCalls; 291 final int minExpectedCalls;
295 final int maxExpectedCalls; 292 final int maxExpectedCalls;
296 final Function isDone; 293 final Function isDone;
297 final int testNum; 294 final TestCase testCase;
298 final String id; 295 final String id;
299 int actualCalls = 0; 296 int actualCalls = 0;
300 TestCase testCase;
301 bool complete; 297 bool complete;
302 static const sentinel = const _Sentinel(); 298 static const sentinel = const _Sentinel();
303 299
304 _SpreadArgsHelper(Function callback, int minExpected, int maxExpected, 300 _SpreadArgsHelper(Function callback, int minExpected, int maxExpected,
305 Function isDone, String id) 301 Function isDone, String id)
306 : this.callback = callback, 302 : this.callback = callback,
307 minExpectedCalls = minExpected, 303 minExpectedCalls = minExpected,
308 maxExpectedCalls = (maxExpected == 0 && minExpected > 0) 304 maxExpectedCalls = (maxExpected == 0 && minExpected > 0)
309 ? minExpected 305 ? minExpected
310 : maxExpected, 306 : maxExpected,
311 this.isDone = isDone, 307 this.isDone = isDone,
312 testNum = _currentTestCaseIndex, 308 this.testCase = currentTestCase,
313 this.id = _makeCallbackId(id, callback) { 309 this.id = _makeCallbackId(id, callback) {
314 ensureInitialized(); 310 if(testCase == null) {
315 if (!(_currentTestCaseIndex >= 0 && 311 throw new StateError("No valid test, did you forget to run your test "
316 _currentTestCaseIndex < _testCases.length && 312 "inside a call to test()?");
317 _testCases[_currentTestCaseIndex] != null)) {
318 print("No valid test, did you forget to run your test inside a call "
319 "to test()?");
320 } 313 }
321 assert(_currentTestCaseIndex >= 0 && 314
322 _currentTestCaseIndex < _testCases.length &&
323 _testCases[_currentTestCaseIndex] != null);
324 testCase = _testCases[_currentTestCaseIndex];
325 if (isDone != null || minExpected > 0) { 315 if (isDone != null || minExpected > 0) {
326 testCase._callbackFunctionsOutstanding++; 316 testCase._callbackFunctionsOutstanding++;
327 complete = false; 317 complete = false;
328 } else { 318 } else {
329 complete = true; 319 complete = true;
330 } 320 }
331 } 321 }
332 322
333 static _makeCallbackId(String id, Function callback) { 323 static _makeCallbackId(String id, Function callback) {
334 // Try to create a reasonable id. 324 // Try to create a reasonable id.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 return callback(arg0, arg1, arg2); 388 return callback(arg0, arg1, arg2);
399 } else if (arg4 == sentinel) { 389 } else if (arg4 == sentinel) {
400 return callback(arg0, arg1, arg2, arg3); 390 return callback(arg0, arg1, arg2, arg3);
401 } else { 391 } else {
402 testCase.error( 392 testCase.error(
403 'unittest lib does not support callbacks with more than' 393 'unittest lib does not support callbacks with more than'
404 ' 4 arguments.', 394 ' 4 arguments.',
405 ''); 395 '');
406 } 396 }
407 }, 397 },
408 after, testNum); 398 after, testCase);
409 } 399 }
410 400
411 invoke0() { 401 invoke0() {
412 return _guardAsync( 402 return _guardAsync(
413 () { 403 () {
414 if (shouldCallBack()) { 404 if (shouldCallBack()) {
415 return callback(); 405 return callback();
416 } 406 }
417 }, 407 },
418 after, testNum); 408 after, testCase);
419 } 409 }
420 410
421 invoke1(arg1) { 411 invoke1(arg1) {
422 return _guardAsync( 412 return _guardAsync(
423 () { 413 () {
424 if (shouldCallBack()) { 414 if (shouldCallBack()) {
425 return callback(arg1); 415 return callback(arg1);
426 } 416 }
427 }, 417 },
428 after, testNum); 418 after, testCase);
429 } 419 }
430 420
431 invoke2(arg1, arg2) { 421 invoke2(arg1, arg2) {
432 return _guardAsync( 422 return _guardAsync(
433 () { 423 () {
434 if (shouldCallBack()) { 424 if (shouldCallBack()) {
435 return callback(arg1, arg2); 425 return callback(arg1, arg2);
436 } 426 }
437 }, 427 },
438 after, testNum); 428 after, testCase);
439 } 429 }
440 } 430 }
441 431
442 /** 432 /**
443 * Indicate that [callback] is expected to be called a [count] number of times 433 * Indicate that [callback] is expected to be called a [count] number of times
444 * (by default 1). The unittest framework will wait for the callback to run the 434 * (by default 1). The unittest framework will wait for the callback to run the
445 * specified [count] times before it continues with the following test. Using 435 * specified [count] times before it continues with the following test. Using
446 * [_expectAsync] will also ensure that errors that occur within [callback] are
447 * tracked and reported. [callback] should take between 0 and 4 positional
448 * arguments (named arguments are not supported here). [id] can be used
449 * to provide more descriptive error messages if the callback is called more
450 * often than expected.
451 */
452 Function _expectAsync(Function callback,
453 {int count: 1, int max: 0, String id}) {
454 return new _SpreadArgsHelper(callback, count, max, null, id).invoke;
455 }
456
457 /**
458 * Indicate that [callback] is expected to be called a [count] number of times
459 * (by default 1). The unittest framework will wait for the callback to run the
460 * specified [count] times before it continues with the following test. Using
461 * [expectAsync0] will also ensure that errors that occur within [callback] are 436 * [expectAsync0] will also ensure that errors that occur within [callback] are
462 * tracked and reported. [callback] should take 0 positional arguments (named 437 * tracked and reported. [callback] should take 0 positional arguments (named
463 * arguments are not supported). [id] can be used to provide more 438 * arguments are not supported). [id] can be used to provide more
464 * descriptive error messages if the callback is called more often than 439 * descriptive error messages if the callback is called more often than
465 * expected. [max] can be used to specify an upper bound on the number of 440 * expected. [max] can be used to specify an upper bound on the number of
466 * calls; if this is exceeded the test will fail (or be marked as in error if 441 * calls; if this is exceeded the test will fail (or be marked as in error if
467 * it was already complete). A value of 0 for [max] (the default) will set 442 * it was already complete). A value of 0 for [max] (the default) will set
468 * the upper bound to the same value as [count]; i.e. the callback should be 443 * the upper bound to the same value as [count]; i.e. the callback should be
469 * called exactly [count] times. A value of -1 for [max] will mean no upper 444 * called exactly [count] times. A value of -1 for [max] will mean no upper
470 * bound. 445 * bound.
(...skipping 13 matching lines...) Expand all
484 459
485 /** Like [expectAsync0] but [callback] should take 2 positional arguments. */ 460 /** Like [expectAsync0] but [callback] should take 2 positional arguments. */
486 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 461 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
487 Function expectAsync2(Function callback, 462 Function expectAsync2(Function callback,
488 {int count: 1, int max: 0, String id}) { 463 {int count: 1, int max: 0, String id}) {
489 return new _SpreadArgsHelper(callback, count, max, null, id).invoke2; 464 return new _SpreadArgsHelper(callback, count, max, null, id).invoke2;
490 } 465 }
491 466
492 /** 467 /**
493 * Indicate that [callback] is expected to be called until [isDone] returns 468 * Indicate that [callback] is expected to be called until [isDone] returns
494 * true. The unittest framework checks [isDone] after each callback and only
495 * when it returns true will it continue with the following test. Using
496 * [expectAsyncUntil] will also ensure that errors that occur within
497 * [callback] are tracked and reported. [callback] should take between 0 and
498 * 4 positional arguments (named arguments are not supported). [id] can be
499 * used to identify the callback in error messages (for example if it is called
500 * after the test case is complete).
501 */
502 Function _expectAsyncUntil(Function callback, Function isDone, {String id}) {
503 return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke;
504 }
505
506 /**
507 * Indicate that [callback] is expected to be called until [isDone] returns
508 * true. The unittest framework check [isDone] after each callback and only 469 * true. The unittest framework check [isDone] after each callback and only
509 * when it returns true will it continue with the following test. Using 470 * when it returns true will it continue with the following test. Using
510 * [expectAsyncUntil0] will also ensure that errors that occur within 471 * [expectAsyncUntil0] will also ensure that errors that occur within
511 * [callback] are tracked and reported. [callback] should take 0 positional 472 * [callback] are tracked and reported. [callback] should take 0 positional
512 * arguments (named arguments are not supported). [id] can be used to 473 * arguments (named arguments are not supported). [id] can be used to
513 * identify the callback in error messages (for example if it is called 474 * identify the callback in error messages (for example if it is called
514 * after the test case is complete). 475 * after the test case is complete).
515 */ 476 */
516 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 477 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
517 Function expectAsyncUntil0(Function callback, Function isDone, {String id}) { 478 Function expectAsyncUntil0(Function callback, Function isDone, {String id}) {
(...skipping 14 matching lines...) Expand all
532 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 493 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
533 Function expectAsyncUntil2(Function callback, Function isDone, {String id}) { 494 Function expectAsyncUntil2(Function callback, Function isDone, {String id}) {
534 return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke2; 495 return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke2;
535 } 496 }
536 497
537 /** 498 /**
538 * Wraps the [callback] in a new function and returns that function. The new 499 * Wraps the [callback] in a new function and returns that function. The new
539 * function will be able to handle exceptions by directing them to the correct 500 * function will be able to handle exceptions by directing them to the correct
540 * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that 501 * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
541 * might optionally be called but may never be called during the test. 502 * might optionally be called but may never be called during the test.
542 * [callback] should take between 0 and 4 positional arguments (named arguments
543 * are not supported). [id] can be used to identify the callback in error
544 * messages (for example if it is called after the test case is complete).
545 */
546 Function _protectAsync(Function callback, {String id}) {
547 return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke;
548 }
549
550 /**
551 * Wraps the [callback] in a new function and returns that function. The new
552 * function will be able to handle exceptions by directing them to the correct
553 * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
554 * might optionally be called but may never be called during the test.
555 * [callback] should take 0 positional arguments (named arguments are not 503 * [callback] should take 0 positional arguments (named arguments are not
556 * supported). [id] can be used to identify the callback in error 504 * supported). [id] can be used to identify the callback in error
557 * messages (for example if it is called after the test case is complete). 505 * messages (for example if it is called after the test case is complete).
558 */ 506 */
559 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 507 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
560 Function protectAsync0(Function callback, {String id}) { 508 Function protectAsync0(Function callback, {String id}) {
561 return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke0; 509 return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke0;
562 } 510 }
563 511
564 /** 512 /**
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 563
616 /** 564 /**
617 * Register a [setUp] function for a test [group]. This function will 565 * Register a [setUp] function for a test [group]. This function will
618 * be called before each test in the group is run. Note that if groups 566 * be called before each test in the group is run. Note that if groups
619 * are nested only the most locally scoped [setUpTest] function will be run. 567 * are nested only the most locally scoped [setUpTest] function will be run.
620 * [setUp] and [tearDown] should be called within the [group] before any 568 * [setUp] and [tearDown] should be called within the [group] before any
621 * calls to [test]. The [setupTest] function can be asynchronous; in this 569 * calls to [test]. The [setupTest] function can be asynchronous; in this
622 * case it must return a [Future]. 570 * case it must return a [Future].
623 */ 571 */
624 void setUp(Function setupTest) { 572 void setUp(Function setupTest) {
573 _requireNotRunning();
kevmoo-old 2013/04/06 23:10:03 Should be a call to ensureInitialized(), but pub t
625 _testSetup = setupTest; 574 _testSetup = setupTest;
626 } 575 }
627 576
628 /** 577 /**
629 * Register a [tearDown] function for a test [group]. This function will 578 * Register a [tearDown] function for a test [group]. This function will
630 * be called after each test in the group is run. Note that if groups 579 * be called after each test in the group is run. Note that if groups
631 * are nested only the most locally scoped [teardownTest] function will be run. 580 * are nested only the most locally scoped [teardownTest] function will be run.
632 * [setUp] and [tearDown] should be called within the [group] before any 581 * [setUp] and [tearDown] should be called within the [group] before any
633 * calls to [test]. The [teardownTest] function can be asynchronous; in this 582 * calls to [test]. The [teardownTest] function can be asynchronous; in this
634 * case it must return a [Future]. 583 * case it must return a [Future].
635 */ 584 */
636 void tearDown(Function teardownTest) { 585 void tearDown(Function teardownTest) {
586 _requireNotRunning();
kevmoo-old 2013/04/06 23:10:03 Should be a call to ensureInitialized(), but pub t
637 _testTeardown = teardownTest; 587 _testTeardown = teardownTest;
638 } 588 }
639 589
640 /** Advance to the next test case. */
641 void _nextTestCase() {
642 _defer(() {
643 _currentTestCaseIndex++;
644 _nextBatch();
645 });
646 }
647
648 /** 590 /**
649 * Utility function that can be used to notify the test framework that an 591 * Utility function that can be used to notify the test framework that an
650 * error was caught outside of this library. 592 * error was caught outside of this library.
651 */ 593 */
652 void _reportTestError(String msg, String trace) { 594 void _reportTestError(String msg, String trace) {
653 if (_currentTestCaseIndex < _testCases.length) { 595 if (currentTestCase != null) {
654 final testCase = _testCases[_currentTestCaseIndex]; 596 currentTestCase.error(msg, trace);
655 testCase.error(msg, trace);
656 } else { 597 } else {
657 _uncaughtErrorMessage = "$msg: $trace"; 598 _uncaughtErrorMessage = "$msg: $trace";
658 } 599 }
659 } 600 }
660 601
661 /** 602 /**
662 * Runs [callback] at the end of the event loop. Note that we don't wrap 603 * Runs [callback] at the end of the event loop. Note that we don't wrap
663 * the callback in guardAsync; this is for test framework functions which 604 * the callback in guardAsync; this is for test framework functions which
664 * should not be throwing unexpected exceptions that end up failing test 605 * should not be throwing unexpected exceptions that end up failing test
665 * cases! Furthermore, we need the final exception to be thrown but not 606 * cases! Furthermore, we need the final exception to be thrown but not
666 * caught by the test framework if any test cases failed. However, tests 607 * caught by the test framework if any test cases failed. However, tests
667 * that make use of a similar defer function *should* wrap the callback 608 * that make use of a similar defer function *should* wrap the callback
668 * (as we do in unitttest_test.dart). 609 * (as we do in unitttest_test.dart).
669 */ 610 */
670 _defer(void callback()) { 611 _defer(void callback()) {
671 (new Future.immediate(null)).then((_) => callback()); 612 (new Future.immediate(null)).then((_) => callback());
672 } 613 }
673 614
674 void rerunTests() { 615 void rerunTests() {
675 _uncaughtErrorMessage = null; 616 assert(_uncaughtErrorMessage == null);
kevmoo-old 2013/04/06 23:10:03 Need a TODO about getting rid of this. Perhaps we
676 _initialized = true; // We don't want to reset the test array.
677 runTests(); 617 runTests();
678 } 618 }
679 619
680 /** 620 /**
681 * Filter the tests. [testFilter] can be a [RegExp], a [String] or a 621 * Filter the tests. [testFilter] can be a [RegExp], a [String] or a
682 * predicate function. This is different to enabling/disabling tests 622 * predicate function. This is different to enabling/disabling tests
683 * in that it removes the tests completely. 623 * in that it removes the tests completely.
684 */ 624 */
685 void filterTests(testFilter) { 625 void filterTests(testFilter) {
686 var filterFunction; 626 _requireNotRunning();
kevmoo-old 2013/04/06 23:10:03 Should be a call to ensureInitialized(), but pub t
627 Function filterFunction;
687 if (testFilter is String) { 628 if (testFilter is String) {
688 RegExp re = new RegExp(testFilter); 629 RegExp re = new RegExp(testFilter);
689 filterFunction = (t) => re.hasMatch(t.description); 630 filterFunction = (t) => re.hasMatch(t.description);
690 } else if (testFilter is RegExp) { 631 } else if (testFilter is RegExp) {
691 filterFunction = (t) => testFilter.hasMatch(t.description); 632 filterFunction = (t) => testFilter.hasMatch(t.description);
692 } else if (testFilter is Function) { 633 } else if (testFilter is Function) {
693 filterFunction = testFilter; 634 filterFunction = testFilter;
694 } 635 }
695 _testCases.retainWhere(filterFunction); 636 _testCases.retainWhere(filterFunction);
696 } 637 }
697 638
698 /** Runs all queued tests, one at a time. */ 639 /** Runs all queued tests, one at a time. */
699 void runTests() { 640 void runTests() {
700 _ensureInitialized(false); 641 _ensureInitialized(false);
701 _currentTestCaseIndex = 0; 642 assert(_currentTestCase == null);
kevmoo-old 2013/04/06 23:10:03 Overly paranoid. _ensureInitialized() throws if th
643
702 _currentGroup = ''; 644 _currentGroup = '';
703 645
704 // If we are soloing a test, remove all the others. 646 // If we are soloing a test, remove all the others.
705 if (_soloTest != null) { 647 if (_soloTest != null) {
706 filterTests((t) => t == _soloTest); 648 filterTests((t) => t == _soloTest);
707 } 649 }
708 650
709 _config.onStart(); 651 _config.onStart();
710 652
711 _defer(() { 653 _defer(() {
712 _nextBatch(); 654 _nextBatch();
713 }); 655 });
714 } 656 }
715 657
716 /** 658 /**
717 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, it is 659 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, it is
718 * passed to the corresponding test. 660 * passed to the corresponding test.
719 * 661 *
720 * The value returned by [tryBody] (if any) is returned by [guardAsync]. 662 * The value returned by [tryBody] (if any) is returned by [guardAsync].
721 */ 663 */
722 guardAsync(Function tryBody) { 664 guardAsync(Function tryBody) {
723 return _guardAsync(tryBody, null, _currentTestCaseIndex); 665 return _guardAsync(tryBody, null, currentTestCase);
724 } 666 }
725 667
726 _guardAsync(Function tryBody, Function finallyBody, int testNum) { 668 _guardAsync(Function tryBody, Function finallyBody, TestCase testCase) {
727 assert(testNum >= 0); 669 assert(testCase != null);
728 try { 670 try {
729 return tryBody(); 671 return tryBody();
730 } catch (e, trace) { 672 } catch (e, trace) {
731 _registerException(testNum, e, trace); 673 _registerException(testCase, e, trace);
732 } finally { 674 } finally {
733 if (finallyBody != null) finallyBody(); 675 if (finallyBody != null) finallyBody();
734 } 676 }
735 } 677 }
736 678
737 /** 679 /**
738 * Registers that an exception was caught for the current test. 680 * Registers that an exception was caught for the current test.
739 */ 681 */
740 void registerException(e, [trace]) { 682 void registerException(e, [trace]) {
741 _registerException(_currentTestCaseIndex, e, trace); 683 _registerException(currentTestCase, e, trace);
742 } 684 }
743 685
744 /** 686 /**
745 * Registers that an exception was caught for the current test. 687 * Registers that an exception was caught for the current test.
746 */ 688 */
747 void _registerException(testNum, e, [trace]) { 689 void _registerException(TestCase testCase, e, [trace]) {
690 assert(testCase != null);
748 trace = trace == null ? '' : trace.toString(); 691 trace = trace == null ? '' : trace.toString();
749 String message = (e is TestFailure) ? e.message : 'Caught $e'; 692 String message = (e is TestFailure) ? e.message : 'Caught $e';
750 if (_testCases[testNum].result == null) { 693 if (testCase.result == null) {
751 _testCases[testNum].fail(message, trace); 694 testCase.fail(message, trace);
752 } else { 695 } else {
753 _testCases[testNum].error(message, trace); 696 testCase.error(message, trace);
754 } 697 }
755 } 698 }
756 699
757 /** 700 // TODO(kevmoo) we could imagine runTests returning a future...
Andrei Mouravski 2013/04/07 19:15:54 Re-add some doc comments here. Also, this TODO do
kevmoo-old 2013/04/18 16:13:55 More doc comments are coming in an update. Should
758 * Runs a batch of tests, yielding whenever an asynchronous test starts 701 Future _nextBatch([int index = 0]) {
kevmoo-old 2013/04/06 23:10:03 FYI: I looked into using Future.forEach here, but
Andrei Mouravski 2013/04/07 19:15:54 If the Future.forEach has poor performance, please
759 * running. Tests will resume executing when such asynchronous test calls 702 for(int i = index; i < _testCases.length; i++) {
Andrei Mouravski 2013/04/07 19:15:54 I'm not entirely clear on what this function is do
gram 2013/04/18 20:46:08 The problem with that is you now have unpredictabl
760 * [done] or if it fails with an exception. 703 _currentTestCase = _testCases[i];
761 */ 704
762 void _nextBatch() { 705 Future f = guardAsync(_currentTestCase._run);
763 while (true) { 706
764 if (_currentTestCaseIndex >= _testCases.length) { 707 if(f != null) {
765 _completeTests(); 708 return f.then((_) => _nextBatch(i + 1));
Andrei Mouravski 2013/04/07 19:15:54 Should probably be whenComplete
kevmoo-old 2013/04/18 16:13:55 guardAsync should never fail. If it returns a futu
766 break;
767 } 709 }
768 final testCase = _testCases[_currentTestCaseIndex];
769 var f = _guardAsync(testCase._run, null, _currentTestCaseIndex);
770 if (f != null) {
771 f.whenComplete(() {
772 _nextTestCase(); // Schedule the next test.
773 });
774 break;
775 }
776 _currentTestCaseIndex++;
777 } 710 }
711 _currentTestCase = null;
712 return new Future.of(_completeTests);
778 } 713 }
779 714
780 /** Publish results on the page and notify controller. */ 715 /** Publish results on the page and notify controller. */
781 void _completeTests() { 716 void _completeTests() {
782 if (!_initialized) return; 717 assert(_initialized);
Andrei Mouravski 2013/04/07 19:15:54 Now that I think of it, it's kind of weird to have
718 assert(_currentTestCase == null);
719
783 int passed = 0; 720 int passed = 0;
784 int failed = 0; 721 int failed = 0;
785 int errors = 0; 722 int errors = 0;
786 723
787 for (TestCase t in _testCases) { 724 for (TestCase t in _testCases) {
788 switch (t.result) { 725 switch (t.result) {
789 case PASS: passed++; break; 726 case PASS: passed++; break;
790 case FAIL: failed++; break; 727 case FAIL: failed++; break;
791 case ERROR: errors++; break; 728 case ERROR: errors++; break;
792 } 729 }
793 } 730 }
794 _config.onSummary(passed, failed, errors, testCases, _uncaughtErrorMessage); 731 _config.onSummary(passed, failed, errors, testCases, _uncaughtErrorMessage);
795 _config.onDone(passed > 0 && failed == 0 && errors == 0 && 732 _config.onDone(passed > 0 && failed == 0 && errors == 0 &&
796 _uncaughtErrorMessage == null); 733 _uncaughtErrorMessage == null);
797 _initialized = false; 734
735 _uncaughtErrorMessage = null;
798 } 736 }
799 737
800 String _fullSpec(String spec) { 738 String _fullSpec(String spec) {
801 if (spec == null) return '$_currentGroup'; 739 if (spec == null) return '$_currentGroup';
802 return _currentGroup != '' ? '$_currentGroup$groupSep$spec' : spec; 740 return _currentGroup != '' ? '$_currentGroup$groupSep$spec' : spec;
803 } 741 }
804 742
805 /** 743 /**
806 * Lazily initializes the test library if not already initialized. 744 * Lazily initializes the test library if not already initialized.
807 */ 745 */
808 void ensureInitialized() { 746 void ensureInitialized() {
809 _ensureInitialized(true); 747 _ensureInitialized(true);
810 } 748 }
811 749
750 void _requireNotRunning() {
kevmoo-old 2013/04/06 23:10:03 Once everything has moved to ensureInitialized() .
751 if(_currentTestCase != null) {
752 throw new StateError("A forbidden operation occured "
kevmoo-old 2013/04/06 23:10:03 I've pondered allowing a string to be passed in he
Andrei Mouravski 2013/04/07 19:15:54 See my comment about asserts. I sort of want meta-
753 "while tests were running");
754 }
755 }
756
812 void _ensureInitialized(bool configAutoStart) { 757 void _ensureInitialized(bool configAutoStart) {
758 _requireNotRunning();
813 if (_initialized) { 759 if (_initialized) {
814 return; 760 return;
815 } 761 }
816 _initialized = true; 762 _initialized = true;
817 // Hook our async guard into the matcher library. 763 // Hook our async guard into the matcher library.
818 wrapAsync = (f, [id]) => expectAsync1(f, id: id); 764 wrapAsync = (f, [id]) => expectAsync1(f, id: id);
819 765
820 _uncaughtErrorMessage = null; 766 _uncaughtErrorMessage = null;
821 767
822 if (_config == null) { 768 if (_config == null) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 } 803 }
858 804
859 /** Enable a test by ID. */ 805 /** Enable a test by ID. */
860 void enableTest(int testId) => _setTestEnabledState(testId, true); 806 void enableTest(int testId) => _setTestEnabledState(testId, true);
861 807
862 /** Disable a test by ID. */ 808 /** Disable a test by ID. */
863 void disableTest(int testId) => _setTestEnabledState(testId, false); 809 void disableTest(int testId) => _setTestEnabledState(testId, false);
864 810
865 /** Signature for a test function. */ 811 /** Signature for a test function. */
866 typedef dynamic TestFunction(); 812 typedef dynamic TestFunction();
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698