Thursday, October 9, 2008

Using ajax transaction counts in selenium tests

Sometimes your "only hope" in making a selenium web test stable is to keep track of the number of ajax requests that have happened on the client side.

An example of this is the ajax request that normally returns exactly the same html as was present in the dom before the request. Although this may sound stupid, there are legitimate situations for this.

My test would look like this:

int transactionNumer = selenium.getCurrentAjaxTransactionNumber();
selenium.clickLink("SomeLink");
selenium.waitForAjaxTransactionNumberChange(transactionNumer);
-- rest of test ---


This test is free from timing issues, because it will not proceed to the rest of the test before the ajax request is completed.


public int getCurentAjaxTransactionNumber() {
String eval = selenium.getEval("window.ajaxRequestNumber");
return Integer.parseInt( eval);
}





In my ajax.js file, which wraps prototype, I will typically include two lines like this:

window.ajaxRequestNumber = 0;


Now you will have to find a way to patch into your ajax framework to update this value. For prototype, this would work:


Ajax.Responders.register({
onComplete: function() {
window.ajaxRequestNumber++;
}
});


Now you can track request numbers, and yes - they start with value 0 on page load.

Wednesday, June 11, 2008

Detecting javascript errors with selenium

I've only found out how to do this by including a few javascript functions that get included in the code. I have made no attempt to remove this from production code:


window.onerror = function(){
if (sessionStorage){ // Mozilla only
var cnt;
if (sessionStorage.errcnt){
cnt = parseInt(sessionStorage.errcnt);
} else {
cnt = 0;
}
cnt++;
sessionStorage.errcnt = cnt;
}
return false;
}

function hadJavaScriptError(){
if (sessionStorage){ // Mozilla only
if (sessionStorage.errcnt){
delete sessionStorage.errcnt;
return true;
}
}
return false;
}
Somewhere in your selenium test you can put this check:
String hadJserror = getSelenium().getEval("window.hadJavaScriptError()");
assertFalse("Page had a javascript error, this error has occured somewhere during the test.", Boolean.parseBoolean(hadJserror));


I've put this straight after a common waitForPageToLoad function that we are using, please note that if you do so, it must be after the call to waitForPageToLoad.

Note that the javascript code uses mozilla session store (and probably IE8) to actually keep a persistent count of javascript errors. I'm sure some "userData" for IE could be used for older IE versions