TDD Javascript With JsUnit

Evaluating this framework brings back memories… the year was 2005, I had been working for a small IT firm as one of the first developers hired, which as of 2005 included three developers. I had zero process in place and had never had any experience elsewhere as this was my first job. Somehow, from reading Royce’s Software Project Management to a book on RUP to a book on Scrum, I finally found my way to Extreme Programming and was trying my best to implement it. I had just picked up unit testing and was using SimpleTest (after trying PHPUnit out and deciding I liked SimpleTest better) and felt that I should be Test Driving all code, javascript included. So I joined #javascript on efnet and asked “Hey, what should I use? I’ve been trying jsUnit out…”

The reply I got was that I should stop using jsUnit from and start using the one on instead as it was a more faithful port of JUnit, was more Object Oriented, and it was possible to run the tests from Rhino (which led me to asking what rhino is, and then a 2 hour longer conversation ensued).

Anyway, jsunit is just that… it’s a faithful port of JUnit 3.8.1 and is designed in a more object oriented way than it’s counterpart. In fact, the syntax looks similar to the current built in test runner in js-test-driver. With that out of the way, let’s take a quick look at the dirty details.

The Dirty Details

Apache Software License 2.0

Last Updated
The last stable release was 1.3 in October of 2008.

The jsunit mailing list link on the page links to the other jsunit, but you can email the author directly.

Let’s Dive In!

First let’s download the tarball for jsunit 1.3, and extract it to a directory. It seems a maven2 and ant plugin are included for plugging into continuous integration cycles, but thats a topic for another post so we’ll delete those.

First, I admit it’s been a long time since I used this so I’m a bit disoriented, but in the samples directory there are many sample tests, and an example runner named AllTests.html. This is more of an example on how to implement a runner versus “the de-facto runner” … it’s very basic. Here’s the javascript code driving it:

var writer = new HTMLWriterFilter( JsUtil.prototype.getSystemWriter());
var printer = new ClassicResultPrinter( writer );
var runner = new EmbeddedTextTestRunner( printer );
var collector = new TestCaseCollector( this ); collector.collectTests());

and here’s the output of opening it up in firefox:

Yep… very basic.There are also various examples in other languages, such as JScript in AllTests.asp, AllTests.jsp, and more. Alright, enough of that… let’s go ahead and write a test case for the old HTML5 placeholder example.

Getting started is pretty simple… we’ll just modify the existing sample code and get started with the test case. The examples use a format of defining functions prefixed with the test name (i.e. Html5PlaceholderTest_setUp()) and then calls glue to add those methods in. I don’t like this though, and you don’t have to do it as long as you set the protototyp to TestCase before adding test methods. Anyhow, here’s the first test:

function Html5EmulatorTest(name){ this, name );
Html5EmulatorTest.prototype = new TestCase();
Html5EmulatorTest.prototype.setUp = function(){
  var sandbox = $('
') this.emulator = new Html5Emulator(sandbox); this.PLACEHOLDER_TEXT = "placeholder text is here"; this.input = sandbox.append('

With the exception of having to call TestCase in the "constructor" and assigning the prototype to TestCase, you might notice that that as I mentioned previously the syntax is similar to that found in js-test-driver. Here is my current directory structure.

So with the basic runner I open it and firefox and see some plain text describing that I have a failure... wirte some code to make it pass and it passes. Simple enough, but very ugly... when you get to multiple test cases (as you surely will) it's hard to distinguish the results.

Anyhow, as usual I have completed test driving some example code and provided it on github for your viewing pleasure.

What I Liked

  • A lot more object oriented than the other jsUnit
  • Pretty faithful adaption of JUnit
  • It's possible to run from any javascript interpreter, and includes an ASP example

What I Didn't Like

  • Hasn't been updated forever... not sure if it's a live project anymore
  • The included runner is very plain... it'd be nice to at least have red/green bar
  • You have to remember to set the prototype to TestCase and invoke in all your test cases


Overall I did like the fact it feels like a straight adaption of JUnit, and like I said a similar syntax survives in js-test-driver. It's overall a good framework, but sadly in today's arena it really doesn't have anything special going for it. But it was definitely a start in the right direction.

What's Next?

Wow... who woulda thunk there were so many javascript TDD frameworks out there!? And there's still more... Crosscheck, jsunittest, FireUnit, SugarTest, and many many more. But for now I think we've covered enough and although I'll cover these as the chance arises I will now be moving into the next phase of this series.

The most important aspect of test driven development is automated Continuous Integration. All these frameworks are fine and dandy, but they're useless if you can't have them running in daily (or even hourly.. or even every 10 minutes) so that you know when something is broken. So for the next several blog posts I'll be investigating how each of these frameworks (or at least the ones I like working with the most) stack up in ease of integration in CI. Stay tuned! ;)

  • Travis Nichols

    It would be really interesting to see a blog with the comparison of the several different JavaScript testing frameworks you have investigated/used. Perhaps you might even be able to put it in a table (unless the vague reference to early HTML structure is too disturbing).

  • James Carr

    Thanks Travis!!

    In fact, I think this is a wonderful idea… it’d be great for others to be able to have a quick reference to help decide on which framework they’d like to use. :)