Previous month:
June 2010
Next month:
September 2010

August 2010

Testing Client Side Javascript with Jasmine and Node.js

After having spent a long time trying to run javascript tests with Rhino, I've finally found something better. Rhino was never really fast enough for me. Spinning up the JVM just takes too long when you're running your tests continuously. A few seconds really makes a difference when you do something hundreds (thousands?) of times per day.

On top of that, testing frameworks like ScrewUnit (aside from being abandonware) have scoping issues that make tests very brittle...unless you run each one in it's own process...again back to the JVM startup problem.

Recently, I started playing around with the Jasmine testing framework for Javascript. It was really nice, but I wasn't convinced it was really going to solve the problems I was experiencing since they were mostly due to global namespaces and Rhino.

Enlighentment came, however, when I tried running Jasmine tests from within Node.js, using a patched version of mhevery's jasmine-node module. If you don't know, Node.js is a Javascript runtime environment based on the V8 engine. It's actually designed for server-side development, but I wondered if I could use it to run tests for my in-browser javascript. The answer is mostly, but the results were very compelling and I'm now doing this on all my web application projects.

Firstly, here's an example project that shows how I set things up.

To understand what's going on here, lets begin at the html. In index.html, we're not doing anything fancy. Just a few tags to load jquery and the javascripts in our app:

The interesting bits start to show up in spec/specHelper.js

specHelper.js is actually a proper node.js module, meaning that it explicitly declares it's exports. What it's doing, actually, is exporting the namespace for our entire application (as the variable 'app'). This means that in our specs:

We can create a completely clean copy of the entire application and store it in a variable that the tests can access. Jasmine's beforeEach function can recreate it before every single test. This means that we don't have to create a new Rhino instance for each test to get a clean environment. As a result, these tests run fast (hundreds of tests per second).

They run so fast, in fact, that I've been using Watchr to run them. Here's my Watchr script

This automatically runs all the Jasmine specs on each change. The tests run so quickly I haven't had the need to optimize it yet. I've been really happy with this setup (despite a few problems with jquery and env.js) and I'm hoping to improve it as the tools mature.