📄 testharness.js
字号:
'AsyncCheck' : 2,
'PostBack' : 3
};
// Constant values
var constants = {
// Default timeout for checking the results of asynchronous operations
// in AsyncCheck tests
'DefaultTimeout' : 10000,
// Default interval for checking the results of asynchronous operations
// in AsyncCheck tests
'DefaultInterval' : 100,
// Function with an empty body used for overloads of addStep
'DefaultFunction' : function() { }
};
// Reference to the TestHarness that is executing this TestCase so we can
// access the interface as needed
var harness = null;
// Name of the TestCase
var name = null;
// Sequence of steps to be executed for this TestCase. Each of the steps
// is an object with a Type property that indicates step type and
// additional properties, such as Action, pertinent to that type of test.
var steps = [];
// Result of executing the test. The test is considered a success unless a
// failure or cancellation occurs.
var result = this.ResultType.Success;
// The completed flag is used to mark asynchronous tests complete. Since
// executing an asynchronous test will return before the test is actually
// complete, callers should check this flag before querying the results of
// the test or proceeding with the next test.
var completed = false;
var test = null;
// Initialize the TestCase
this.initialize = function(testName, testHarness) {
name = testName;
harness = testHarness;
}
// The isOverload function is a utility to determine whether or not the
// function that called it is a valid overload by matching the list of
// type names passed in as arguments to isOverload.
function isOverload() {
// Get the arguments passed to the function that called us
// and the expected types of those arguments
var args = arguments[0];
var types = arguments;
// Check if the number of arguments provided is the same number
// of arguments desired
if (args.length + 1 != types.length) {
return false;
}
// For each argument, check if its type matches the desired type
for (var i = 0; i < args.length; i++) {
if (typeof(args[i]) != types[i + 1]) {
return false;
}
}
return true;
}
// The addStep function provides the interface for building up the TestCase
// steps one at a time. It is overloaded so that you can specify Sync,
// AsyncWait, and AsyncCheck steps with optional parameters via this single
// method. The overloads are as follows:
//
// - Sync: Perform a simple atomic action
// >> addStep(Action)
// ## Action: atomic action to perform
//
// - Async Wait: Perform a simple atomic action that initiates an
// asynchronous operation, allow a specified wait duration to elapse,
// and then perform an atomic verification action of the asynchronous
// operation
// >> addStep(Action, WaitDuration, Verification)
// >> addStep(Action, WaitDuration)
// ## Action: atomic action to perform
// ## WaitDuration: length of time to wait after the action
// ## Verification: atomic action to perform after the wait duration has
// elapsed
//
// - Async Check: Peform a simple atomic action that initiates an
// asynchronous operation, continue to check if the operation has
// completed at a specified interval, and then perform an atomic
// verification action of the asynchronous operation. There is also a
// specified timeout that prevents the completion check from running
// forever.
// >> addStep(Action, CheckComplete, Interval, Timeout, Verification)
// >> addStep(Action, CheckComplete)
// >> addStep(Action, CheckComplete, Interval)
// >> addStep(Action, CheckComplete, Verification)
// >> addStep(Action, CheckComplete, Interval, Verification)
// >> addStep(Action, CheckComplete, Interval, Timeout)
// ## Action: atomic action to perform
// ## CheckComplete: atomic predicate to determine if the result of the
// action has been obtained
// ## Interval: interval to keep invoking the CheckComplete predicate to
// see if the result has been obtained
// ## Timeout: maximum length of time to keep checking for completion
// before giving up and throwing an error
// ## Verification: atomic action to perform after the completion check
// has returned true
//
// Default values from the constants object are used for overloads with
// optional parameters.
this.addStep = function() {
// Create an object to represent the step
var step = {};
step.Type = null;
// Determine the type of step to create based on the number and type of
// the provided arguments
var a = arguments;
var func = 'function';
var num = 'number';
if (isOverload(arguments, func)) {
// addStep(Action)
step.Type = StepType.Sync;
step.Action = a[0];
} else if (isOverload(arguments, func, num)) {
// addStep(Action, WaitDuration)
step.Type = StepType.AsyncWait;
step.Action = a[0];
step.WaitDuration = a[1];
step.Verification = constants.DefaultFunction;
} else if (isOverload(arguments, func, func)) {
// addStep(Action, CheckComplete)
step.Type = StepType.AsyncCheck;
step.Action = a[0];
step.CheckComplete = a[1];
step.Interval = constants.DefaultInterval;
step.Timeout = constants.DefaultTimeout;
step.Verification = constants.DefaultFunction;
} else if (isOverload(arguments, func, num, func)) {
// addStep(Action, WaitDuration, Verification)
step.Type = StepType.AsyncWait;
step.Action = a[0];
step.WaitDuration = a[1];
step.Verification = a[2];
} else if (isOverload(arguments, func, func, func)) {
// addStep(Action, CheckComplete, Verification)
step.Type = StepType.AsyncCheck;
step.Action = a[0];
step.CheckComplete = a[1];
step.Interval = constants.DefaultInterval;
step.Timeout = constants.DefaultTimeout;
step.Verification = a[2];
} else if (isOverload(arguments, func, func, num)) {
// addStep(Action, CheckComplete, Interval)
step.Type = StepType.AsyncCheck;
step.Action = a[0];
step.CheckComplete = a[1];
step.Interval = a[2];
step.Timeout = constants.DefaultTimeout;
step.Verification = constants.DefaultFunction;
} else if (isOverload(arguments, func, func, num, func)) {
// addStep(Action, CheckComplete, Interval, Verification)
step.Type = StepType.AsyncCheck;
step.Action = a[0];
step.CheckComplete = a[1];
step.Interval = a[2];
step.Timeout = constants.DefaultTimeout;
step.Verification = arguments[3];
} else if (isOverload(arguments, func, func, num, num)) {
// addStep(Action, CheckComplete, Interval, Timeout)
step.Type = StepType.AsyncCheck;
step.Action = a[0];
step.CheckComplete = a[1];
step.Interval = a[2];
step.Timeout = a[3];
step.Verification = constants.DefaultFunction;
} else if (isOverload(arguments, func, func, num, num, func)) {
// addStep(Action, CheckComplete, Interval, Timeout, Verification)
step.Type = StepType.AsyncCheck;
step.Action = a[0];
step.CheckComplete = a[1];
step.Interval = a[2];
step.Timeout = a[3];
step.Verification = a[4];
} else {
var message = 'No matching overload found for addStep(';
for (var i = 0; i < arguments.length; i++) {
message += typeof(arguments[i]);
if (i < arguments.length - 1) {
message += ', ';
}
}
message += ') - step ' + (steps.length + 1) + ' of ' + name;
throw message;
}
// Add the step to the end of the list
steps.push(step);
}
// The addPostBack function creates a step that will be used to force a
// postback and resume the test at the beginning of the next step. It
// optionally takes a reference to an element that will be used to force
// a postback (via an element.click(); function). If no element is
// provided, we then submit the first form in the window.forms array to
// force the postback.
this.addPostBack = function(element) {
// Create the postback step and add it to the end of the list
var step = {};
step.Type = StepType.PostBack;
step.Element = element;
steps.push(step);
}
this.generate = function() {
test = buildTest(steps);
}
// The execute function is used to build the test from the sequence of
// steps and then execute the resulting function.
this.execute = function() {
// Build the test if we haven't already
if (!test) {
this.generate();
}
test();
}
// Report a failure
function fail(message) {
harness.fail('Step ' + currentStep + ': ' + message);
}
function debugInvoke(func) {
return func();
}
function safeInvoke(func) {
try {
return func();
}
catch (ex) {
fail(ex);
return null;
}
}
// The buildTest method is the heart of the TestCase functionality. It is
// used to turn the array of steps into an executable function that
// performs the operations described by the test steps. It builds up the
// test function in reverse order.
//
// TODO: Ensure error handling is comprehensive
function buildTest(steps, last) {
if (!last) {
last = function() { currentStep = steps.length + 1; completed = true; };
harness.registerTestFunction(last);
}
if (steps.length == 0) {
// Write the initialization of the test
return function() {
completed = false;
currentStep = 0;
last();
};
}
var step = steps.pop();
var test = null;
var invoke;
if (!harness.getDebugMode()) {
invoke = safeInvoke;
}
else {
invoke = debugInvoke;
}
switch (step.Type)
{
case StepType.Sync :
// AddStep(Action)
test = function() {
if (!completed) {
harness.registerOnResumeFunction(last);
currentStep = steps.length + 1;
invoke(step.Action);
last();
}
};
break;
case StepType.AsyncWait :
// AddStep(Action, WaitDuration, Verification)
test = function() {
if (!completed) {
harness.registerOnResumeFunction(last);
currentStep = steps.length + 1;
invoke(step.Action);
var f = function() {
if (!completed) {
invoke(step.Verification);
last();
}
};
window.setTimeout(f, step.WaitDuration);
}
};
break;
case StepType.AsyncCheck :
// AddStep(Action, CheckComplete, Interval, Timeout, Verification)
test = function() {
if (!completed) {
harness.registerOnResumeFunction(last);
currentStep = steps.length + 1;
invoke(step.Action);
var remaining = step.Timeout;
var f = function() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -