Checking for JavaScript Errors with Selenium
Posted At : June 7, 2010 5:54 PM | Posted By : Bob Silverberg
Related Categories: Selenium, TDD
I've recently been writing some end-to-end tests for ValidateThis, my validation framework for ColdFusion objects, using Selenium. One of the things I wanted to test were the client-side validations that the framework generates automatically. Selenium makes it very easy to test these, as I can use Selenium's assertText command to locate failure messages that have been generated by the jQuery Validation plugin, using XPath, and check whether the message is what I expected.
I found, however, that I was often getting JavaScript errors when the page first loaded (because I was working on the JS and was introducing errors), so I was looking for a quick way to add an assert to my test to check whether any JS errors occurred. After some Googling I came to the conclusion that there is nothing built into Selenium to support this, but there are a number of hacks that can be used to accomplish it. I'm going to describe one of them here. Let me state again, for the record, that this is pretty hacky. I'd love to hear from others who may have better solutions.
I simply add a script to my page that will catch any JS errors by intercepting the window.onerror event:
2 window.onerror=function(msg){
3 $("body").attr("JSError",msg);
4 }
5</script>
This will cause an attribute called JSError with a value corresponding to the JavaScript error message to be added to the body tag of my document if a JavaScript error occurs. Note that I'm using jQuery to do this, so this specific example won't work if jQuery fails to load. Then, in my Selenium test, I just use the command assertElementNotPresent with a target of //body[@JSError]. Now, if any JavaScript errors occur on the page my test will fail and I'll know I have to address them first. If, for some strange reason, I want to check for a particular JavaScript error, I could use the assertElementPresent command with a target of //body[@JSError='the error message'].
Note that I'm using this with a test fixture page, it's not an actual page that is part of an application. I'm not sure that this would be very useful in an automated testing environment, I'm just using it for some TDDing, where I want to write an end-to-end acceptance test first, and then write my unit tests. Getting the test to fail because of a JavaScript error is a nice way, imo, of satisfying the criteria that I must have a failing test before writing code to make it work. The usefullness of this technique in terms of pure testing is questionable, but I find it useful for my purposes, so I thought I'd put it out there for others.
Does that clear it up, or only make it even more confusing?
From selenium documentation: "Selenium does NOT support JavaScript alerts that are generated in a page's onload() event handler. In this case a visible dialog WILL be generated and Selenium will hang until someone manually clicks OK."
We get around this (and detect other javaScript errors) by leveraging another tool called from our selenium code: AutoIt. Detailed in this blog post: http://aptdeveloper.blogspot.com/2009/11/selenium-...
This is the tweak we did at my work in order to chain up the errors into the body attribute and then in selenium with the get_attribute method
get all of them.
<script type="text/javascript">
window.onerror=function(msg){
var previous_errors = document.getElementsByTagName("body")[0].getAttribute("JSError");
$("body").attr("JSError",previous_errors + '\n' + msg );
}
</script>
Great approach but since we are adding an attribute to the body tag here therefore it could make the page as an invalid XHTML. Or the doctype must have this attribute defined in it. Way around for this would be to store the error in an input hidden variable and check the value of this variable. OR specify to use the above mentioned code only while running selenium tests (dunno how to do it).
I didn't get where to add this code. In my selenium RC script(Java) or in the main source code of the page. Please tell me