Setting up a unit testing environment in Node.js

Example Project

Introduction

In this post we'll go through the complete process of setting up your test environment in a Node.js app, and then write a few simple unit tests. Although I've aimed this for Node apps, you should be able to follow these steps for any JavaScript setup such as Ionic.

Before reading reading this article you should already know:

1. Setting up a Testing Framework

A testing framework will take care of the overall test structure for us and make it easy to run our tests and allow us to use additional plugins too if necissary (such as generating HTML test reports, or providing coverage test features). It is possible to do all this with vanilla JavaScript, but a lot more work

The two most popular test frameworks are Mocha and Jasmine. For this we will be using Mocha.

Since we will use the 'mocha' command, we must first install Mocha globally. If not you will get the error message 'mocha is not recognized as an internal or external command' (or mac equivalent).
npm install mocha --global

If your using git, or have multiple developers working on the project you'll also want to add mocha to your package.json so others can just run npm install to populate their node_modules.
First initialize your package.json (if you haven't already done so):
npm init

Then add mocha to your devDepenencies and save in node_modules by running
npm install mocha --save-dev

Next we need to create a directory to store our tests. By default mocha will look for a folder called 'test' inside the projects root, so we must use this name exactly.
mkdir test

Summary

The following commands can be used to setup mocha in a new project. (mac commands might be slightly different)
mkdir test-example && cd test-example :: create new projet director

npm i mocha -g :: install mocha globally so the mocha command can be used

npm init :: initialise package.json

npm i mocha -D ::  add mocha to your projects devDependancies

mkdir test :: create new folder for tests


2. Setting up an Assertion Library

Node does have some assertion test functionality built in, although it is quite basic, and not particularly nice to use. So instead we are going to use Chai as an assertion library - there several others out there, but chai is good and well established with good documentation.
So first off we need to install chai to our project like we do with all node modules:
npm install chai --save-dev

Next we are going to create a file to put our test in. Remember this should be inside the test directory. The file can be called what ever you like (but keep it relevant), and the extension should be .js (or .coffee if your writing your tests in CoffeeScript).

Inside your new test file, the first step is, as usually done with node modules, to include the module in your file.
var chai = require('chai');

If you visit the Chai website(http://chaijs.com/) you will see that chai has three interfaces: Should, Expect and Assert.

It is up to you which one you use, and it's easily possible to use a combination. They all work in a similar way, with the only main difference being the syntax and the structure of the test blocks you write. Should is much more like English, and Assert is more like conventional JUnit comparisons, Expect is somewhere in between.

So if we were using expect, the fist thing we would need to do is define the expect method.
var expect = chai.expect;

The format of your tests will have a describe block for what the code module should have been tested for, followed by a series of it's containing the Chai tests, in this format:
describe('JavaScript example test', function(){
    it('should return true in JavaScript',function(){
        expect(true).equal(true);
    });
});


The format of an expect method is like this:
expect(foo).to.be.a('string');
expect(foo).to.equal('bar');
expect(foo).to.have.length(3);
expect(tea).to.have.property('flavors')
  .with.length(3);

Example from the Chai documentation, view more here: http://chaijs.com/guide/styles/#expect


3. Running Tests, and specifying additional options

Once you have a sample test, like above. You can run it to see the result.
To run all tests in the command line, use the following command:
mocha

Running tests from a single file

If you'd like to run just tests from a single file, you can type mocha followed by the path to the test file.

Specifying test path in package.json

It's good practice to specify a command to execute your tests in your package.json. 
This will allow other developers to run 'npm test' on any project whatever testing framework or setup is implemented.
In the scripts section, where you've specified the entry point, add a test command:
"scripts": {
    "start": "node ./bin/www",
    "test": "mocha",
  }

This will mean you can run npm test and npm will run the mocha command.

Passing additional parameters to mocha

With mocha, it's possible to pass it additional parameters to specify options such as how tests are run. 
You can change things like, how results are displayed, what language you write your tests in (e.g coffee), whether it should look in sub-directories or not, the timeout etc......
This can be done with the ordinary flag syntax, e.g.
mocha --reporter nyan --recursive

You can see a full list of flags here: https://docs.npmjs.com/misc/config

The above command will set the reporter (how results are displayed) to be Nyan cat (check it out, it's pretty cool), and the recursive flag will mean that mocha will also execute tests in sub-directories.

But, it's a bit of a pain having to specify all those flags instead of just calling the mocha command. So you can instead create a file called 'mocha.opts' inside your test directory. In this file you can specify a list of flags. Then you can just run the mocha command, without typing any parameters in the command line.

Put each flag on a new line, and use long flags rather than short-hand so that it's clear for other developers. Here is an example mocha.opts file:
https://github.com/mochajs/mocha/blob/master/test/mocha.opts

4. Coverage Testing

See coverage testing confluence article here: 


3 comments :

Post a Comment