Site Loading

TDD unit tests and javascript with QUnit

I did a post on TDD a while ago and based it on C# and I thought it would be a good idea to look into TDD and unit testing in Javascript.

Overview on TDD

This is a really quick overview of TDD from the earlier post:

The easiest way of understanding what test driven design is, can be achieved by looking at the following diagram: Test-driven development
Please note I have obtained this image from Wikipedia (the article can be found here) To summarize:

  1. Before writing any code to solve the issue:  write a test to test the functionality.  If the test passes then the functionality exists or the test has not been written correctly.
  2. Run the tests to make sure that this does fail.
  3. Write only enough code to make the test pass.
  4. Run all the tests to make sure that the test passes.   All the tests should be run to make sure that the new code does not break the existing tests.
  5. Refactor and clean up the code.

 

Unit Testing in JavaScript using QUnit

I am using QUnit as the unit testing framework.  This is a framework from the same guys who do JQuery.  There are other frameworks out there, this just the one I have chosen based on my love of JQuery.

You can find the frameworks here (if you know of others not listed here then please let me know):

Your first unit test in JavaScript

QUnit comes for CSS and a template for running these tests in a browser.  All you need is to create an Html file with the following markup:

<!DOCTYPE html>

<html>
    <head>
        <title>QUnit Test Runner</title>
        <link href="/Content/qunit.css" rel="stylesheet" />
    </head>
    <body>
        <h1 id="qunit-header">QUnit Test Runner</h1>
        <h2 id="qunit-banner"></h2>
        <div id="qunit-testrunner-toolbar"></div>
        <h2 id="qunit-userAgent"></h2>
        <ol id="qunit-tests"></ol>

        <!-- Scripts required for the test -->
        <script src="/Scripts/jquery-2.0.3.min.js"></script>
        <script src="/Scripts/qunit.js"></script>
        <script src="/Scripts/Custom/UnitTests.js"></script>
    </body>
</html>

I have put all the tests in a file called UnitTests.Js

The First test is:

test("Simple test", function () {
    ok(1 == "1", "Passed!");
});

 

Testing objects

So to do something that is a little more like what we would be doing is testing objects and the methods contained in them.  So I have created a test for the constructor:

test("Does property get set on creation", function () {
    var value = "Property Value";
    var object = new MyObject(value);
    same(object.MyProperty, value);
});

And a test for the simple method

test("Does property get changed on calling 'MySimpleMethod'", function () {
    var value = "Property Value";
    var object = new MyObject(value);
    object.MySimpleMethod();
    same(object.MyProperty, "Something else");
});

So looking at the Object it should like this:

function MyObject(propertyValue) {

    this.MyProperty = propertyValue;

    this.MySimpleMethod = function () {
        //Change the value of the property to something else
        this.MyProperty = "Something else";
    };
};

So this shows how we can test methods in the class. If those methods are interacting with the DOM we can check to make sure that the DOM has been updated.

Parameterizing unit tests

Sometimes you may want to run the same test multiple times.  I have found a very useful plugin for QUnit that allows for this.  You can find it a https://github.com/AStepaniuk/qunit-parameterize.  An example would be:

QUnit
    .cases([
        { data: "First" },
        { data: "second", },
        { data: "third" }
    ])
    .test("Multiple Input Test", function (params) {
        var value = "Property Value";
        var object = new MyObject(value);

        object.MultipleTestMethod(params.a);

        same(object.MyProperty, params.a);
    });

And the code being tested is:

    this.MultipleTestMethod = function (input) {
        this.MyProperty = input;
    },

This means that you wouldnt have to create three separate tests but just incorporate it all into one test but when it is run it looks like three separate tests.

Mocking objects

Lastly I wanted to see how we could mock the behaviour of objects being used in our classes. An ajax request is a perfect example of this. So I looked around in the internet and my example is taken from a really clever stackoverflow answer.  So here is my adaptation with the current object:

test("Mocking test for the Ajax Method", function () {
    var options = null;
    var data = "data=1";
    var value = "Property Value";
    var object = new MyObject(value);

    //Override the ajax function
    jQuery.ajax = function (param) {
        options = param;
    };

    object.AjaxRequestMethod("url", data);

    same(options.data, data);
});

and the code being tested:

this.AjaxRequestMethod = function (url, dataToSend) {
        $.ajax({
            url: url,
            type: 'POST',
            dataType: 'json',
            data: dataToSend,
            success: function (data) {
                //update the page with the returned data
                $('#MyDiv').val(data.newProperty);
            }
        });
    };

Final Results

So when you run the tests it should look like this:
Test-driven development

If you are looking for the code I have used to create, you can find it here

Close