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

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: removed unused private methods while we're at it 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 int _currentTestCaseIndex = null;
217 217
218 /** [TestCase] currently being executed. */ 218 /** [TestCase] currently being executed. */
219 TestCase get currentTestCase => 219 TestCase get currentTestCase =>
220 (_currentTestCaseIndex >= 0 && _currentTestCaseIndex < _testCases.length) 220 (_currentTestCaseIndex != null && _currentTestCaseIndex >= 0 &&
221 ? _testCases[_currentTestCaseIndex] 221 _currentTestCaseIndex < _testCases.length)
222 ? _testCases[_currentTestCaseIndex]
222 : null; 223 : null;
223 224
224 /** Whether the framework is in an initialized state. */ 225 /** Whether the framework is in an initialized state. */
225 bool _initialized = false; 226 bool _initialized = false;
226 227
227 String _uncaughtErrorMessage = null; 228 String _uncaughtErrorMessage = null;
228 229
229 /** Test case result strings. */ 230 /** Test case result strings. */
230 // TODO(gram) we should change these constants to use a different string 231 // 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 232 // (so that writing 'FAIL' in the middle of a test doesn't
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 } 288 }
288 289
289 /** Simulates spread arguments using named arguments. */ 290 /** Simulates spread arguments using named arguments. */
290 // TODO(sigmund): remove this class and simply use a closure with named 291 // TODO(sigmund): remove this class and simply use a closure with named
291 // arguments (if still applicable). 292 // arguments (if still applicable).
292 class _SpreadArgsHelper { 293 class _SpreadArgsHelper {
293 final Function callback; 294 final Function callback;
294 final int minExpectedCalls; 295 final int minExpectedCalls;
295 final int maxExpectedCalls; 296 final int maxExpectedCalls;
296 final Function isDone; 297 final Function isDone;
297 final int testNum; 298 final TestCase testCase;
298 final String id; 299 final String id;
299 int actualCalls = 0; 300 int actualCalls = 0;
300 TestCase testCase;
301 bool complete; 301 bool complete;
302 static const sentinel = const _Sentinel(); 302 static const sentinel = const _Sentinel();
303 303
304 _SpreadArgsHelper(Function callback, int minExpected, int maxExpected, 304 _SpreadArgsHelper(Function callback, int minExpected, int maxExpected,
305 Function isDone, String id) 305 Function isDone, String id)
306 : this.callback = callback, 306 : this.callback = callback,
307 minExpectedCalls = minExpected, 307 minExpectedCalls = minExpected,
308 maxExpectedCalls = (maxExpected == 0 && minExpected > 0) 308 maxExpectedCalls = (maxExpected == 0 && minExpected > 0)
309 ? minExpected 309 ? minExpected
310 : maxExpected, 310 : maxExpected,
311 this.isDone = isDone, 311 this.isDone = isDone,
312 testNum = _currentTestCaseIndex, 312 this.testCase = currentTestCase,
313 this.id = _makeCallbackId(id, callback) { 313 this.id = _makeCallbackId(id, callback) {
314 ensureInitialized(); 314 if(testCase == null) {
315 if (!(_currentTestCaseIndex >= 0 && 315 throw new StateError("No valid test, did you forget to run your test "
316 _currentTestCaseIndex < _testCases.length && 316 "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 } 317 }
321 assert(_currentTestCaseIndex >= 0 && 318
322 _currentTestCaseIndex < _testCases.length &&
323 _testCases[_currentTestCaseIndex] != null);
324 testCase = _testCases[_currentTestCaseIndex];
325 if (isDone != null || minExpected > 0) { 319 if (isDone != null || minExpected > 0) {
326 testCase._callbackFunctionsOutstanding++; 320 testCase._callbackFunctionsOutstanding++;
327 complete = false; 321 complete = false;
328 } else { 322 } else {
329 complete = true; 323 complete = true;
330 } 324 }
331 } 325 }
332 326
333 static _makeCallbackId(String id, Function callback) { 327 static _makeCallbackId(String id, Function callback) {
334 // Try to create a reasonable id. 328 // Try to create a reasonable id.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 return callback(arg0, arg1, arg2); 392 return callback(arg0, arg1, arg2);
399 } else if (arg4 == sentinel) { 393 } else if (arg4 == sentinel) {
400 return callback(arg0, arg1, arg2, arg3); 394 return callback(arg0, arg1, arg2, arg3);
401 } else { 395 } else {
402 testCase.error( 396 testCase.error(
403 'unittest lib does not support callbacks with more than' 397 'unittest lib does not support callbacks with more than'
404 ' 4 arguments.', 398 ' 4 arguments.',
405 ''); 399 '');
406 } 400 }
407 }, 401 },
408 after, testNum); 402 after, testCase);
409 } 403 }
410 404
411 invoke0() { 405 invoke0() {
412 return _guardAsync( 406 return _guardAsync(
413 () { 407 () {
414 if (shouldCallBack()) { 408 if (shouldCallBack()) {
415 return callback(); 409 return callback();
416 } 410 }
417 }, 411 },
418 after, testNum); 412 after, testCase);
419 } 413 }
420 414
421 invoke1(arg1) { 415 invoke1(arg1) {
422 return _guardAsync( 416 return _guardAsync(
423 () { 417 () {
424 if (shouldCallBack()) { 418 if (shouldCallBack()) {
425 return callback(arg1); 419 return callback(arg1);
426 } 420 }
427 }, 421 },
428 after, testNum); 422 after, testCase);
429 } 423 }
430 424
431 invoke2(arg1, arg2) { 425 invoke2(arg1, arg2) {
432 return _guardAsync( 426 return _guardAsync(
433 () { 427 () {
434 if (shouldCallBack()) { 428 if (shouldCallBack()) {
435 return callback(arg1, arg2); 429 return callback(arg1, arg2);
436 } 430 }
437 }, 431 },
438 after, testNum); 432 after, testCase);
439 } 433 }
440 } 434 }
441 435
442 /** 436 /**
443 * Indicate that [callback] is expected to be called a [count] number of times 437 * 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 438 * (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 439 * 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 440 * [expectAsync0] will also ensure that errors that occur within [callback] are
462 * tracked and reported. [callback] should take 0 positional arguments (named 441 * tracked and reported. [callback] should take 0 positional arguments (named
463 * arguments are not supported). [id] can be used to provide more 442 * arguments are not supported). [id] can be used to provide more
464 * descriptive error messages if the callback is called more often than 443 * 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 444 * 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 445 * 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 446 * 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 447 * 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 448 * called exactly [count] times. A value of -1 for [max] will mean no upper
470 * bound. 449 * bound.
(...skipping 13 matching lines...) Expand all
484 463
485 /** Like [expectAsync0] but [callback] should take 2 positional arguments. */ 464 /** Like [expectAsync0] but [callback] should take 2 positional arguments. */
486 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 465 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
487 Function expectAsync2(Function callback, 466 Function expectAsync2(Function callback,
488 {int count: 1, int max: 0, String id}) { 467 {int count: 1, int max: 0, String id}) {
489 return new _SpreadArgsHelper(callback, count, max, null, id).invoke2; 468 return new _SpreadArgsHelper(callback, count, max, null, id).invoke2;
490 } 469 }
491 470
492 /** 471 /**
493 * Indicate that [callback] is expected to be called until [isDone] returns 472 * 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 473 * true. The unittest framework check [isDone] after each callback and only
509 * when it returns true will it continue with the following test. Using 474 * when it returns true will it continue with the following test. Using
510 * [expectAsyncUntil0] will also ensure that errors that occur within 475 * [expectAsyncUntil0] will also ensure that errors that occur within
511 * [callback] are tracked and reported. [callback] should take 0 positional 476 * [callback] are tracked and reported. [callback] should take 0 positional
512 * arguments (named arguments are not supported). [id] can be used to 477 * arguments (named arguments are not supported). [id] can be used to
513 * identify the callback in error messages (for example if it is called 478 * identify the callback in error messages (for example if it is called
514 * after the test case is complete). 479 * after the test case is complete).
515 */ 480 */
516 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 481 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
517 Function expectAsyncUntil0(Function callback, Function isDone, {String id}) { 482 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. 497 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
533 Function expectAsyncUntil2(Function callback, Function isDone, {String id}) { 498 Function expectAsyncUntil2(Function callback, Function isDone, {String id}) {
534 return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke2; 499 return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke2;
535 } 500 }
536 501
537 /** 502 /**
538 * Wraps the [callback] in a new function and returns that function. The new 503 * 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 504 * 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 505 * 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. 506 * 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 507 * [callback] should take 0 positional arguments (named arguments are not
556 * supported). [id] can be used to identify the callback in error 508 * 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). 509 * messages (for example if it is called after the test case is complete).
558 */ 510 */
559 // TODO(sigmund): deprecate this API when issue 2706 is fixed. 511 // TODO(sigmund): deprecate this API when issue 2706 is fixed.
560 Function protectAsync0(Function callback, {String id}) { 512 Function protectAsync0(Function callback, {String id}) {
561 return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke0; 513 return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke0;
562 } 514 }
563 515
564 /** 516 /**
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 567
616 /** 568 /**
617 * Register a [setUp] function for a test [group]. This function will 569 * 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 570 * 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. 571 * are nested only the most locally scoped [setUpTest] function will be run.
620 * [setUp] and [tearDown] should be called within the [group] before any 572 * [setUp] and [tearDown] should be called within the [group] before any
621 * calls to [test]. The [setupTest] function can be asynchronous; in this 573 * calls to [test]. The [setupTest] function can be asynchronous; in this
622 * case it must return a [Future]. 574 * case it must return a [Future].
623 */ 575 */
624 void setUp(Function setupTest) { 576 void setUp(Function setupTest) {
577 ensureInitialized();
kevmoo-old 2013/04/06 17:56:34 broke folks who set a custom config after this...w
Andrei Mouravski 2013/04/06 22:41:53 Whom did you break? If someone is doing something
kevmoo-old 2013/04/18 16:13:54 Since I *am* changing the semantics of unittest la
625 _testSetup = setupTest; 578 _testSetup = setupTest;
626 } 579 }
627 580
628 /** 581 /**
629 * Register a [tearDown] function for a test [group]. This function will 582 * 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 583 * 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. 584 * are nested only the most locally scoped [teardownTest] function will be run.
632 * [setUp] and [tearDown] should be called within the [group] before any 585 * [setUp] and [tearDown] should be called within the [group] before any
633 * calls to [test]. The [teardownTest] function can be asynchronous; in this 586 * calls to [test]. The [teardownTest] function can be asynchronous; in this
634 * case it must return a [Future]. 587 * case it must return a [Future].
635 */ 588 */
636 void tearDown(Function teardownTest) { 589 void tearDown(Function teardownTest) {
590 ensureInitialized();
kevmoo-old 2013/04/06 17:56:34 broke folks who set a custom config after this...w
637 _testTeardown = teardownTest; 591 _testTeardown = teardownTest;
638 } 592 }
639 593
640 /** Advance to the next test case. */ 594 /** Advance to the next test case. */
641 void _nextTestCase() { 595 void _nextTestCase() {
642 _defer(() { 596 _defer(() {
643 _currentTestCaseIndex++; 597 _currentTestCaseIndex++;
644 _nextBatch(); 598 _nextBatch();
645 }); 599 });
646 } 600 }
647 601
648 /** 602 /**
649 * Utility function that can be used to notify the test framework that an 603 * Utility function that can be used to notify the test framework that an
650 * error was caught outside of this library. 604 * error was caught outside of this library.
651 */ 605 */
652 void _reportTestError(String msg, String trace) { 606 void _reportTestError(String msg, String trace) {
653 if (_currentTestCaseIndex < _testCases.length) { 607 if (currentTestCase != null) {
Andrei Mouravski 2013/04/06 22:41:53 How about a private getter: bool get _isCurrentTes
kevmoo-old 2013/04/06 23:00:40 I'm confused. The latest commit eliminated the _cu
kevmoo-old 2013/04/18 16:13:54 _currentTestCaseIndex has been internalized into _
654 final testCase = _testCases[_currentTestCaseIndex]; 608 currentTestCase.error(msg, trace);
655 testCase.error(msg, trace);
656 } else { 609 } else {
657 _uncaughtErrorMessage = "$msg: $trace"; 610 _uncaughtErrorMessage = "$msg: $trace";
658 } 611 }
659 } 612 }
660 613
661 /** 614 /**
662 * Runs [callback] at the end of the event loop. Note that we don't wrap 615 * 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 616 * the callback in guardAsync; this is for test framework functions which
664 * should not be throwing unexpected exceptions that end up failing test 617 * should not be throwing unexpected exceptions that end up failing test
665 * cases! Furthermore, we need the final exception to be thrown but not 618 * 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 619 * 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 620 * that make use of a similar defer function *should* wrap the callback
668 * (as we do in unitttest_test.dart). 621 * (as we do in unitttest_test.dart).
669 */ 622 */
670 _defer(void callback()) { 623 _defer(void callback()) {
671 (new Future.immediate(null)).then((_) => callback()); 624 (new Future.immediate(null)).then((_) => callback());
672 } 625 }
673 626
674 void rerunTests() { 627 void rerunTests() {
Andrei Mouravski 2013/04/06 22:41:53 Why do we even have this? What makes this differen
kevmoo-old 2013/04/06 23:00:40 It's legacy. It's used by interactive html configu
Andrei Mouravski 2013/04/07 19:15:54 On your radar: good. Add a TODO: better. File a bu
kevmoo-old 2013/04/18 16:13:54 It's being used. I've verified the behavior. We ca
gram 2013/04/18 20:46:08 We could eliminate this now. Originally there was
675 _uncaughtErrorMessage = null; 628 assert(_uncaughtErrorMessage == null);
Andrei Mouravski 2013/04/06 22:41:53 Can you make a common "reset()" method somewhere?
kevmoo-old 2013/04/06 23:00:40 Agreed. Things for us to discuss on Tuesday.
Andrei Mouravski 2013/04/07 19:15:54 I don't think we need to discuss. This is just som
kevmoo-old 2013/04/18 16:13:54 I'm not going to modify the current semantic furth
676 _initialized = true; // We don't want to reset the test array.
677 runTests(); 629 runTests();
678 } 630 }
679 631
680 /** 632 /**
681 * Filter the tests. [testFilter] can be a [RegExp], a [String] or a 633 * Filter the tests. [testFilter] can be a [RegExp], a [String] or a
682 * predicate function. This is different to enabling/disabling tests 634 * predicate function. This is different to enabling/disabling tests
683 * in that it removes the tests completely. 635 * in that it removes the tests completely.
684 */ 636 */
685 void filterTests(testFilter) { 637 void filterTests(testFilter) {
686 var filterFunction; 638 _ensureInitialized(false);
kevmoo-old 2013/04/06 17:56:34 broke folks who set a custom config after this...w
639 Function filterFunction;
687 if (testFilter is String) { 640 if (testFilter is String) {
688 RegExp re = new RegExp(testFilter); 641 RegExp re = new RegExp(testFilter);
689 filterFunction = (t) => re.hasMatch(t.description); 642 filterFunction = (t) => re.hasMatch(t.description);
690 } else if (testFilter is RegExp) { 643 } else if (testFilter is RegExp) {
691 filterFunction = (t) => testFilter.hasMatch(t.description); 644 filterFunction = (t) => testFilter.hasMatch(t.description);
692 } else if (testFilter is Function) { 645 } else if (testFilter is Function) {
693 filterFunction = testFilter; 646 filterFunction = testFilter;
694 } 647 }
695 _testCases.retainWhere(filterFunction); 648 _testCases.retainWhere(filterFunction);
696 } 649 }
697 650
698 /** Runs all queued tests, one at a time. */ 651 /** Runs all queued tests, one at a time. */
699 void runTests() { 652 void runTests() {
700 _ensureInitialized(false); 653 _ensureInitialized(false);
654 assert(_currentTestCaseIndex == null);
Andrei Mouravski 2013/04/06 22:41:53 If this assert is a post-condition on _ensureIntia
kevmoo-old 2013/04/06 23:00:40 See latest update. This is now an assert around _c
655
701 _currentTestCaseIndex = 0; 656 _currentTestCaseIndex = 0;
702 _currentGroup = ''; 657 _currentGroup = '';
703 658
704 // If we are soloing a test, remove all the others. 659 // If we are soloing a test, remove all the others.
705 if (_soloTest != null) { 660 if (_soloTest != null) {
706 filterTests((t) => t == _soloTest); 661 filterTests((t) => t == _soloTest);
707 } 662 }
708 663
709 _config.onStart(); 664 _config.onStart();
710 665
711 _defer(() { 666 _defer(() {
712 _nextBatch(); 667 _nextBatch();
713 }); 668 });
714 } 669 }
715 670
716 /** 671 /**
717 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, it is 672 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, it is
718 * passed to the corresponding test. 673 * passed to the corresponding test.
719 * 674 *
720 * The value returned by [tryBody] (if any) is returned by [guardAsync]. 675 * The value returned by [tryBody] (if any) is returned by [guardAsync].
721 */ 676 */
722 guardAsync(Function tryBody) { 677 guardAsync(Function tryBody) {
723 return _guardAsync(tryBody, null, _currentTestCaseIndex); 678 return _guardAsync(tryBody, null, currentTestCase);
724 } 679 }
725 680
726 _guardAsync(Function tryBody, Function finallyBody, int testNum) { 681 _guardAsync(Function tryBody, Function finallyBody, TestCase testCase) {
727 assert(testNum >= 0); 682 assert(testCase != null);
728 try { 683 try {
729 return tryBody(); 684 return tryBody();
730 } catch (e, trace) { 685 } catch (e, trace) {
731 _registerException(testNum, e, trace); 686 _registerException(testCase, e, trace);
732 } finally { 687 } finally {
733 if (finallyBody != null) finallyBody(); 688 if (finallyBody != null) finallyBody();
734 } 689 }
735 } 690 }
736 691
737 /** 692 /**
738 * Registers that an exception was caught for the current test. 693 * Registers that an exception was caught for the current test.
739 */ 694 */
740 void registerException(e, [trace]) { 695 void registerException(e, [trace]) {
Andrei Mouravski 2013/04/06 22:41:53 Is there a good reason that this is top-level?
kevmoo-old 2013/04/06 23:00:40 It was used by layout unit test random, but that's
Andrei Mouravski 2013/04/07 19:15:54 Consider removing it? Or actually remove it. ;]
kevmoo-old 2013/04/18 16:13:54 scheduled_test uses this
741 _registerException(_currentTestCaseIndex, e, trace); 696 _registerException(currentTestCase, e, trace);
742 } 697 }
743 698
744 /** 699 /**
745 * Registers that an exception was caught for the current test. 700 * Registers that an exception was caught for the current test.
746 */ 701 */
747 void _registerException(testNum, e, [trace]) { 702 void _registerException(TestCase testCase, e, [trace]) {
703 assert(testCase != null);
748 trace = trace == null ? '' : trace.toString(); 704 trace = trace == null ? '' : trace.toString();
749 String message = (e is TestFailure) ? e.message : 'Caught $e'; 705 String message = (e is TestFailure) ? e.message : 'Caught $e';
750 if (_testCases[testNum].result == null) { 706 if (testCase.result == null) {
751 _testCases[testNum].fail(message, trace); 707 testCase.fail(message, trace);
752 } else { 708 } else {
753 _testCases[testNum].error(message, trace); 709 testCase.error(message, trace);
754 } 710 }
755 } 711 }
756 712
757 /** 713 /**
758 * Runs a batch of tests, yielding whenever an asynchronous test starts 714 * Runs a batch of tests, yielding whenever an asynchronous test starts
759 * running. Tests will resume executing when such asynchronous test calls 715 * running. Tests will resume executing when such asynchronous test calls
760 * [done] or if it fails with an exception. 716 * [done] or if it fails with an exception.
761 */ 717 */
762 void _nextBatch() { 718 void _nextBatch() {
763 while (true) { 719 while (true) {
764 if (_currentTestCaseIndex >= _testCases.length) { 720 if (_currentTestCaseIndex >= _testCases.length) {
765 _completeTests(); 721 _completeTests();
766 break; 722 break;
767 } 723 }
768 final testCase = _testCases[_currentTestCaseIndex]; 724 var f = guardAsync(currentTestCase._run);
769 var f = _guardAsync(testCase._run, null, _currentTestCaseIndex);
770 if (f != null) { 725 if (f != null) {
771 f.whenComplete(() { 726 f.whenComplete(() {
772 _nextTestCase(); // Schedule the next test. 727 _nextTestCase(); // Schedule the next test.
773 }); 728 });
774 break; 729 break;
775 } 730 }
776 _currentTestCaseIndex++; 731 _currentTestCaseIndex++;
777 } 732 }
778 } 733 }
779 734
780 /** Publish results on the page and notify controller. */ 735 /** Publish results on the page and notify controller. */
781 void _completeTests() { 736 void _completeTests() {
782 if (!_initialized) return; 737 if (!_initialized) return;
783 int passed = 0; 738 int passed = 0;
784 int failed = 0; 739 int failed = 0;
785 int errors = 0; 740 int errors = 0;
786 741
787 for (TestCase t in _testCases) { 742 for (TestCase t in _testCases) {
788 switch (t.result) { 743 switch (t.result) {
789 case PASS: passed++; break; 744 case PASS: passed++; break;
790 case FAIL: failed++; break; 745 case FAIL: failed++; break;
791 case ERROR: errors++; break; 746 case ERROR: errors++; break;
792 } 747 }
793 } 748 }
794 _config.onSummary(passed, failed, errors, testCases, _uncaughtErrorMessage); 749 _config.onSummary(passed, failed, errors, testCases, _uncaughtErrorMessage);
795 _config.onDone(passed > 0 && failed == 0 && errors == 0 && 750 _config.onDone(passed > 0 && failed == 0 && errors == 0 &&
796 _uncaughtErrorMessage == null); 751 _uncaughtErrorMessage == null);
797 _initialized = false; 752
753 _currentTestCaseIndex = null;
754 _uncaughtErrorMessage = null;
798 } 755 }
799 756
800 String _fullSpec(String spec) { 757 String _fullSpec(String spec) {
801 if (spec == null) return '$_currentGroup'; 758 if (spec == null) return '$_currentGroup';
802 return _currentGroup != '' ? '$_currentGroup$groupSep$spec' : spec; 759 return _currentGroup != '' ? '$_currentGroup$groupSep$spec' : spec;
803 } 760 }
804 761
805 /** 762 /**
806 * Lazily initializes the test library if not already initialized. 763 * Lazily initializes the test library if not already initialized.
807 */ 764 */
808 void ensureInitialized() { 765 void ensureInitialized() {
809 _ensureInitialized(true); 766 _ensureInitialized(true);
810 } 767 }
811 768
812 void _ensureInitialized(bool configAutoStart) { 769 void _ensureInitialized(bool configAutoStart) {
770 if(_currentTestCaseIndex != null) {
771 throw new StateError("A forbidden operation occured "
Andrei Mouravski 2013/04/06 22:41:53 I feel like this error could be useful at other pl
kevmoo-old 2013/04/06 23:00:40 See latest update.
772 "while tests were running");
773 }
813 if (_initialized) { 774 if (_initialized) {
814 return; 775 return;
815 } 776 }
816 _initialized = true; 777 _initialized = true;
817 // Hook our async guard into the matcher library. 778 // Hook our async guard into the matcher library.
818 wrapAsync = (f, [id]) => expectAsync1(f, id: id); 779 wrapAsync = (f, [id]) => expectAsync1(f, id: id);
819 780
820 _uncaughtErrorMessage = null; 781 _uncaughtErrorMessage = null;
821 782
822 if (_config == null) { 783 if (_config == null) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 } 818 }
858 819
859 /** Enable a test by ID. */ 820 /** Enable a test by ID. */
860 void enableTest(int testId) => _setTestEnabledState(testId, true); 821 void enableTest(int testId) => _setTestEnabledState(testId, true);
861 822
862 /** Disable a test by ID. */ 823 /** Disable a test by ID. */
863 void disableTest(int testId) => _setTestEnabledState(testId, false); 824 void disableTest(int testId) => _setTestEnabledState(testId, false);
864 825
865 /** Signature for a test function. */ 826 /** Signature for a test function. */
866 typedef dynamic TestFunction(); 827 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