TDD in Javascript with QUnit

Posted: January 09, 2009

These days you'd be hard pressed to find a web application that isn't using JQuery, Prototype, or YUI. Over the last few months I've had several conversations with fellow developers about how to test applications using these frameworks.

Fortunately each of these frameworks includes a unit test runner. In this article I dive into QUnit, the test harness for JQuery based web applications.

Technologies

In this example I'll be using the following technologies:

  • JQuery 1.2.6
  • QUnit - I used the current trunk version as of 1/9/2008

QUnit TDD Workflow

In QUnit, each test "class" is a single HTML file. You write a <script> block inside this file that contains your unit test code. Consequently, the TDD workflow looks like this:

  1. Create a QUnit HTML file
  2. Write a test function in the file
  3. Load the HTML file in your browser (using a file:/// path, no web server required
  4. The test function should run, and fail
  5. Write Javascript code to make the test pass
  6. Refactor
  7. Repeat

Reloading the HTML file in your browser becomes natural after a while. It's the equivalent of running a JUnit test individually in your IDE. And if you use Firebug you can debug the js code while the test runs if necessary.

Example

QUnit HTML file: test1.html

<html>
<head>
    <title>Group Tests</title>

    <!-- these 2 lines will be the same in each of your QUnit HTML files -->
    <script language="javascript" src="../../main/webapp/js/jquery-1.2.6.min.js" 
        type="application/javascript"></script>
    <link media="screen" href="testsuite.css" type="text/css" rel="stylesheet"/>
    

    <!-- this file contains the js file under test -->
    <script language="javascript" src="../../main/webapp/js/group.js" 
        type="application/javascript"></script>

    <!-- your test functions go in this block -->
    <script language="javascript" type="application/javascript">

    $(document).ready(function() {

        test("constructor hides div", function() {
            var controller = new CreateGroupController('create-group');
            equals($("#create-group").css("display"), "none", "Element should be hidden");
        });

        test("shows div when told to", function() {
            var controller = new CreateGroupController('create-group');
            controller.show();
            equals($("#create-group").css("display"), "block", "Element should be visible");
        });

    });

    </script>
</head>
<body>

    <h1>Group Tests</h1>

    <!-- these are boilerplate elements that qunit requires -->
    <h2 id="banner"></h2>
    <ol id="tests"></ol>
    <div id="results"></div>
    <div id="main"></div>

    <!-- this is the div we're going to show/hide in our test -->
    <div id="create-group">
    <form action=""></form>
    </div>

<!-- I put this at the bottom of the file to workaround an issue in HTMLUnit, which I use to
         automate running the tests on my Continuous Integration server -->
<script language="javascript" src="testrunner.js" type="application/javascript"></script>
</body>
</html>

Output in Browser

When you run this test, you'll see output like this:

QUnit test output

A failed test will look like this:

QUnit test output failure

Conclusion

This is a very basic overview of how to use QUnit to test drive your Javascript development. In my next entry I'll explain how to automate your tests using JUnit and HTMLUnit.