Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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(); |
| OLD | NEW |