Node.js Automated Testing: A Quick Intro to Writing and Running Tests

Oct 21 2011

Node.js does not come with a formal testing suite (though there are several available). However, it comes with the necessary tools for writing simple and effective automated tests. This is a quick explanation of how to write simple tests for Node.js code. We cover the directory structure for testing, the assert class of Node.js, and automating the process with make and a Makefile.

By the end of this short blog, you should be able to quickly and easily write automated tests for your Node.js packages. <!--break-->

1. A home for tests

First, your code should have a directory for storing your tests:

$ mkdir test

We will place all of our tests inside of this directory.

2. Some code to test

Let's say we want to develop a simple Hello World class. In Node, classes are typically stored in lib/, so we'll create lib/hello.js.

  module.exports = Hello;
  function Hello() {
  }

  Hello.prototype.sayHello = function (name) {
    if (name == undefined) {
      name = 'world';
    }
    return "Hello " + name;
  }

This simple module creates a prototype object called Hello which has one function: sayHello(). The sayHello() function has an optional name argument. If name is supplied, this will print "Hello NAME". Otherwise it will print "Hello world".

Now we are ready to write a simple test to verify that Hello works as expected.

3. A simple test

We will use Node.js's built-in assert library to test Hello. And we will create a test called test/test-hello.js. Not only to we make sure to put the test in the test/ folder, but we prepend test- to the name. This will assist us in making the running of tests easier.

Here is what test/test-hello.js looks like:

  var assert = require('assert');
  var Hello = require('../lib/hello');

  // First, create a new Hello object:
  var myHello = new Hello();

  // Now test that it generates 'Hello world' when no params are given:
  assert.equal(myHello.sayHello(), "Hello world");

  // Test that it says "Hello NAME" when we pass in "NAME"
  assert.equal(myHello.sayHello("Matt"), "Hello Matt");

That is all there is to creating a simple automated test of the new code. As you can see, there is nothing special about this code. There is no big unit testing framework to learn. That makes writing the tests easy (though we are missing some bells and whistles that come with unit testing or behavioral testing packages).

We can run the test like any other Node.js script: node test/test-hello.js. If the tests pass, no output will be generated. If anything fails, Node will print a stack trace showing us what went wrong and where.

This is one test for one piece of functionality. But as your application grows, you should find yourself writing separate tests (in separate files) for each unit of functionality (each prototype or file or module). It would get tedious to run each test by hand. So we will write a build script to automate the running of tests.

4. A Makefile to Run Tests

How can we best run all of our tests? We can use a build script.

Typically, Node.js modules use some version of make (a UNIX build tool) to handle package tasks. make looks for a special configuration file called, appropriately, Makefile.

In our case, we need to write a simple Makefile that provides a testing target. The Makefile should be in the top level of your project.

We will build a Makefile with a single target for running all of the automated tests in our test/ directory:

SHELL := /bin/bash

test:
    @find test/test-*.js | xargs -n 1 -t node

.PHONY: test

The first line simple tells Make that we want to use the bash shell.

From there, we define targets for make. A target is a named command that we can ask make to run for us. Our target is test. To execute this target from the command line, we can type make test.

Make will then run one or more shell commands for our target. In the example above, it runs a basic UNIX command which finds all of the files in test/* that match the pattern test-*.js. Since our test above matches that pattern, find will pass each matched file to xargs, which will then in turn execute each file with node.

In other words, that single-line find/xargs command does this:

  • Find all files that match test/test-*.js (find)
  • Then with each file, build the command node FILE
  • And then run this node FILE command

On the final line of the Makefile, you'll notice .PHONY: test. In a nutshell, this special target tells make which targets can be run. (A full explanation is available in the Make documentation). Most of the time, in Node.js all you need to do with this is declare a list of targets you want to be able to run from the command line.

Conclusion

That is the basic pattern for building simple automated tests for Node.js code. In many cases, the Makefile supplied above should get you testing away. (You may even notice that same Makefile in a number of common node packages).

The Node.js assert library that we looked at in Step 3 is very powerful, and has several other tests you can use. Check out the documentation on assert to learn more about the other available functions.



comments powered by Disqus