Wednesday, February 22, 2012

Getting Console Errors From the Browser

So being able to grab Console errors out of the browser has long been a feature I wanted to add into our selenium framework.  Thanks to the help of a couple devs, I've finally worked out a nice way to grab console messages.  Basically the functionality works as follows:


First we override the Console object with some custom functionality every time the page loads.  We injected this into our Page Object base class, that all pages inherit from. This causes it to be called every time the page changes.  After we perform some actions on the page we check our object to see if any console messages have been seen.


There are several ways to do this, but we wanted to be able to differentiate between errors, warnings, logs, and uncaught exceptions.  This code will create the following variables on the page you can grab:

window.console.errorsJson (Errors)
window.console.warnsJson (Warnings)
window.errorsJson (Uncaught Exceptions)
window.console.logsJson (Logs)

First we need to override the console.  This is our magic function that performs all the work on the page.  The beauty of this function is that you can keep calling it multiple times and it won't delete the previous data.  
                string function = "var win = this.browserbot.getUserWindow();win.errors = win.errors || [];win.errorsJson = win.errorsJson || \"\";win.originalonerror = win.originalonerror || win.onerror ||\"none\";win.onerror = function(errorMsg, url, lineNumber) { win.errors.push({\"errorMsg\": errorMsg || \"\",\"url\": url || \"\",\"lineNumber\": lineNumber || \"\"});if (JSON &&JSON.stringify) win.errorsJson = JSON.stringify(win.errors); if (win.originalonerror != \"none\") win.originalonerror(errorMsg, url, lineNumber);};win.console = {logs: win.console.logs || [],logsJson: win.console.logsJson || \"\",log: function() {win.console.logs.push(arguments);if (JSON && JSON.stringify) win.console.logsJson = JSON.stringify(win.console.logs);},warns: win.console.warns || [],warnsJson: win.console.warnsJson || \"\",warn: function() {win.console.warns.push(arguments); if (JSON && JSON.stringify) win.console.warnsJson = JSON.stringify(win.console.warns);},errors: win.console.errors || [],errorsJson: win.console.errorsJson || \"\",error: function() { win.console.errors.push(arguments);if (JSON && JSON.stringify) win.console.errorsJson = JSON.stringify(win.console.errors);}};";
selenium.GetEval(function);

Now we can get our messages like this:

string errorFunction = "this.browserbot.getUserWindow().console.errorsJson";
string errors = GetEval(errorFunction);
                if(errors!="")
                    TestLog.WriteLine("Console errors found: \r\n" + errors);
       
There you go: Console message logging.  We can of course include other functionality, like throwing an exception if an error occurs, or performing another action.   All we have to do to integrate this into our framework is to perform both actions in our page object base class's constructor, and each page object will automatically call it.  

4 comments:

  1. Hello,

    I didn't get it properly where to add JS(string function) code. In my selenium RC script or in the main source code of the web page(client side). Please clarify little bit more how to use this piece of code.

    Mahadi

    ReplyDelete
  2. I also have the same problem.when I use the script with ie8,it throws seleniumException with 'win.console.logs' 为空或不是对象,and with firefox it throws seleniumException with 'win.console' undefined.I am puzzled in it,can you help me with my problem?

    ReplyDelete
  3. can u make a small video description or blog with snapshot.. that way is always work for understanding the concept easily...

    ReplyDelete
  4. do i have to import some packages for this.. because with my current webdriver packages it throw unidenfy errors.. so if there is any pakage than give there info too..

    ReplyDelete