Wednesday, May 23, 2012

A Simple Introduction to Behavior Driven Development in NodeJS with Mocha

I recently had a chance to use the Mocha test framework for NodeJS on a large-ish project and wanted to provide a really simple introduction to it.  Mocha is a unit testing framework for NodeJS apps from TJ Holowaychuk.  As the successor to the popular Expresso test framework, it adds a number of new features. It supports both Test-Driven and Behavior-Driven development styles and can report test results in a variety of formats.

Mocha can be installed easily using npm. Assuming you have node and npm installed, you can install mocha as a global module using the -g flag to it will be available everywhere on the system.

npm -g install mocha

or perhaps

sudo npm -g install mocha

or, if you prefer a local install instead of a global install

npm install mocha
export PATH=./node_modules/.bin:$PATH

You're also going to want should.js, which you can install in your local project folder.

npm install should

Mocha, in addition to being a test framework, is a command-line utility that you run when you want to test things. You should be able to type `mocha -h` on the command line now and get some usage info.

Example


Before we can use mocha to test stuff we should have a little bit of code to test. I'm going to borrow from Attila Domokos' blog http://www.adomokos.com/2012/01/javascript-testing-with-mocha.html but try to simplify it just a bit. We're going to create two files in two different directories:

src/dog.js
test/dog_test.js

dog.js is our source code that we want to test.  Normally this would be a module that you have written. Since this is a super-simple introduction, it just exports one function called "speak". We can use this to invoke the "speak" method, which will return "woof!".

// dog.js
function speak() {
    return 'woof!';
}
exports.speak = speak;

Now we can write something to test our code: dog_test.js. Remember this file goes under the test/ directory and dog.js is under the src/ directory. So here is how we would write a test case for Dog.

// dog_test.js
var should = require('should'); 
var dog = require(__dirname + "/../src/dog");

describe('dog', function() {
  it('should be able to speak', function() {
    var doggysound = dog.speak();
    doggysound.should.equal('woof!');
  });
});

Now there should be a src/ and a test/ directory with these two files in them.

src/dog.js
test/dog_test.js


Mocha will automatically run every .js file under the test/ directory. To run the tests you can simple type 'mocha' on the command line:

mocha

and it should give you the following output:

  ✔ 1 test complete (3ms)

or if you want a little more detail use:

mocha -R list

and it should give you this output:

  ✓ Dog should be able to speak: 0ms
  ✔ 1 test complete (2ms)

Mocha can generate several different styles of test reports. To see a list of the types of reports it can generate, type mocha --reporters.


Explanation


Let's take a quick look at the test case definition. A group of tests starts with "describe". You provide some title for the thing you're testing. You can choose whatever title you want, but it should be descriptive. Our test suite is called 'dog'.

describe("dog", function () {
    // your test cases go in here
}

You can describe more than one group of tests in the file.

describe("dog", function () {
    // your doggy tests
}

describe("puppy", function () {
    // your puppy tests
}

Test descriptions can be nested, which is often convenient.

describe("dog", function () {
    describe("old tricks", function () {
        //  your old doggy tricks
    }
    describe("new tricks", function () {
        // your new doggy tricks
    }
}

Individual tests themselves start out like "it('should do such-and-so...". You can give the test whatever description you want, but generally you give it a brief explanation of what it should or shouldn't do. If you added more methods to Dog, you would add more tests within the "Dog" test description to test them.

describe("dog", function () {
    it('should be able to speak', function () {
        // the body of the speak test goes here
    }
    it('should be able to wag its tail', function () {
        // the body of the wag test goes here
    }
}

Our examples use should.js for writing test cases in Behavior Driven Development style. Should.js provides a bunch of cool assertions like foo.should.be.above(10) or baz.should.include('bar'), and so on. Check out the documentation for should.js here: https://github.com/visionmedia/should.js

    it('should be able to speak', function () {
        var doggysound = dog.speak();
        doggysound.should.equal('woof!');
    }
    it('should be able to wag its tail', function () {
        var wags = dog.wag(5);
        wags.should.be.above(4)
    }

Synch and Asynch Tests


These examples show an asynchronous testing approach. It's quite easy to run your tests in a synchronous way, though, by using the "done" callback which Mocha provides.


    it('should be able to speak', function (done) {
        var doggysound = dog.speak();
        doggysound.should.equal('woof!');
        done();
    }


Using the "done" callback means the test will complete before moving on to the next one.

For a slightly more advanced tutorial check out http://dailyjs.com/2011/12/08/mocha/. It has some great tips about setting up a package.json and Makefile to help with test automation, as well as writing synchronous and asynchronous tests.

Thursday, April 12, 2012

Ottawa Javascript Rolls Again

The Ottawa Javascript group emerged from hibernation to hold our first meetup of the year at TheCodeFactory on April 11th.  Here's a followup that I posted to the Ottawa Javascript Google group.

Thanks to Jon Abrams and Simon Kaegi who stepped in last night with a couple of impromptu demo's. Ben also sends his apologies for not being able to make it. I know lots of people were looking forward to the WebGL / Javascript demo so hopefully we will get him to come next time and demo something.

First of all Jon put together a great little web application that you can check out at http://wiqr.herokuapp.com/

Jon went into fairly low-level detail that provided some interesting points of discussion. One particularly good point was the use of environment variables to hold things that you don't want to (or shouldn't) hard-code, like database passwords or keys.

For newcomers it's easy to feel inundated by all the unfamiliar pieces when first looking at a node application. I recommend for people interested in the Express framework, check out the screencasts at http://expressjs.com/screencasts.html

For people who want a dead-simple introduction to node, I have a little blog post here that might be useful. http://51elliot.blogspot.ca/2011/07/simple-intro-to-nodejs-modules.html

Redis is a very popular database that's becoming a favorite among the NodeJS crowd. For a good introduction to it, check out http://try.redis-db.com

Finally Simon Kaegi's demo of the Orion development environment was a great example of how advanced web-based applications are becoming. If you missed it you can check out the Orion project here: http://www.eclipse.org/orion/

Dan L, Owain and Simon K volunteered to help with the planning and organization so the next meetup should be a good one. If you're interested in presenting something please drop one of us a line.

Some ideas are:
  • walk through the "try mongo", "try redis" or similar tutorial as a group, taking questions as we go 
  • show off a cool web application or technology that you found interesting and have a discussion around it 
  • demo your weekend project to a friendly group and get some feedback
I recommend we keep presentations to around 20 minutes max with 5-10
minutes at the end for questions. Feel free to make suggestions for future meetups, too.

Thanks again everyone.

Sunday, March 18, 2012

Wednesday, January 25, 2012

Simple Intro to NodeJS Module Scope

Update: Here are slides for this talk at OttawaJS: "Node.JS Module Patterns Using Simple Examples".

Update 2: More Node.JS Module Patterns - still fairly basic but more practical examples.

People often ask about scope and visibility in Node.JS modules. What's visible outside the module versus local to the module? How can you write a module that automatically exports an object? And so on.

Here are six examples showing different ways of defining things in Node.JS modules.  Not all of these are recommended but they will help explain how modules and their exports work, intuitively.

Exporting a global function

This module defines a global function called foo. By not putting var in front of the declaration of foo, foo is global. This is really not recommended. You should avoid polluting the global namespace.

// foo.js
foo = function () {
  console.log("foo!");
}


Here is an app that uses it.

// Module supplies global function foo()
require('./foo');
foo();

Exporting an anonymous function

This module exports an anonymous function.

// bar.js
module.exports = function() {
  console.log("bar!");
}


Here is an app that uses it.

// Module exports anonymous function
var bar = require('./bar');
bar();

Exporting a named function

This exports a function called fiz.

// fiz.js
exports.fiz = function() {
  console.log("fiz!");
}


Here is an app that uses it.

// Module exports function fiz()
var fiz = require('./fiz').fiz;
fiz();

Exporting an anonymous object

This exports an anonymous object.

// buz.js
var Buz = function() {}; 

Buz.prototype.log = function () {
  console.log("buz!");
};
module.exports = new Buz();


Here is an app that uses it.

// Module exports anonymous object
var buz = require('./buz');
buz.log();

Exporting a named object

This exports an object called Baz.

// baz.js
var Baz = function() {}; 

Baz.prototype.log = function () {
  console.log("baz!");
};

exports.Baz = new Baz();


Here is an app that uses it.

// Module exports object Baz
var baz = require('./baz').Baz;
baz.log();


Exporting an object prototype

This exports a prototype called Qux.

// qux.js
var Qux = function() {}; 
Qux.prototype.log = function () {
  console.log("qux!");
};
exports.Qux = Qux;

Here is an app that uses it.

// Module exports a prototype Qux
var Qux = require('./qux').Qux;
var qux = new Qux();
qux.log();

Thursday, January 5, 2012

The Global Power Shift

Paddy Ashdown's fantastic speech at TEDx Brussels, which was published today.  This is well worth watching for anyone interested in what is happening in global power structures and the end of the American century.  Absolutely brilliant talk, at once troubling and still inspirational.

Saturday, December 31, 2011

The Battle Path

Writing-On-Stone Provincial Park, Alberta, Canada

© 2012 Darren DeRidder

Monday, December 12, 2011

Productivity and Note-taking

I told a friend of mine that I wasn't really happy with the amount of time that gets taken up by Slack and "communication and sched...