📄 testharness.js
字号:
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Permissive License.
// See http://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx.
// All other rights reserved.
// The TestHarness contains the implementation that populates the list of Test
// Suites, runs the selected Test Suites, and displays the results of the Test
// Pass. We also define the following terms to share a common vocabulary:
// - Test Harness: testing archictures that performs the Test Pass
// - Test Pass: running selected Test Suites and displaying the results
// - Test Suite: *.aspx page containing a RegisterTests method in JavaScript
// that defines one or more Test Cases
// - Test Case: An individual unit test composed of one or more Test Steps
// - Test Step: An atomic action peformed (possibly asynchronously) as part of
// a Test Case
function TestHarness() {
// Constant values
var constants = {
// Initial delay (ms) to wait before running a Test Suite
'InitialDelay' : 50,
// Interval (ms) to wait before checking Test Case completion
'PollingInterval' : 250,
// Heading BackColor for successful Test Suites
'SuccessBackColor' : '#B0FFB0',
// Message ForeColor for successful Test Cases
'SuccessForeColor' : 'green',
// Heading BackColor for failing Test Suites
'FailureBackColor' : '#EFC4C1',
// Message ForeColor for failing Test Cases
'FailureForeColor' : 'red',
// Heading BackColor for unknown Test Suites
'UnknownBackColor' : '#F0F0F0',
// Message ForeColor for unknown Test Cases
'UnknownForeColor' : '#000000'
};
this.Constants = constants;
//
var testInterface = null;
// References to controls in the page
var wndTest = null; // iframe used to load the test suites
var frameTest = null; // iframe used to load the test suites
var btnRun = null; // button that executes the selected tests
var availableTests = null; // div containing the list of all tests
// Note: The variable "testSuiteUrls" is declared in the TestHarness.aspx
// page and is an array populated by the server with the list of test
// suites
// The selectedTestSuitesUrls list and currentTestSuiteUrl variable track
// the remaining test suites the user requested to run as well as the suite
// currently executing. These variables reference the urls of the suites.
var selectedTestSuiteUrls = [];
var currentTestSuiteUrl = null;
// The testCases list and currentTestCase variable track the remaining Test
// Cases to be executed in the current Test Suite. They contain instances
// of the TestCase object and are populated via the Test Suite's
// RegisterTests function.
var testCases = [];
var currentTestCase = -1;
var registeredFunctions = [];
var resumeFunctionRegistrationID = -1;
var waitIntervalID = null;
// Flag and CheckBox determining if we're in debug mode. Debug mode will not
// automatically catch exceptions so that they can easily be caught by your
// debugger of choice.
var debug = false;
var chkDebug = null;
// Called via window.onload of TestHarness.aspx, the initialize method is
// responsible for getting references to all the controls, creating the
// list of tests we can run, and focusing the "Run Tests" button.
this.initialize = function() {
// Get references to the controls on the page
wndTest = window.document.getElementById('wndTest');
if (!wndTest) {
throw "Could not find iframe 'wndTest' on page!";
}
btnRun = window.document.getElementById('btnRun');
if (!btnRun) {
throw "Could not find button 'btnRun' on page!";
}
availableTests = window.document.getElementById('availableTests');
if (!availableTests) {
throw "Could not find div 'availableTests' on page!";
}
chkDebug = window.document.getElementById('chkDebug');
if (!chkDebug) {
throw "Could not find input 'chkDebug' on page!";
}
// Setup the test interface
testInterface = new TestInterface();
testInterface.initialize(this);
// Get a reference to the frame via window.frames because we need them
// both (the DOM method allows us to use the src property, which Safari
// requires for relocation, but the window.frames method provides us
// access to the script objects in that frame which we need to work
// anywhere). We can't just use window.frames['wndTest'] because it
// doesn't work on Mozilla.
for (var i = 0; i < window.frames.length; i++) {
if (window.frames[i].location.href == wndTest.src) {
frameTest = window.frames[i];
break;
}
}
if (!frameTest) {
throw "Count not find corresponding frame for 'wndTest' on page!";
}
// Automatically build the list of available test suites given the
// list provided in testSuiteUrls
for (var i = 0; i < testSuiteUrls.length; i++) {
var div = window.document.createElement('div');
div.id = 'testSuiteList_' + i;
availableTests.appendChild(div);
var checkbox = window.document.createElement('input');
checkbox.type = 'checkbox';
checkbox.id = 'testSuiteList_' + i + '_check';
div.appendChild(checkbox);
checkbox.checked = window.runAll;
var label = window.document.createElement('label');
label.id = 'testSuiteList_' + i + '_label';
label.innerHTML = testSuiteUrls[i].replace('.aspx', '');
label.htmlFor = checkbox.id;
div.appendChild(label);
}
// Focus the "Run Tests" button by default
btnRun.focus();
// Cascade the debug flag if it was set in the querystring
chkDebug.checked = window.debug;
// Automatically run all the tests if querystring parameter was set
if (window.runAll)
this.runTests();
}
// selectAllTests either selects or deselects all of the tests in the
// list of availableTests to make it quicker to do a full Test Pass
this.selectAllTests = function(selected) {
for (var i = 0; i < testSuiteUrls.length; i++) {
var checkbox = window.document.getElementById(
'testSuiteList_' + i + '_check');
checkbox.checked = selected;
}
return false;
}
// The runTests function starts the Test Pass over the currently selected
// list of Test Suites
this.runTests = function() {
// Determine if we're in debug mode
debug = chkDebug.checked;
// Determine which Test Suites were selected
selectedTestSuiteUrls = [];
for (var i = 0; i < testSuiteUrls.length; i++) {
var checkbox = window.document.getElementById(
'testSuiteList_' + i + '_check');
if (checkbox.checked) {
selectedTestSuiteUrls.push(testSuiteUrls[i] + "?t=" + (new Date()).getTime());
}
}
// Prevent the user from running any more tests until we finish
// with the test pass
btnRun.disabled = true;
// Show the test window (it is initially visible to make it work in
// Safari, but from the first run and after it will be hidden on
// completion of the test pass to provide the a better view of the
// results)
// TODO: Special case Safari so it starts hidden by default
wndTest.style.display = 'block';
// Reset all of the reporting mechanisms for the test pass and then
// start running the first Test Suite
testInterface.startTestPass();
// Start running the first test suite
runNextTestSuite();
}
// Pulls the next Test Suite from the remaining list of selected Test
// Suites and loads it into the test window (which causes it to start
// executing)
function runNextTestSuite() {
if (selectedTestSuiteUrls.length > 0) {
// Get the next Test Suite
currentTestSuiteUrl = selectedTestSuiteUrls.shift();
wndTest.src = currentTestSuiteUrl;
} else {
// Finish the report after we iterate through all Test Suites
testInterface.finishTestPass();
// Hide the test window to provide a better view of the test
// results
currentTestSuiteUrl = null;
wndTest.src = 'about:blank';
wndTest.style.display = 'none';
// Allow the user to run tests again
btnRun.disabled = false;
btnRun.focus();
}
}
// Create a new Test Case and add it to the list of remaining Test Cases
this.addTest = function(testName) {
var test = new TestCase();
test.initialize(testName, this);
testCases.push(test);
return test;
}
this.registerTestFunction = function(func) {
func.registrationID = registeredFunctions.length;
registeredFunctions.push(func);
}
this.registerOnResumeFunction = function(func) {
resumeFunctionRegistrationID = func.registrationID;
}
function reloadTestWindow() {
wndTest.src = currentTestSuiteUrl;
}
// Determine all the necessary types have been loaded before processing the tests
function isLoaded() {
// Get the frame containing variable definitions in the child window
var frame = getFrame();
if (!frame) return false;
// Check if the ASP.NET AJAX Runtime loaded (Sys.Application is the very last type defined)
if (!frame.Sys || !frame.Sys.Application || !frame.Sys.Application.get_isInitialized()) {
return false;
}
// Check the custom dependencies from the Test Suite
var dependencies = frame.typeDependencies;
if (dependencies) {
for (var i = 0; i < dependencies.length; i++) {
// Start by looking for objects in the child window
var parent = frame;
// Split the dependency into namespaces and member name to look up
// (for example 'Sys.Application' -> ['Sys', 'Application']
var names = dependencies[i].split(/\./);
for (var j = 0; j < names.length; j++)
{
// If the parent object (note that ASP.NET AJAX namespaces are objects)
// has a property with the name we want, then continue with it next
if (parent[names[j]]) {
parent = parent[names[j]];
} else {
return false;
}
}
}
}
// If everything was loaded, then we are ready to proceed with the tests
return true;
}
// Expose whether or not we're in debug mode (which will cause exceptions to surface so that
// you can attach a debugger)
function getDebugMode() {
return debug;
}
this.getDebugMode = getDebugMode;
// Initialize a Test Suite and start executing its Test Cases (this is
// called via the wndTest.onload handler after a short delay to allow
// ASP.NET AJAX and control scripts to have loaded)
this.initializeTestSuite = function() {
// Ensure we have a Test Suite (as this function fires the first time
// the page is loaded, even though no tests have been run yet)
if (!currentTestSuiteUrl)
return;
if (waitIntervalID) {
window.clearInterval(waitIntervalID);
waitIntervalID = null;
}
// Wait unti everything has loaded before starting the tests
if (!isLoaded()) {
window.setTimeout(arguments.callee, constants.InitialDelay);
return;
}
if (resumeFunctionRegistrationID == -1 && currentTestCase == -1) {
testInterface.startTestSuite(currentTestSuiteUrl);
}
testCases = [];
registeredFunctions = [];
// Get the frame that has access to the JavaScript declarations
// (note that to get Safari working, you need to check wndTest first)
var frame = getFrame();
// Register the Test Cases of this Test Suite
if (frame)
{
// Register the tests and start running the first
// TestCase in the list that we generate
if (!getDebugMode()) {
try {
frame.registerTests(testHarness);
} catch (ex) {
fail('registerTests failure: ' + ex);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -