Moving With Automation

HOW TO CAPTURE JAVASCRIPT ERRORS FROM YOUR WEB APPLICATION

Tags: selenium javascript

This article is also available here

Recently, in one of my projects I was asked to come up with an automated way to capture all the JavaScript exceptions from the browser for one of our Web Applications. It is a known fact that most of the modern web applications in use today involve an extensive use of JavaScript for the client side processing which makes it all the more important to capture all JavaScript exceptions and consider each Java Script exception as a bug that needs to be fixed, irrespective of whether it is currently affecting the website functionality or the user experience.

There are many browser based tools which developers rely on to find and debug JavaScript errors like Chrome’s DevTool, Firebug , IE Developer toolbar etc. but still there exists a need of automated logging of these errors to a centralized server. To meet this requirement there are few paid solutions available today like (errorception, jslogger and muscular) which requires inserting a script tag on every web page and then it will start recording all the Java Script errors and also log them to a centralized location in real-time.

Till now we have addressed this problem from a developer’s perspective but being a tester I would also like to discuss few approaches to capture these JavaScript errors in automated tests using Selenium WebDriver. Webdriver does not support this feature and it is an issue open since 2009 and well documented on their Google group. Different people have come up with different approaches to tackle this problem and I would like to discuss each approach one by one.

APPROACH 1: INJECTING A SCRIPT ON EACH PAGE TO CATCH ALL UNDETECTED JAVASCRIPT ERRORS.

First we need to add a script like the following on every page

Now these errors can be extracted from your Webdriver code like this:

((JavascriptExecutor) driver).executeScript("return window.javascript_errors ");

I believe this approach is good but there are still a few drawbacks worth mentioning here. First, the JavaScript error won’t necessarily occur in the currently active window so we need to go through all the iFrames and windows to check the errors. Second problem is that it is not easy to convince your developers and management team to add this extra script in your webpages to make it testable. To overcome the second issue we can use a proxy like Browsermob or Fiddler Core to make sure our script gets injected in to the page on time to catch the onload event.

APPROACH 2: USING A FIREFOX EXTENSION TO CAPTURE THE ERRORS.

You can create your own Firefox extension as Firefox allows extensions to get notified of JavaScript errors, no matter where they occur, then you can extract these errors from your Webdriver code. Marc Guillemot has created a similar extension and more details can be found on here.

Here is the simple Java example to use this extension to extract the errors.

    FirefoxProfile ffProfile = new FirefoxProfile();
    JavaScriptError.addExtension(ffProfile);
    final WebDriver driver = new FirefoxDriver(ffProfile);
 
    driver.get("http://somesite");
 
    final List jsErrors = JavaScriptError.readErrors(driver);
    assertTrue(jsErrors.toString(), jsErrors.isEmpty());

APPROACH 3: USING CHROMEDRIVER2 (WEBDRIVER FOR CHROME)

In the GTAC 2013, Ken Kania from Google has explained how ChromeDriver2 is different from its previous version as it uses Chrome DevTools API and now it provides access to internals of Web App and we can do things like:

  • Query and manipulate DOM tree
  • Debug JavaScript and extracting JavaScript errors
  • Memory and Performance Profiling
  • Network Traffic Monitoring

Detailed slides of this presentation can be found here.

I would like to recommend this approach as it is very simple, robust and does not require any tweaking or workaround like the earlier approaches. Here I am posting the Java code to extract the JavaScript errors using ChromeDriver2

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
 
public class JSErrorsLogging {
private WebDriver driver;
    @BeforeMethod
    public void setUp() {
        System.setProperty("webdriver.chrome.driver", "{path to your chromedriver.exe}");        
        DesiredCapabilities capabilities = DesiredCapabilities.chrome();
        LoggingPreferences loggingprefs = new LoggingPreferences();
        loggingprefs.enable(LogType.BROWSER, Level.ALL);
        capabilities.setCapability(CapabilityType.LOGGING_PREFS, loggingprefs);
        driver = new ChromeDriver(capabilities);
    }
 
    @AfterMethod
    public void tearDown() {
        driver.quit();
    }
    public void ExtractJSLogs() {
        LogEntries logEntries = driver.manage().logs().get(LogType.BROWSER);
        for (LogEntry entry : logEntries) {
            System.out.println(new Date(entry.getTimestamp()) + " " + entry.getLevel() + " " + entry.getMessage());
        }
    }
    @Test
    public void testMethod() {
        driver.get("http://yourwebsite.com");
        ExtractJSLogs();
    }
}

This approach can only be used in those languages where the Logger interface has been implemented for WebDriver. We cannot use C# for this approach as according to this link, Logger interface is not yet implemented in C#.

I hope what I have shared with you through this blog will help you address the issue of how to capture JavaScript errors from your web application(s). Please do leave your comments in the box below.

comments powered by Disqus