OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview Library providing basic test framework functionality. | 6 * @fileoverview Library providing basic test framework functionality. |
7 **/ | 7 **/ |
8 | 8 |
9 /** | 9 /** |
10 * Namespace for |Test|. | 10 * Namespace for |Test|. |
11 * @type {Object} | 11 * @type {Object} |
12 **/ | 12 **/ |
13 var testing = {}; | 13 var testing = {}; |
14 | 14 |
15 /** | 15 /** |
16 * Hold the currentTestCase across between PreLoad and Run. | 16 * Hold the currentTestCase across between PreLoad and Run. |
17 * @type {TestCase} | 17 * @type {TestCase} |
18 **/ | 18 **/ |
19 var currentTestCase = null; | 19 var currentTestCase = null; |
20 | 20 |
| 21 /** |
| 22 * @type {?string} The string representation of the currently running test |
| 23 * function. |
| 24 */ |
| 25 var currentTestFunction = null; |
| 26 |
| 27 /** |
| 28 * @type {?Array} The arguments of the currently running test. |
| 29 */ |
| 30 var currentTestArguments = null; |
| 31 |
21 (function() { | 32 (function() { |
22 // Provide global objects for generation case. | 33 // Provide global objects for generation case. |
23 if (this['window'] === undefined) | 34 if (this['window'] === undefined) |
24 this['window'] = this; | 35 this['window'] = this; |
25 if (this['chrome'] === undefined) { | 36 if (this['chrome'] === undefined) { |
26 this['chrome'] = { | 37 this['chrome'] = { |
27 send: function() {}, | 38 send: function() {}, |
28 }; | 39 }; |
29 } | 40 } |
30 if (this['console'] === undefined) { | 41 if (this['console'] === undefined) { |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 } | 211 } |
201 } | 212 } |
202 | 213 |
203 /** | 214 /** |
204 * Overrides {@code chrome.send} for routing messages to javascript | 215 * Overrides {@code chrome.send} for routing messages to javascript |
205 * functions. Also fallsback to sending with the original chrome object. | 216 * functions. Also fallsback to sending with the original chrome object. |
206 * @param {string} messageName The message to route. | 217 * @param {string} messageName The message to route. |
207 **/ | 218 **/ |
208 function send(messageName) { | 219 function send(messageName) { |
209 var callback = sendCallbacks[messageName]; | 220 var callback = sendCallbacks[messageName]; |
210 var args = Array.prototype.slice.call(arguments, 1); | |
211 if (callback != undefined) | 221 if (callback != undefined) |
212 callback[1].apply(callback[0], args); | 222 callback[1].apply(callback[0], Array.prototype.slice.call(arguments, 1)); |
213 else | 223 else |
214 this.__proto__.send.apply(this.__proto__, args); | 224 this.__proto__.send.apply(this.__proto__, arguments); |
215 } | 225 } |
216 | 226 |
217 /** | 227 /** |
218 * Provides a mechanism for assert* and expect* methods to fetch the signature | 228 * Provides a mechanism for assert* and expect* methods to fetch the signature |
219 * of their caller. Assert* methods should |registerCall| and expect* methods | 229 * of their caller. Assert* methods should |registerCall| and expect* methods |
220 * should set |isExpect| and |expectName| properties to indicate that the | 230 * should set |isExpect| and |expectName| properties to indicate that the |
221 * interesting caller is one more level up the stack. | 231 * interesting caller is one more level up the stack. |
222 **/ | 232 **/ |
223 function CallHelper() { | 233 function CallHelper() { |
224 this.__proto__ = CallHelper.prototype; | 234 this.__proto__ = CallHelper.prototype; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 return callMessage; | 312 return callMessage; |
303 }, | 313 }, |
304 }; | 314 }; |
305 | 315 |
306 /** | 316 /** |
307 * Help register calls for better error reporting. | 317 * Help register calls for better error reporting. |
308 * @type {CallHelper} | 318 * @type {CallHelper} |
309 **/ | 319 **/ |
310 var helper = new CallHelper(); | 320 var helper = new CallHelper(); |
311 | 321 |
| 322 /** |
| 323 * true when testDone has been called. |
| 324 * @type {boolean} |
| 325 */ |
| 326 var testIsDone = false; |
| 327 |
| 328 /** |
| 329 * Holds the errors, if any, caught by expects so that the test case can |
| 330 * fail. Cleared when results are reported from runTest() or testDone(). |
| 331 * @type {Array.<Error>} |
| 332 **/ |
| 333 var errors = []; |
| 334 |
| 335 /** |
| 336 * Resets test state by clearing |errors| and |testIsDone| flags. |
| 337 **/ |
| 338 function resetTestState() { |
| 339 errors.splice(0, errors.length); |
| 340 testIsDone = false; |
| 341 } |
| 342 |
| 343 /** |
| 344 * Notifies the running browser test of the test results. Clears |errors|. |
| 345 * @param {Array.<boolean, string>=} result When passed, this is used for the |
| 346 * testResult message. |
| 347 **/ |
| 348 function testDone(result) { |
| 349 if (!testIsDone) { |
| 350 testIsDone = true; |
| 351 chrome.send('testResult', result ? result : testResult()); |
| 352 errors.splice(0, errors.length); |
| 353 } else { |
| 354 console.warn('testIsDone already'); |
| 355 } |
| 356 } |
| 357 |
| 358 /** |
| 359 * Returns [success, message] & clears |errors|. |
| 360 * @return {Array.<boolean, string>} |
| 361 **/ |
| 362 function testResult() { |
| 363 var result = [true, '']; |
| 364 if (errors.length) { |
| 365 var message = ''; |
| 366 for (var i = 0; i < errors.length; ++i) { |
| 367 message += 'Failed: ' + currentTestFunction + '(' + |
| 368 currentTestArguments.map(JSON.stringify) + |
| 369 ')\n' + errors[i].stack; |
| 370 } |
| 371 result = [false, message]; |
| 372 } |
| 373 return result; |
| 374 } |
| 375 |
312 // Asserts. | 376 // Asserts. |
313 // Use the following assertions to verify a condition within a test. | 377 // Use the following assertions to verify a condition within a test. |
314 // If assertion fails, the C++ backend will be immediately notified. | 378 // If assertion fails, throw an Error with information pertinent to the test. |
315 // If assertion passes, no notification will be sent to the C++ backend. | |
316 | 379 |
317 /** | 380 /** |
318 * When |test| !== true, aborts the current test. | 381 * When |test| !== true, aborts the current test. |
319 * @param {boolean} test The predicate to check against |expected|. | 382 * @param {boolean} test The predicate to check against |expected|. |
320 * @param {string=} message The message to include in the Error thrown. | 383 * @param {string=} message The message to include in the Error thrown. |
321 * @throws {Error} upon failure. | 384 * @throws {Error} upon failure. |
322 **/ | 385 **/ |
323 function assertTrue(test, message) { | 386 function assertTrue(test, message) { |
324 helper.registerCall(); | 387 helper.registerCall(); |
325 if (test !== true) | 388 if (test !== true) |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 * Always aborts the current test. | 501 * Always aborts the current test. |
439 * @param {string=} message The message to include in the Error thrown. | 502 * @param {string=} message The message to include in the Error thrown. |
440 * @throws {Error} always. | 503 * @throws {Error} always. |
441 **/ | 504 **/ |
442 function assertNotReached(message) { | 505 function assertNotReached(message) { |
443 helper.registerCall(); | 506 helper.registerCall(); |
444 throw new Error(helper.getCallMessage(message)); | 507 throw new Error(helper.getCallMessage(message)); |
445 } | 508 } |
446 | 509 |
447 /** | 510 /** |
448 * Holds the errors, if any, caught by expects so that the test case can fail. | |
449 * @type {Array.<Error>} | |
450 **/ | |
451 var errors = []; | |
452 | |
453 /** | |
454 * Creates a function based upon a function that thows an exception on | 511 * Creates a function based upon a function that thows an exception on |
455 * failure. The new function stuffs any errors into the |errors| array for | 512 * failure. The new function stuffs any errors into the |errors| array for |
456 * checking by runTest. This allows tests to continue running other checks, | 513 * checking by runTest. This allows tests to continue running other checks, |
457 * while failing the overal test if any errors occurrred. | 514 * while failing the overall test if any errors occurrred. |
458 * @param {Function} assertFunc The function which may throw an Error. | 515 * @param {Function} assertFunc The function which may throw an Error. |
459 * @return {Function} A function that applies its arguments to |assertFunc|. | 516 * @return {Function} A function that applies its arguments to |assertFunc|. |
460 * @see errors | 517 * @see errors |
461 * @see runTest | 518 * @see runTest |
462 **/ | 519 **/ |
463 function createExpect(assertFunc) { | 520 function createExpect(assertFunc) { |
464 var expectFunc = function() { | 521 var expectFunc = function() { |
465 try { | 522 try { |
466 assertFunc.apply(null, arguments); | 523 assertFunc.apply(null, arguments); |
467 } catch (e) { | 524 } catch (e) { |
468 errors.push(e); | 525 errors.push(e); |
469 } | 526 } |
470 }; | 527 }; |
471 expectFunc.isExpect = true; | 528 expectFunc.isExpect = true; |
472 expectFunc.expectName = assertFunc.name.replace(/^assert/, 'expect'); | 529 expectFunc.expectName = assertFunc.name.replace(/^assert/, 'expect'); |
473 return expectFunc; | 530 return expectFunc; |
474 } | 531 } |
475 | 532 |
476 /** | 533 /** |
477 * This is the starting point for tests run by WebUIBrowserTest. If an error | 534 * This is the starting point for tests run by WebUIBrowserTest. If an error |
478 * occurs, it reports a failure and a message created by joining individual | 535 * occurs, it reports a failure and a message created by joining individual |
479 * error messages. | 536 * error messages. This supports sync tests and async tests by calling |
| 537 * testDone() when |isAsync| is not true, relying on async tests to call |
| 538 * testDone() when they complete. |
| 539 * @param {boolean} isAsync When false, call testDone() with the test result. |
480 * @param {string} testFunction The function name to call. | 540 * @param {string} testFunction The function name to call. |
481 * @param {Array} testArguments The arguments to call |testFunction| with. | 541 * @param {Array} testArguments The arguments to call |testFunction| with. |
482 * @return {Array.<boolean, string>} [test-succeeded, message-if-failed] | 542 * @return {boolean} true always to signal successful execution (but not |
| 543 * necessarily successful results) of this test. |
483 * @see errors | 544 * @see errors |
484 * @see runTestFunction | 545 * @see runTestFunction |
485 **/ | 546 **/ |
486 function runTest(testFunction, testArguments) { | 547 function runTest(isAsync, testFunction, testArguments) { |
487 // Avoid eval() if at all possible, since it will not work on pages | 548 // Avoid eval() if at all possible, since it will not work on pages |
488 // that have enabled content-security-policy. | 549 // that have enabled content-security-policy. |
489 var testBody = this[testFunction]; // global object -- not a method. | 550 var testBody = this[testFunction]; // global object -- not a method. |
490 if (typeof testBody === "undefined") | 551 var testName = testFunction; |
| 552 if (typeof testBody === "undefined") { |
491 testBody = eval(testFunction); | 553 testBody = eval(testFunction); |
| 554 testName = testBody.toString(); |
| 555 } |
492 if (testBody != RUN_TEST_F) { | 556 if (testBody != RUN_TEST_F) { |
493 var testName = | |
494 testFunction.name ? testFunction.name : testBody.toString(); | |
495 console.log('Running test ' + testName); | 557 console.log('Running test ' + testName); |
496 } | 558 } |
497 return runTestFunction(testFunction, testBody, testArguments); | 559 var result = runTestFunction(testFunction, testBody, testArguments); |
| 560 if (!isAsync) |
| 561 testDone(result); |
| 562 return true; |
498 } | 563 } |
499 | 564 |
500 /** | 565 /** |
501 * This is the guts of WebUIBrowserTest. It clears |errors|, runs the | 566 * This is the guts of WebUIBrowserTest. It runs the test surrounded by an |
502 * test surrounded by an expect to catch Errors. If |errors| is | 567 * expect to catch Errors. If |errors| is non-empty, it reports a failure and |
503 * non-empty, it reports a failure and a message by joining |errors|. | 568 * a message by joining |errors|. Consumers can use this to use assert/expect |
504 * Consumers can use this to use assert/expect functions asynchronously, | 569 * functions asynchronously, but are then responsible for reporting errors to |
505 * but are then responsible for reporting errors to the browser themselves. | 570 * the browser themselves through testDone(). |
506 * @param {string} testFunction The function name to report on failure. | 571 * @param {string} testFunction The function name to report on failure. |
507 * @param {Function} testBody The function to call. | 572 * @param {Function} testBody The function to call. |
508 * @param {Array} testArguments The arguments to call |testBody| with. | 573 * @param {Array} testArguments The arguments to call |testBody| with. |
509 * @return {Array.<boolean, string>} [test-succeeded, message-if-failed] | 574 * @return {Array.<boolean, string>} [test-succeeded, message-if-failed] |
510 * @see errors | |
511 * @see createExpect | 575 * @see createExpect |
| 576 * @see testDone |
512 **/ | 577 **/ |
513 function runTestFunction(testFunction, testBody, testArguments) { | 578 function runTestFunction(testFunction, testBody, testArguments) { |
514 errors.splice(0, errors.length); | 579 currentTestFunction = testFunction; |
| 580 currentTestArguments = testArguments; |
515 createExpect(testBody).apply(null, testArguments); | 581 createExpect(testBody).apply(null, testArguments); |
516 | 582 return testResult(); |
517 var result = [true]; | |
518 if (errors.length) { | |
519 var message = ''; | |
520 for (var i = 0; i < errors.length; ++i) { | |
521 message += 'Failed: ' + testFunction + '(' + | |
522 testArguments.map(JSON.stringify) + | |
523 ')\n' + errors[i].stack; | |
524 } | |
525 errors.splice(0, errors.length); | |
526 result = [false, message]; | |
527 } | |
528 return result; | |
529 } | 583 } |
530 | 584 |
531 /** | 585 /** |
532 * Creates a new test case for the given |testFixture| and |testName|. Assumes | 586 * Creates a new test case for the given |testFixture| and |testName|. Assumes |
533 * |testFixture| describes a globally available subclass of type Test. | 587 * |testFixture| describes a globally available subclass of type Test. |
534 * @param {string} testFixture The fixture for this test case. | 588 * @param {string} testFixture The fixture for this test case. |
535 * @param {string} testName The name for this test case. | 589 * @param {string} testName The name for this test case. |
536 * @return {TestCase} A newly created TestCase. | 590 * @return {TestCase} A newly created TestCase. |
537 **/ | 591 **/ |
538 function createTestCase(testFixture, testName) { | 592 function createTestCase(testFixture, testName) { |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
703 * @return {string} description of the matcher for this argument. | 757 * @return {string} description of the matcher for this argument. |
704 **/ | 758 **/ |
705 describe: function() { | 759 describe: function() { |
706 return 'SaveArguments(' + | 760 return 'SaveArguments(' + |
707 this.realMatcher_.describe.call(this.realMatcher_) + ')'; | 761 this.realMatcher_.describe.call(this.realMatcher_) + ')'; |
708 }, | 762 }, |
709 }; | 763 }; |
710 | 764 |
711 // Exports. | 765 // Exports. |
712 testing.Test = Test; | 766 testing.Test = Test; |
| 767 window.testDone = testDone; |
713 window.assertTrue = assertTrue; | 768 window.assertTrue = assertTrue; |
714 window.assertFalse = assertFalse; | 769 window.assertFalse = assertFalse; |
715 window.assertGE = assertGE; | 770 window.assertGE = assertGE; |
716 window.assertGT = assertGT; | 771 window.assertGT = assertGT; |
717 window.assertEquals = assertEquals; | 772 window.assertEquals = assertEquals; |
718 window.assertLE = assertLE; | 773 window.assertLE = assertLE; |
719 window.assertLT = assertLT; | 774 window.assertLT = assertLT; |
720 window.assertNotEquals = assertNotEquals; | 775 window.assertNotEquals = assertNotEquals; |
721 window.assertNotReached = assertNotReached; | 776 window.assertNotReached = assertNotReached; |
722 window.callFunction = callFunction; | 777 window.callFunction = callFunction; |
723 window.expectTrue = createExpect(assertTrue); | 778 window.expectTrue = createExpect(assertTrue); |
724 window.expectFalse = createExpect(assertFalse); | 779 window.expectFalse = createExpect(assertFalse); |
725 window.expectGE = createExpect(assertGE); | 780 window.expectGE = createExpect(assertGE); |
726 window.expectGT = createExpect(assertGT); | 781 window.expectGT = createExpect(assertGT); |
727 window.expectEquals = createExpect(assertEquals); | 782 window.expectEquals = createExpect(assertEquals); |
728 window.expectLE = createExpect(assertLE); | 783 window.expectLE = createExpect(assertLE); |
729 window.expectLT = createExpect(assertLT); | 784 window.expectLT = createExpect(assertLT); |
730 window.expectNotEquals = createExpect(assertNotEquals); | 785 window.expectNotEquals = createExpect(assertNotEquals); |
731 window.expectNotReached = createExpect(assertNotReached); | 786 window.expectNotReached = createExpect(assertNotReached); |
732 window.preloadJavascriptLibraries = preloadJavascriptLibraries; | 787 window.preloadJavascriptLibraries = preloadJavascriptLibraries; |
733 window.registerMessageCallback = registerMessageCallback; | 788 window.registerMessageCallback = registerMessageCallback; |
734 window.registerMockMessageCallbacks = registerMockMessageCallbacks; | 789 window.registerMockMessageCallbacks = registerMockMessageCallbacks; |
| 790 window.resetTestState = resetTestState; |
735 window.runTest = runTest; | 791 window.runTest = runTest; |
736 window.runTestFunction = runTestFunction; | 792 window.runTestFunction = runTestFunction; |
737 window.SaveArgumentsMatcher = SaveArgumentsMatcher; | 793 window.SaveArgumentsMatcher = SaveArgumentsMatcher; |
738 window.TEST = TEST; | 794 window.TEST = TEST; |
739 window.TEST_F = TEST_F; | 795 window.TEST_F = TEST_F; |
740 window.GEN = GEN; | 796 window.GEN = GEN; |
741 | 797 |
742 // Import the Mock4JS helpers. | 798 // Import the Mock4JS helpers. |
743 Mock4JS.addMockSupport(window); | 799 Mock4JS.addMockSupport(window); |
744 })(); | 800 })(); |
OLD | NEW |