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

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

Powered by Google App Engine
This is Rietveld 408576698