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

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

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