JavaScript Testing Guide

JavaScript testing is a skill that you must master and in this tutorial I’ll teach you exactly how to do it. Let’s get started with JavaScript testing.

Frontend JS Testing

There’s no need to unit test for HTML/CSS because they’re not function-based languages. JavaScript is true scripting and with new resources like Node.js and TypeScript it’s becoming much more powerful.

Simple JS unit testing will take a function, monitor output and return its behavior. Smashing Magazine has a great example which tests a calendar date output function based on a specific type of input.

Not every JS project will need a unit test. But many developers prefer to be safe rather than sorry, and it’s always good to double-check work.

Every unit test is made to check against an individual unit in JavaScript, which typically breaks down to a function or library. The goal is to check every aspect of the function to make sure it all works properly for all cases.

JavaScript Unit Testing Frameworks

Sometimes you find the error message on your screen regarding such as ‘Unable to load example.js’ or any other JavaScript error regarding version control, these vulnerabilities come under JavaScript Unit Testing.

We will review some tools and frameworks that are being used to perform JavaScript Unit Testing.

1. Unit.js: It is known as an open source assertion library running on browser and Node.js. It is extremely compatible with other JavaScript Unit Testing frameworks like Mocha, Karma, Jasmine, QUnit, Protractor, etc. Provides the full documented API of assertion list

2. QUnit: It is used for both client-side as well as server-side JavaScript Unit Testing. This Free framework is used for jQuery projects. It follows Common JS unit testing Specification for unit testing. It supports the Node Long-term Support Schedule.

3. Jasmine: Jasmine is the behavior-driven development framework for JavaScript unit Testing. It is used for testing both synchronous and asynchronous JavaScript Code. It does not require DOM and comes with the easy syntax that can be Written for any test.

4. Karma: Karma is an open source productive testing environment. Easy workflow control Running on the command line. Offers the freedom to write the tests with Jasmine, Mocha, and QUnit. You can run the test on real devices with easy debugging.

5. Mocha: Mocha runs on Node.js and in the browser. Mocha performs asynchronous Testing in a simpler way. Provides accuracy and flexibility in reporting. Provides tremendous support of rich features such as test-specific timeouts, JavaScript APIs etc.

6. Jest: Jest is used by Facebook so far to test all of the JavaScript code. It provides the ‘zero-configuration’ testing experience. Supports independent and non-interrupting running test without any conflict. Do not require any other setup configuration and libraries.

7. AVA: AVA is simple JavaScript Unit Testing Framework. Tests are being run in parallel and serially. Parallel tests run without interrupting each other. AVA Supports asynchronous testing as well. AVA uses subprocesses to run the test.

Examples (using QUnit)

Let’s look at an example using QUnit.

Setting up QUnit

For this article I don’t want to set any prerequisite (read Bower and npm), so we’ll employ the first method. Therefore, go to the QUnit website and download the latest version of both the JavaScript file and the CSS file.

Place them into a folder where you’ll also create an index.html. In this file we’ll place the HTML code shown in the homepage of the website that I’m repeating below for your commodity.

How to Create a Test with QUnit

QUnit offers two methods to create a new test: QUnit.test() and QUnit.asyncTest(). The first is used to test code that run synchronously, while the latter is used to test asynchronous code. In this section, I’ll describe how to create tests for synchronous code.

The signature of the QUnit.test() method is:

QUnit.test(name, testFunction)

The first parameter, name, is a string that helps us identify the test created. The second parameter, testFunction, is the function containing the assertions that the framework will execute. The framework passes to this function an argument that exposes all of QUnit’s assertion methods.

Putting this description into code, we can update the file tests.js with the following code:

QUnit.test('My first test', function(assert) {
   // Assertions here...
});

This code creates a new test identified by the string “My first test” and a function with an empty body. Adding a test without any assertion isn’t of any utility. To fix this issue, we have to learn the assertion methods available in QUnit.

The Assertion Methods of QUnit

Assertions are the core of software testing. They are the piece that enables us to verify that our code is working as expected. In QUnit we have a bunch of methods to verify these expectations. They can be accessed within a test through the parameter passed to the function of the QUnit.test() method (assert in our previous example).

The list below summarizes the methods available, along with their signature and purpose:

  • deepEqual(value, expected[, message]): A recursive, strict comparison that works on all the JavaScript types. The assertion passes if value and expected are identical in terms of properties, values, and they have the same prototype;
  • equal(value, expected[, message]): Verify the value provided is equal the expected parameter using a non-strict comparison (==).
  • notDeepEqual(value, expected[, message]): Same as deepEqual() but tests for inequality;
  • notEqual(value, expected[, message]): Same as equal() but tests for inequality;
  • propEqual(value, expected[, message]): A strict comparison of the properties and values of an object. The assertion passes if all the properties and the values are identical;
  • strictEqual(value, expected[, message]): Verify the value provided is equal to the expected parameter using a strict comparison (===);
  • notPropEqual(value, expected[, message]): Same as propEqual() but tests for inequality;
  • notStrictEqual(value, expected[, message]): Same as strictEqual() but tests for inequality;
  • ok(value[, message]: An assertion that passes if the first argument is truthy;
  • throws(function [, expected ] [, message ]): Test if a callback throws an exception, and optionally compare the thrown error;

The meaning of the parameters accepted by these methods is described below:

  • value: The value returned by a function, a method, or stored in a variable that has to be verified;
  • expected: The value to test against. In case of the throws() method, this can be an Error Object (instance), Error Function (constructor), a RegExp that matches (or partially matches) the String representation, or a callback Function that must return true to pass the assertion check;
  • message: An optional string describing the assertion;
  • function: The function to execute that should return an Error;

Now that you know the methods available and the parameters, it’s time to see some code. Instead of writing several tests for a single function, I’ll try to reproduce a more realistic example. By any means the tests I’ll show you should be considered a complete test suite, but they should give you a concrete idea of where to start.

In order to write the mentioned tests, we need to define some code to test. In this case I’m going to define an object literal as follows:

var App = {
   max: function() {
      var max = -Infinity;
      for (var i = 0; i < arguments.length; i++) {
         if (arguments[i] > max) {
            max = arguments[i];
         }
      }

      return max;
   },
   isOdd: function(number) {
      return number % 2 !== 0;
   },
   sortObj: function(array) {
      array.sort(function(a, b) {
         var date1 = new Date(a.timestamp).getTime();
         var date2 = new Date(b.timestamp).getTime();

         if (date1 < date2) {
            return -1;
         } else if (date1 === date2) {
            return 0;
         } else {
            return 1;
         }
      });
   }
};

As you can see, we’ve defined an object literal containing three functions: max()isOdd(), and sortObj(). The first takes an arbitrary number of arguments and returns the maximum. isOdd() accepts a number as its argument and tests if it’s odd. sortObj() accepts an array of objects, that ideally should have a property called timestamp, and sorts them based on the value of this property.

A possible set of tests for these functions is shown below:

QUnit.test('max', function (assert) {
    assert.strictEqual(App.max(), -Infinity, 'No parameters');
    assert.strictEqual(App.max(3, 1, 2), 3, 'All positive numbers');
    assert.strictEqual(App.max(-10, 5, 3, 99), 99, 'Positive and negative numbers');
    assert.strictEqual(App.max(-14, -22, -5), -5, 'All positive numbers');
});

QUnit.test('isOdd', function (assert) {
    assert.ok(App.isOdd(5), '5 is odd');
    assert.ok(!App.isOdd(2), '5 is not odd');
    assert.ok(!App.isOdd(0), '0 is not odd');
    assert.throws(function () {
        App.isOdd(null);
    },
        /The given argument is not a number/,
        'Passing null raises an Error');
    assert.throws(function () {
        App.isOdd([]);
    },
    new Error('The given argument is not a number'),
        'Passing an array raises an Error');
});


QUnit.test('sortObj', function (assert) {
    var timestamp = Date.now();

    var array = [{
        id: 1,
        timestamp: timestamp
    }, {
        id: 3,
        timestamp: timestamp + 1000
    }, {
        id: 11,
        timestamp: timestamp - 1000
    }];

    App.sortObj(array);

    assert.propEqual(array, [{
        id: 11,
        timestamp: timestamp - 1000
    }, {
        id: 1,
        timestamp: timestamp
    }, {
        id: 3,
        timestamp: timestamp + 1000
    }]);
    assert.notPropEqual(App.sortObj(array), array, 'sortObj() does not return an array');
    assert.strictEqual(App.sortObj(array), undefined, 'sortObj() returns
});

The first test created is identified by the string “max”. Within this test you can see four assertions that use the strictEqual() method. We’re using this method instead of equal() because we want to avoid the case where the following assertion would pass:

assert.equal(App.max(0, true), 1);

Inside the test, we’re checking for several different types of input. What I’m trying to suggest with this test is to try to cover the largest number of situations possible: no parameters, all positive numbers, all negative numbers, mixed cases. I haven’t covered every possibility, but this is a good start.

The second test, identified with the string “isOdd”, shows you the use of ok() and throws(). The former is useful when you need to verify functions that return a Boolean value like the isOdd() function of our example.

You can also see the throws() method in action. Probably the most interesting part of the assertions using throws() isn’t the first parameter, which is the function that raises the error (in these cases because we passed an incorrect parameter), but the variations of the second parameter. In fact, I’ve employed both a regular expression and an Error instance.

The third and last test, identified by the string “sortObj”, puts into action other assertion methods. The first assertion uses propEqual() to verify the array passed to the sortObj() function returns an array containing the same objects (same properties and values) in the order we expected. In this test the deepEqual() method is a good fit too because the expected parameter is identical to the input array (same properties, values, and prototype). I could have not employed strictEqual() because they are not the same object, that is two objects pointing to the same memory address.


The second assertion is a bit naive and serves only to show the use of notPropEqual(). It’s naive because we’re already verifying the expected value in a more accurate way using the strictEqual() method in the third assertion.

Leave a Reply

Your email address will not be published. Required fields are marked *

Up Next:

Facebook's Library Fresco Merged My Code

Facebook's Library Fresco Merged My Code