Basic Nodeunit test with Grunt

In this post I'd like to show my first experience with Nodeunit testing tool, more precisely with the Nodeunit plugin for Grunt.

I chose a quite simple code to experiment with Nodeunit, and demonstrate how Nodeunit can help a test driven development process. In the following we will write a function, that accepts two numbers, and returns the sum of them. It sounds pretty easy, but we want to write the test first, and then - with the help of the test - the function.

Make some basic build automation

I will use Grunt for build automation. If you don't know much about Grunt, check the Getting started section in the official site of Grunt). You will need Node, so install it, if you hadn't done yet. I went through the next steps in my project library:

  • create package.json file
  • install grunt-cli
  • install grunt
  • install jshint plugin
  • install nodeunit plugin
  • create Gruntfile.js
  • test build
Create package.json file

There is a simple way to create package.json file. Just type npm init and fill the fields (or just leave them empty, as you like it).

After deleting some fields, my (very plain) package.json file looks like this:

{ 
"name": "check-out-nodeunit", "version": "0.0.0", "description": "basic nodeunit test with Grunt", "keywords": [ "nodeunit", "tdd" ], "author": "tompascall", }

Install grunt-cli

npm install grunt-cli

Install grunt

npm install grunt --save-dev

Install jshint-plugin

npm install grunt-contrib-jshint --save-dev

Install nodeunit-plugin

npm install grunt-contrib-nodeunit --save-dev

Create Gruntfile.js

My Gruntfile.js looks like this:

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    jshint: {
      files: ['gruntfile.js', 'src/**/*.js']
    },
    nodeunit: {
    files: ['src/**/*-test.js'],
    options: {
      reporter : 'default'
    }
  }
  });

  // Load the plugin that provides the "jshint task.
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-nodeunit');

  // Default task(s).
  grunt.registerTask('default', ['jshint', 'nodeunit']);
};

(I'm going to put the file with the add function and the test file to the src folder)

If we type grunt, the default task runs:

$ grunt  
Running "jshint:files" (jshint) task  
>> 1 file lint free.

Running "nodeunit:files" (nodeunit) task

OK: 0 assertions (1ms)

Done, without errors.

Now we have our build automation and it works, but there is nothing to build, and nothing to test. So let's write our test code.

Creating test

Our goal is to write a test for a function, that adds two numbers. We will put this add() function in src/calc.js, and our test code will be located in src/calc-test.js. The test code looks like this:

var calc = require("./calc.js");

exports.testAdding = function(test){  
    var x = 3,
        y = 2;
    test.equals(x+y, calc.add(x,y), "Test add function");
    test.done();
};

Let's see what happens if we try to build:

$ grunt  
Running "jshint:files" (jshint) task  
>> 2 files lint free.

Running "nodeunit:files" (nodeunit) task  
Fatal error: Cannot find module './calc.js'

Create an empty calc.js, and build:

$ > src/calc.js  
$ grunt
Running "jshint:files" (jshint) task  
>> 3 files lint free.

Running "nodeunit:files" (nodeunit) task

calc-test.js  
✖ testAdding

TypeError: Object has no method 'add'  
    at Object.exports.testAdding (/Users/check-out-nodeunit/src/calc-test.js:7:24)
    at Object. (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/lib/core.js:236:16)
    at /Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/lib/core.js:236:16
    at Object.exports.runTest (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/lib/core.js:70:9)
    at /Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/lib/core.js:118:25
    at /Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/deps/async.js:513:13
    at iterate (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/deps/async.js:123:13)
    at async.forEachSeries (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/deps/async.js:139:9)
    at _concat (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/deps/async.js:512:9)
    at Object.concatSeries (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/deps/async.js:152:23)


FAILURES: 1/1 assertions failed (8ms)  
Warning: We have got test failures. Use --force to continue.

Aborted due to warnings.

We get a quite long error message, but the bottom line is at the beginning: Object has no method 'add'. Let's create an 'add' function in calc.js, but make a mistake:

exports.add = function(x, y){  
    return x*y;
};    

Let's build:

$ grunt  
Running "jshint:files" (jshint) task  
>> 3 files lint free.

Running "nodeunit:files" (nodeunit) task

calc-test.js  
✖ testAdding

Assertion Message: Test add function  
AssertionError: 5 == 6  
    at Object.equals (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/lib/types.js:83:39)
    at Object.exports.testAdding (/Users/check-out-nodeunit/src/calc-test.js:7:7)
    at Object. (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/lib/core.js:236:16)
    at /Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/lib/core.js:236:16
    at Object.exports.runTest (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/lib/core.js:70:9)
    at /Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/lib/core.js:118:25
    at /Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/deps/async.js:513:13
    at iterate (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/deps/async.js:123:13)
    at async.forEachSeries (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/deps/async.js:139:9)
    at _concat (/Users/check-out-nodeunit/node_modules/grunt-contrib-nodeunit/node_modules/nodeunit/deps/async.js:512:9)


FAILURES: 1/1 assertions failed (7ms)  
Warning: We have got test failures. Use --force to continue.

Aborted due to warnings.

Here comes the long error message again, the essence is at the beginning: Assertion Message: Test add function
AssertionError: 5 == 6
. Fix the code, and build again:

$ grunt  
Running "jshint:files" (jshint) task  
>> 3 files lint free.

Running "nodeunit:files" (nodeunit) task

calc-test.js  
✔ testAdding

OK: 1 assertions (7ms)

Done, without errors.


comments powered by Disqus