Unit testing JavaScript

August 4, 2009 – 2:46 pm Tags: , ,

I’ve recently been looking into some JavaScript unit testing frameworks. There are many alternatives, and while many of them seem good, very few of them actually matched my requirements:

  • Must be able to run tests from the commend-line
  • Tests should be relatively easy to write

Some alternatives

There’s a multitude of JavaScript testing frameworks, ranging from xUnit style ones like JsUnit to more unique ones like jQunit, jsspec and such.

However, many share a major flaw: You can’t run tests from the command line. Easily that is.

Why do I want to run tests from the command-line you ask? Afterall, it’s JavaScript… Well because it’s much simple to just hit up arrow and enter to run the testsuite, rather than having to open the browser, change the tab, change the URL and reload the page.

And not only that.

Various testing libraries that run in the browser require you to fill your tests with cruft that set up a nice HTML document, include the script files, etc. etc.

Out of the various libraries available, Berlios JsUnit, Dojo Object Harness (D.O.H.) and JsTestDriver seemed like the best choices to try out, as they each provided a xUnit’ish feel and allowed command line running.

Berlios JsUnit

While this library seemed okay at first, their documentation was a bit scant. I found some examples about tests and running them from the command line, but it seemed a bit labor intensive to load various files manually, and the examples used ActiveX FileSystemObject, so I wasn’t sure whether it would be a good idea to use the library if it wasn’t able to load the scripts without that…

Thus, I left the library on the “backup plan” position in case the two others wouldn’t work out.

Dojo Object Harness

D.O.H. seemed like the most complete JavaScript unit testing tool. It had it all: Browser tests, command-line tests, even automated user-interface testing was possible with it!

That is, until I read the documentation. The documentation that didn’t exist. I had forgotten how poorly documented Dojo was, and was quickly reminded of it.

Now, there are some articles around the web regarding D.O.H., and Dojo’s site has some documentation as well. However, I found them totally unhelpful.

Despite this, I decided to try and get the tests running, and to my surprise, the command-line test runner actually ran on the first try. The problems started when I wanted to get my own code loaded into it and tested. Since my code didn’t follow Dojo’s coding style, it seemed next to impossible to get the test runner to figure out where the files were and how to load them.

While the Dojo testing library seems very good, I gave up after a few hours of fighting it and trying to figure out what’s wrong by reading their source code. As usual, nobody on Dojo’s IRC channel had any idea why it didn’t work.

Free tip: Are you making a code library? Do you want it to be popular and widely adopted? Write. Good. Docs.

JsTestDriver

This was the late-comer to my testing framework list. I randomly spotted it on Miško Hevery’s blog, which is something you must read if you haven’t heard of him. Full of excellent advice on making code testable and various best practices type things.

JsTestDriver seems to be a tool written by Miško and some others, and while it looks simpler than some other alternatives, this is the tool I went with.

Why is JsTestDriver better than the others available? It’s almost perfect, that’s why.

First, it doesn’t get much easier than this to do JavaScript testing, as the tool is very easy to configure. You don’t need to manually load the script files you are testing, or your unit test files. JsTestDriver takes care of it for you. Second, it runs on the command-line perfectly fine. Third, you can run tests in multiple browsers at once.

But I said I didn’t want to run tests in browsers. Yes, I don’t want to manually go into the browser and refresh the page to run the tests. The great part about JsTestDriver is that I can open a new tab in the browser, navigate to JsTestDriver’s URL (it has a small server that you run), and simply make the tab a “slave” for testing. After this, I can just forget the browser or use its other tabs for whatever else I want. When I want to run the tests, I simply run the JsTestDriver test runner and it runs my tests in the slave-tab, displaying the results in the command-line.

In closing

So while there are many alternatives if you’re not picky about things like command-line running, you’re hopelessly out of luck if you are. I’m glad I managed to spot JsTestDriver since it’s a great tool, but seems it isn’t very widely known.

For great comparisons of various JS unit testing frameworks, I recommend visiting James Carr’s blog. He has written comparisons about many of JS testing tools, and is planning on writing even more.

Have you tried using unit testing tools with JavaScript? I’m interested in hearing your experiences, especially if you managed to get Dojo’s tool to run command-line tests for code not written in Dojo-style.

Share this:

RSS feed Subscribe to my RSS feed

About the author

Jani is a 15 year veteran of the software industry. He's currently available for consulting

  1. 8 Responses to “Unit testing JavaScript”

  2. So how many people out there, using any kind of framework at all, actually test-drive their JavaScript development?

    For TDD, our javascript unit tests should run in an IDE, so that we can run individual tests repeatedly as we test-drive the code. We also don’t want to mess about with browser instances. In addition, We wish to include the tests as part of a continuous integration build.

    Our current javascript unit-testing setup works rather well for us:
    (1) HtmlUnit executes the Javascript;
    (2) A single file defines stub versions of all the HTML DOM elements, and mocks core behaviour of the document;
    (3) JsUnit.js provides a JUnit-like test environment.

    This allows us to write tests like this:

    this.testClickingButtonCallsFunction = function() {
    this.assertFalse(this.functionCalled);

    this.button.anchor.onclick();

    this.assertTrue(this.functionCalled);
    }

    and this:

    this.testFailsDisgracefullyIfThereIsNoEvent = function() {
    this.assertFails(“You have not supplied an event to bind to the button”, function() {
    this.button = makeButton(self.anchor.id, null);
    });
    }

    which should look comfortingly familiar.

    Most of the development cost is in (2), where we have built a mixture of stubs and mocks to simulate the behaviour of the DOM. As the project matures, we spend less and less time doing this.

    By Chris Agmen-Smith on Aug 5, 2009

  3. nice write up Jani,
    I toyed with jsunit for a while while writing my old ajax library. It was semi cumbersome to use and to be honest I never really used it in real production code because of the time overhead.

    I’ll give JsTestDriver a whirl… also nice link to Miško’s blog, looks like he’s got some interesting articles.

    Jim

    By Jim Plush on Aug 5, 2009

  4. If you’re interested in command-line JS unit testing tools, take a look at rhinounit: http://code.google.com/p/rhinounit/

    It’s uses Rhino to test the JS (no browser involved) and also runs JSLint checks to check the code for syntax inconsistencies. It comes with an ant-script that can be easily included in existing build processes.

    By Menno on Aug 6, 2009

  5. @Chris,

    The set up you describe is exactly the goal of JsTestDriver except we run everything in real browsers. No rhino/htmlunit involved. Everything runs from your IDE, we even have eclipse plugin which lets you run tests by right clicking on them.

    By Misko Hevery on Aug 23, 2009

  6. Also check out Jasmine — http://github.com/pivotal/jasmine/ — an easy, framework-agnostic behavior-driven development environment for JavaScript.

    By Christian Williams on Jul 17, 2010

  7. @ Christian,

    Jasmine ROCKS! It is by far my favorite assertion library, which is why I have hooked it up to JsTestDriver http://github.com/mhevery/jasmine-jstd-adapter So JSTD runs my tests, but I write them in jasmine stile. Check out a sample project which has this setup. http://github.com/angular/angular.js

    By Misko Hevery on Jul 30, 2010

  8. Nice comparison. I too have had trouble finding any significant information on DOH. Which is too bad, because I suspect there are some good ideas in there.

    For those of you interested in unit testing – and TDD in particular – with JavaScript, I have a book coming up on the subject in September: http://www.amazon.com/dp/0321683919/

    I also have a stubbing/mocking library, Sinon.JS, which works well with JsTestDriver (and others). It’s particularly useful with jstd, as jstd does not support asynchronous tests – Sinon provides fake XHR and timers implementations.

    Sorry about the shameless plug, but I thought it might be relevant :)

    It also seems like John Resig did some interesting work with TestSwarm, testing the mobile field. TestSwarm works kinda like JsTestDriver (with the server and distributed tests), check out the presentation on the mobile jQuery announcement (bottom of page): http://jquerymobile.com/gbs/

    By Christian on Aug 13, 2010

  9. One thing that should be mentioned is the jsTestDriver (at the time of writing this) has a major bug, whereby importing any popular JS framework (like Prototype, jQuery, or MooTools) breaks some internal JSON parsing and hoses jsTestDriver: http://code.google.com/p/js-test-driver/issues/detail?id=32

    By siannopollo on Feb 1, 2011

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)