Browserless JavaScript Testing

As users expect more sophisticated AJAX, animation and event functionality, the amount, and complexity of Javascript code is increasing. Even small sites and RIAs can contain 100′s of lines of Javascript code. With the increase in complexity comes the potential for bugs.  Writing clean code matched with lots of testing is what’s required to keep projects on track.

With unit testing we can test individual units of code to determine if it can be relied on in an application. Unit testing is very common in software development but less common in web development.

To run these units tests outside the browser I use a Javascript interpreter that runs the code and the tests. There are many alternatives out there like Rhino, PhantomJS, SpiderMonkey (the engine behind Firefox) and V8 (the engine behind Chrome). These engines are great because they allow you to run Javascript code on the server or command-line but they do not have built-in capabilities to manipulate HTML documents or the DOM.

Below is a quick transcript of the steps I took to unit test a function “validateEmail” which validates an email address by applying a regular expression to the input.

//on validateEmail.js
function validateEmail(email) {
var filter = /^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/;
return filter.test(email);
}

print("john.tubert@rga.com: "+validateEmail("john.tubert@rga.com"));
print("john.tubertrga.com: "+validateEmail("john.tubertrga.com"));

//on console

//this will generate the the class file (validateEmail.class)
java org.mozilla.javascript.tools.jsc.Main validateEmail.js

//run the java
java validateEmail

//will output
john.tubert@rga.com: true
john.tubertrga.com: false

A headless browser is a browser without a GUI but it’s capable of parsing Javascript, “clicking” on links, load images, determining text color, etc. All these can be done programatically from a console, so it can be used to run tests on the server as well.  I’ve been working with EnvJS, but there are alternatives like ZombieJS. The code below shows how to use Rhino and EnvJS to load a page on a console and run a series of tests.

load("../js_tests/lib/env_rhino.js");
load("http://code.jquery.com/qunit/qunit-git.js");

QUnit.init();
QUnit.config.blocking = false;
QUnit.config.autorun = true;
QUnit.config.updateRate = 0;
QUnit.log = function(object) {
print(object.result ? 'PASS' : 'FAIL', object.message);
};

//load html to test
window.location = "../index.html";

load("../js_tests/tests.js");

To run all this tests in the server automatically you can use Hudson, which is a continuous integration server. Hudson will check your source repository for a new version of the code every few minutes and build a the project if necessary.  And of course, it will run all your unit tests and report back to you if any fail.

Working this way can save you headaches later by finding some of the errors earlier in the process.

Resources

  1. Unit testing
    1. Qunit – http://docs.jquery.com/Qunit
    2. JSAssertUnit – http://jsassertunit.sourceforge.net/docs/tutorial.html
    3. JSUnit – http://www.jsunit.net/
    4. RhinoUnit – http://code.google.com/p/rhinounit/
    5. Others: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#JavaScript
  1. Javascript Engine
    1. Rhino – https://developer.mozilla.org/en/Rhino
    2. PhantomJS – http://www.phantomjs.org/
    3. SpiderMonkey – https://developer.mozilla.org/en/SpiderMonkey
    4. V8 – http://code.google.com/p/v8/
  1. Console browser
    1. EnvJS – http://www.envjs.com/
    2. ZombieJS – http://zombie.labnotes.org/
  • Chris Hinkle

    Great article John. 

  • Seanbelling

    running the tests in node.js is another option

  • http://ariya.ofilabs.com/ Ariya Hidayat

    Correction: PhantomJS has full support for HTML, DOM, CSS, even Canvas and SVG. It is capable of running dozens of test frameworks which deals with those technologies. PhantomJS uses WebKit, it is not only a JavaScript engine. See e.g. https://github.com/ariya/phantomjs/wiki/Page-Automation.