Getting Started With jQuery QUnit for Client-Side Javascript Testing

Setup

First of all, I’m assuming you’re already using jQuery. If not, you should be :) QUnit may help you for non-jQuery testing, but it’ll work better with jQuery.

Second, you should start by downloading and setting up QUnit (from this link).  QUnit consists of a single JS file (testrunner.js) and a CSS file (testsuite.css).

Third, I recommend grabbing a patched testrunner.js from here (Ticket 3215).  We, at Dovetail, submitted this patch to the jQuery team. Some of the changes were accepted, some weren’t (and then the ticket was surreptitiously closed! How rude!).  One particular feature that was NOT accepted was the beforeEach/afterEach additions to achieve xUnit-style SetUp and TearDown (before each test/after each test) behavior.  I don’t know about you, but I consider SetUp/TearDown a critical feature for any would-be xUnit framework, regardless of language/platform.

Your First QUnit Test

To start testing, you’ll need to start by creating an HTML page (MyFooTests.htm, for example).  This page will need to reference the jquery core JS file, testrunner.js, testsuite.css, as well as the JS file containing the code you’re going to be testing. Lastly, the page will need some special HTML at the bottom with well-known ID’s so that QUnit can display its output.  When you’re done, you should have a rough skeleton like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>My Foo Tests</title>    
    <script language="javascript" src="../jquery-latest.js" type="text/javascript"></script>
    <script language="javascript" src="testrunner.js" type="text/javascript"></script>
    <!-- add a script reference to your library here -->
    <link media="screen" href="testsuite.css" type="text/css" rel="stylesheet"/>    
</head>
<body>

<script language="javascript" type="text/javascript">

qUnitTesting(function(config){

    config.beforeEach = function(){
    }
    
    config.afterEach = function(){
    }
    
    //TODO: Modules and tests go here
});

</script>

        <h1>My Foo Tests</h1>
        <h2 id="banner"></h2>
        <ol id="tests"></ol>
        <div id="results"></div>
        <div id="main"></div>        
        
        <!-- Any HTML you may require for your tests to work properly -->
        
</body>
</html>

If you save that HTML and open it in a browser, you should see something to the effect of:

image

Modules and Tests

QUnit has the concept of “modules” and “tests.”  Tests are, like you would expect, the individual test cases. Modules are merely grouping mechanisms to organize the display of tests on the results screen.

Let’s create our first module and first test case.  To keep things simple and illustrative for this blog post, I’m merely going to test that the show() and hide() methods in jQuery work properly.  Normally you would want to avoid testing framework stuff (assume it’s already well-tested unless proven otherwise).

First, near the bottom of the HTML, before the closing </body> tag, add a div with an id “testDiv”:

<div id="testDiv"></div>

Then, up higher, where the “TODO” is in our JavaScript, add a new test, like so:

module("Show and Hide");

test("should hide the element when hide is called", function(){

    $("#testDiv").hide();

    // actual, expected
    equals($("#testDiv").css("display"), "none", "The element should be hidden");
});

test("should show the element when show is called", function(){

    // Arrange
    $("#testDiv").css("display", "none");
    
    // Act
    $("#testDiv").show();

    // Assert
    // actual, expected
    equals($("#testDiv").css("display"), "block", "The element should be visible");
}); 

Which should yield two successes:

image

Where to go from here?

For me, QUnit opened up the possibility for serious TDD with client-side JavaScript. Previously, quality with my JavaScript code was always an issue and it never seemed that manual testing was enough.  With QUnit, I can breathe a little easier now.

If I can catch some time in the next few weeks, I’ll do a post or two on how mocking works in JavaScript (or rather, why it’s so dirt simple it’s almost not worth talking about), and then even show how to integrate your QUnit tests into your CI build (which isn’t as hard as you might think).

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Chad Myers

Chad Myers is the Director of Development for Dovetail Software, in Austin, TX, where he leads a premiere software team building complex enterprise software products. Chad is a .NET software developer specializing in enterprise software designs and architectures. He has over 12 years of software development experience and a proven track record of Agile, test-driven project leadership using both Microsoft and open source tools. He is a community leader who speaks at the Austin .NET User's Group, the ADNUG Code Camp, and participates in various development communities and open source projects.
This entry was posted in jQuery, QUnit. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.opgenorth.net Tom Opgenorth

    Very timely for me. Thanks Chad.

    • http://www.facebook.com/people/Deborah-Smith/100002400274841 Deborah Smith

       I recently came across your blog and have been reading and watching videos along.I thought I would leave my first comment.I do not know what to say except that I enjoyed reading what you have to say.
      find a job

  • Paul Cowan

    I’ve been thinking about writing a nant task to parse the results using regular expressions.

    I’ll be very interested to see your approach to hooking it into CruiseControl

  • http://flimflan.com/blog Joshua Flanagan

    Paul – we currently drive the QUnit tests in our CI build using WATIN:

    private IE _ie;
    [TestFixtureSetUp]
    public void TestFixtureSetUp()
    {
    _ie = TestBrowser.GetInternetExplorer();
    }

    [TestFixtureTearDown]
    public void TestFixtureTearDown()
    {
    _ie.Dispose();
    }

    [Test]
    public void TagEditorTester_tests_should_pass()
    {
    RunQUnitTests(“tageditortester.htm”);
    }

    private void RunQUnitTests(string testPage)
    {
    _ie.GoTo(string.Format(“http://localhost/Content/scripts/tests/{0}”, testPage));
    _ie.WaitForComplete(5);
    _ie.Element(“TESTRESULTS”).Text.ShouldEqual(“0″);
    }

  • http://www.lostechies.com/blogs/joe_ocampo/ Joe Ocampo

    @Josh

    nice!

  • http://chadmyers.lostechies.com Chad Myers

    @Joe:

    Right now all it tells us is whether all the tests passed or not, which is good enough for basic CI integration. At some point, in our copious amounts of free time, I’d like to be able to have all the tests matched somehow in C# so that a.) they add to our total test count b.) we can get better visibility when something goes wrong and c.) we can get (maybe) some test timings out of TeamCity.

    Oh yeah, the whole TESTRESULTS thing is a customization we made for QUnit’s testrunner.js. I believe this change was accepted into the JQuery trunk, so it should be there. if not, it should be trivial to add yourself.

    I’ve been thinking about forking the QUnit trunk to make it more xUnit-style (it isn’t right now, and the jQuery folks don’t seem to be too interested in making it so). Plus, I was thinking some basic expectation-based mocking might be useful, too. Right now we’re doing test double-style mocking which gets annoying after just a few of them.

  • http://blog.zerosum.org nap

    Great writeup chad, many thanks!

  • http://peter.worksontheweb.net Peter Eysermans

    Nice introduction of QUnit, I’ve been using it in some of my projects.

    I’m really looking forward to the article(s) about mocking with JavaScript, especially mocking QUnit resultsets (like $(‘div.my-class’). I’m currently struggling with that one and it’s been holding me back when trying to test client side code.

  • http://www.appelsiini.net/ Mika Tuupola

    Good timing on article. I just wrote my first unit tests two days ago using QUnit.

    http://www.appelsiini.net/projects/jeditable/tests/

  • james

    i need this to listen to music

  • http://code.google.com/p/jqmock/ Ken Ko

    Hi, I’ve written a mock framework for jquery’s jqUnit framework, but haven’t been able to get the word out. Have a look if you are interested!

    http://code.google.com/p/jqmock/

  • http://www.yahoo.com ph

    When I copied the first program the outcome is only
    “My Foo test” and nothing… Something wrong?

  • http://craigbuchek.com Craig Buchek

    It appears that your SetUp and TearDown features are already included in QUnit, as optional arguments to module(). Admittedly, it’s a bit odd place to put them, especially since the options are collectively called “lifecycle”.