YUI Test waitFor function
If you've used selenium, you know that you can wait for a condition to be true before resuming the test. It would typically look like this.
-
clickButton("id='submit'");
-
-
waitForSuccessMessage();
-
-
assertSomething();
Though when I went and implemented the JavaScript testing framework for Salesforce.com, I was dismayed to see this type of functionality missing. Instead all you got whats a pre-defined wait interval. Besides the additional time this takes for your test to run, it really leads to flappiness.
Flappiness being an internal term indicating a test that fails randomly. These being the worst type of test failures ever. Did the environment have a problem? Did another test not clean up after its self? With a predefined wait based on time, its most likely that your action just didn't happen in time this one instance.
So being able to wait for a condition to be true would be really nice. Here's the function I wrote internally.
-
// We have some wrapping logic which makes this sensible,
-
// though we really should attach to the prototype at some point.
-
var testCase = new Y.Test.Case(config);
-
testCase.waitFor = function(waitTest, resumeFunction, timeout, msg) {
-
// Run the test every 20ms's till the timeout has been hit.
-
var test = this;
-
var flag = false;
-
var timeoutId = null;
-
// See if we should resume after 20ms
-
timeoutId = setTimeout(testWait, 20);
-
this.wait(function() {
-
Y.Test.Assert.fail(msg || "Should not have hit the full wait timeout.");
-
}, timeout);
-
// What happens if the wait fires and then testWait fires?
-
function testWait() {
-
if (waitTest.call(test)) {
-
clearTimeout(timeoutId);
-
return test.resume(resumeFunction);
-
}
-
// Try again here in a sec.
-
timeoutId = setTimeout(testWait, 20);
-
}
-
};
And for an example of how to use it, here's the test case I wrote for it.
-
// Sfdc.Test.Case is a wrapper for the YUI test case.
-
// We did that to ensure we weren't married to the YUI API.
-
var tests = new Sfdc.Test.Case({
-
name: "JSTest Tests",
-
-
testWaitFor: function() {
-
var testFlag = false;
-
-
// In one second the testFlag should be set to true
-
setTimeout(function(){ testFlag = true; }, 200);
-
-
function resumeFunction() {
-
Sfdc.Test.Assert.isTrue(testFlag, "The test flag should have been set to true after 200ms.");
-
}
-
-
function waitForCondition() {
-
return testFlag === true;
-
}
-
-
this.waitFor(waitForCondition, resumeFunction, 3000, "Shouldn't have waited the full timeout.");
-
-
}
-
});
As always comments and thoughts welcome.
No comments
Leave a Reply