Sunday, November 3, 2013

Introduction to Nodejs and Mocha

"All the world's a stage,
And all the men and women merely players;

They have their exits and their entrances,
And one man in his time plays many part
s"
-- Shakespeare, As You Like It
Act II, Scene VII, Lines 140.2 - 143

Prelude


Places, places, the show is about to begin.  Javascript has hit the big time!  Javascript has gone from a way to annoy, to a full blown language and we have Node.js to thank (well maybe AJAX, but Node.js helped pushed me over the edge).  If you are like me, you had written off Javascript as an annoyance that Web Programmers had to deal with, but now thanks to Node.js we can all find a use for Javascript.

Now do not get me wrong Javascript has more than its fair share of bad parts, but the more I use it, the more I like it.  It has just enough of functional elements to make me happy and yet it has enough object oriented elements to allow for any C#, Java, or Ruby programmer to feel at home.  Plus Node.js' package management system (npm) is simply wonderful.

Installing Node.js


To install Node.js head over to http://www.nodejs.org/ and install the correct installation for your system.


I just stuck with the default install options and have had no problems.

Hello World


The default installation gave me a Node.js folder on my start menu, launch the Node.js command prompt.



This will bring up a command prompt.

Run Node.js by typing, node at the prompt.  This will bring up a REPL (read evaluate print loop), you can use the REPL to try things out.  I normally have a REPL open along with a mocha --watch when I am programming with Node.js.

To write a Hello World in Node.js simply enter console.log("Hello World!); on the REPL.  Boom, you now have done Hello World using Node.js!


Hit Ctrl+c twice to exit.  O-if you are wondering, the undefined you see after Hello World! is the value of the result of the call to console.log.


TDD using Mocha

With Hello World out of the way, we can legally do something more interesting.  Lets download Mocha, which is the best testing framework I've found for working with Node.js.  To download and install Mocha use the Node package by running the Node Package Manager you installed when you installed Node.js by running the following at the command prompt: npm install -g mocha

npm install -g mocha, will download and install globally (that is what the -g means) the Mocha testing framework.



Mocha is a testing framework which allows for either the should BDD style or the assert Unit test style, personally I am starting to prefer the BDD style, but to each their own.

Let's create our first Node.js project!

In order for Mocha to be able to work you need a test directory.  Personally I like this structure for my Node.js projects.

  • project-name
    • src
      • source-file.js
    • test
      • file-spec.js

Nothing that I know of will force you to have a src directory, but I find it cleaner to have it (maybe because I am an old Java programmer).  Let's make the project structure, run the follow commands (assuming you are using Windows or an Unix based machine (I believe this will work on a Mac)):

mkdir  kata
cd kata
mkdir helloer
cd helloer
mkdir src
mkdir test


This will give you a kata directory and your first kata helloer.


Fire up your favorite text editor, I have really taken to Sublime Text lately, so that is what I will be using.

In the src directory create a file called helloer.js leave it empty for now.  In the test directory we'll create a file called helloerSpec.js with the following line of code.

var sut = require("../src/helloer");

This line will create a variable called sut (system under test) which will use to test the helloer code.  Not the syntax on the require, you need to use a .. to say go down a directory and the /src/helloer says where to find the helloer functions.

Let's run this with Mocha from the command prompt type mocha
You should see output like the following (if not you may have the directory structure different than what I have or you have something typed wrong).


Now let's actually do something!

First add should to your system by using the following in the helloer directory:

npm install should


This will install the should module which we'll us in our test file.

In the helloerSpec.js file add the following and save:

var sut = require("../src/helloer"),
 should = require("should");

 describe("helloer will say hello to whatever you pass in", function(){
  it("Nothing will just say hello", function(){
  sut.helloer().should.equal("Hello ");
  });
 });

The describe is a high level grouping for our tests, the it is our test case, in this case we are saying we want a function that when given nothing will produce the string "Hello ".

From the command line run mocha --watch

This will start a continuous testing environment (if this is your first time using one, it will change the way you write your code).


Congratulations you have your first failing test in a continuous testing environment with Mocha!  Now let's make the failing test pass.

Add the following lines to the helloer.js file to get the failing test to pass.

var helloer = function(){
return "Hello ";
};

exports.helloer = helloer;

As soon as you save the continuous testing environment with Mocha will pick up on the changes and rerun the tests.


The exports gives a list of things (variables, functions, objects, ...) to expose.  In this case we are exposing helloer, note that the name on exports is will the caller sees not the local name.

When I do TDD I like to use as little amount of code as I can to get the test to pass (like playing golf).  I find that this leads to better code.  As the old saying goes, the code that you do not write has zero bugs.

Let's write our next failing test.

We'll say hello to Mike using the following code (in bold) to our helloerSpec.js file:

var sut = require("../src/helloer"),
 should = require("should");

 describe("helloer will say hello to whatever you pass in", function(){
  it("Nothing will just say hello", function(){
  sut.helloer().should.equal("Hello ");
  });

  it("Given Mike, hello will hello Mike", function(){
  sut.helloer("Mike").should.equal("Hello Mike");
  });
 });



Mocha will tells us that we have one failing test and that it is failing because it is receiving "Hello " and is expecting "Hello Mike".

Let's make this pass.

Add the following (in bold) to helloer.js:

var helloer = function(name){
return "Hello " + (name ? name : "");
};

exports.helloer = helloer;


The line (name ? name : "") may seem odd, but remember in Javascript the string value of undefined is "undefined" when found on the other side of a concatenation (+ with two strings), yeah odd.


Well, believe it or not we are done, but let's add in some more tests to make sure.

var sut = require("../src/helloer"),
 should = require("should");

 describe("helloer will say hello to whatever you pass in", function(){
  it("Nothing will just say hello", function(){
  sut.helloer().should.equal("Hello ");
  });

  it("Given Mike, hello will hello Mike", function(){
  sut.helloer("Mike").should.equal("Hello Mike");
  });

  it("Given 5, hello will hello 5", function(){
  sut.helloer(5).should.equal("Hello 5");
  });
 });



Congratulations, we have just finished some TDD with Node.js and Mocha.

In case you missed it, full files

src\helloer.js

var helloer = function(name){
return "Hello " + (name ? name : "");
};

exports.helloer = helloer;


test\helloerSpec.js

var sut = require("../src/helloer"),
 should = require("should");

 describe("helloer will say hello to whatever you pass in", function(){
  it("Nothing will just say hello", function(){
  sut.helloer().should.equal("Hello ");
  });

  it("Given Mike, hello will hello Mike", function(){
  sut.helloer("Mike").should.equal("Hello Mike");
  });

  it("Given 5, hello will hello 5", function(){
  sut.helloer(5).should.equal("Hello 5");
  });
 });