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

Side by Side Diff: chrome/test/data/webui/test_api.js

Issue 7576024: Provide ability for WebUIBrowserTests to run asynchronous tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review comments, fixed chrome.send passthrough, fixed assertion tests to use runTestFunction. Created 9 years, 4 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 | « chrome/test/data/webui/async.js ('k') | 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) 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
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
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
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
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 })();
OLDNEW
« no previous file with comments | « chrome/test/data/webui/async.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698