Hello World – Unit Test

After much hair pulling and numerous searches I’ve settled on using Mocha as the test framework. Since I had downloaded WebStorm I thought I’d use the inbuilt JsTestDriver framework – but looks like I can’t test the request/response cycle with it (or maybe I can; Mocha is just a whole lot easier..)

The structure of the test

In order to test the code described in the previous article, I had to refactor the original production code – I’ll show that later. Let me first walk you through the process of setting up the test.

At its base, the test needs to do the following:

  1. Send the request
  2. Verify the response.

Since I am setting the response status as well as the response data, we can further break up the ‘Verify response’ part into verifying the response status and verifying the response data. The test now looks like this:

  1. Send the request
  2. Verify the response status.
  3. Verify the response data.

However, in order to send the request and receive a response, the server needs to be up and running. Which means that the test now needs to do the following

  1. Start the server
  2. Send the request
  3. Verify the response status.
  4. Verify the response data.

Since the test is setting up the server, the test should also tear it down. With that in mind, the test will finally look like this:

  1. Start the server
  2. Send the request
  3. Verify the response status.
  4. Verify the response data.
  5. Tear down the server.

Restructuring the Hello World code

The Hello World code looked like this. In this case the server started automatically.

var http = require(“http”);
http.createServer(function(request, response) {
response.writeHead(200, {“Content-Type”: “text/plain”});
response.write(“Hello World”);
response.end();
}).listen(8888);

Now, since the test needs to start/stop the server, we will refactor the code to look like this.

var http = require(“http”);
var server = http.createServer(function (req, res) {
console.log(‘Received request’);
res.writeHead(200, { ‘Content-Type’: ‘text/plain’ });
res.write(‘Hello World!\n’);
res.end()
});
var listen = function (port) {
server.listen(port, function() {
console.log(‘Listening on port: ‘ + port);
});
};
var close = function () {
server.close(function(){
console.log(‘Closing connection!’);
});
};
module.exports.listen = listen;
module.exports.close = close;

Observe the last 2 lines. In order for the test to access the listen and close functions we need to export them. Here’s a great post on how exports work.

Setting up the test code

With the Hello World code out of the way, let us now move onto the test code. In the beginning I mentioned that I’d be using Mocha as the test framework. For those of you’ll who’ve been following the previous post and have decided to use WebStorm, here’s  how you can hook up Mocha in WebStorm – it’s real easy. Once you go through the video you’ll also figure out how to get rid of all those ugly squiggles that show up in the IDE . Those squiggles are WebStorm’s way of letting you know that there is something amiss. When you take care of them,  you should see a green rectangle in the upper right-hand corner of the IDE indicating that WebStorm is happy!

Side note on how to fix all the WebStorm inspection issues

As you’d have already seen in the video, most of the issues in the code are because you have not included the required JavaScript libraries. For the purposes of this demo, you need to include the following libraries. Refer to this documentation to find out how to configure JavaScript libraries in WebStorm.

ExternalLibraries
Mocha – Test framework
Should – For all the describe/it functions (in the demo we are only using the it function)
Node.js Core Modules – Includes all the core modules such as http
Node – Now this one is kind of strange. I had to include it in order to remove the inspection warnings from my assert statements. I would imagine that assert would have been a part of should or the Node Core modules – note to self: investigate this.

With the Mocha set up complete, here’s what the test code will look like

var server = require(‘../src/server.js’);
var http = require(‘http’);
var assert = require(‘assert’);
before(function () {
server.listen(8888);
});
after(function () {
server.close();
});
it(‘should return 200’, function (done) {
http.get(‘http://localhost:8888’, function (res) {
assert.equal(res.statusCode, ‘200’);
done();
});
});
it(‘should say Hello World\n’, function (done) {
http.get(‘http://localhost:8888’, function (res) {
var data = ”;
res.on(‘data’, function (chunk) {
data += chunk;
});
res.on(‘end’, function () {
assert.equal(data, “Hello World!\n”);
done();
});
});
});

Walking through the test code

var server = require(‘../src/server.js’);
var http = require(‘http’);
var assert = require(‘assert’);

We start by importing the various modules. The server variable is used to import the module that we created in the Hello World code. The assert variable is used to import the assert module and is used for assertions in our test cases.

before(function () {
server.listen(8888);
});
after(function () {
server.close();
});

The before and after functions are hooks provided by the Mocha framework. We are instructing Mocha to start the server before the execution of any test and stop the server once all the test cases have been executed.

Since we exported listen and close we are able to access them in these functions!

it(‘should return 200’, function (done) {
http.get(‘http://localhost:8888’, function (res) {
assert.equal(res.statusCode, ‘200’);
done();
});
});

It is Mocha’s implementation of a test case. Here we describe what the test case should be doing; this is pretty neat because once you run the test in the IDE the description shows up in the test results window which makes it easy to read – contrasting this to .Net where I had to give the test functions descriptive names.

The test itself is straight-forward. It makes a get request on the same port that the server is listening. Since the Hello World code returns a 200 status code, the test checks for that. The only interesting thing to note here is the done(). Per the Mocha documentation

“…Testing asynchronous code with Mocha could not be simpler! Simply invoke the callback when your test is complete. By adding a callback (usually named done) to it() Mocha will know that it should wait for completion…”

Since the get function is asynchronous putting the done() in there instructs Mocha to wait for completion. if you didn’t put the done(), the test would complete without ever receiving the request.

it(‘should say Hello World\n’, function (done) {
http.get(‘http://localhost:8888’, function (res) {
var data = ”;
res.on(‘data’, function (chunk) {
data += chunk;
});
res.on(‘end’, function () {
assert.equal(data, “Hello World!\n”);
done();
});
});
});

In order to validate the response data, the test code handles the data and the end event on the response object. It is interesting to note that the response is chunked. Once again, we add done() to instruct Mocha that it should wait for completion.

Now if you run the test cases, you should see both of them pass.

The code is available here. Till next time….

Advertisements

Hello World with Node JS

My first experience with web pages was through HTML. I remember I was completely baffled by how seemingly cryptic text transformed itself into structured data.

A long time has passed since then. I’ve had some experience working on various parts of the web stack; but so far all this has been through the use of Microsoft technologies, my interactions with the open source world have been few and far between. And although I love the MS stack, of late, I’ve felt the need to know what’s out there; chocolatey, Node Js, NPM, Mongo, Heroku, Shippable, etc. The sheer volume of names is overwhelming, let alone choosing the right tool for the job.

This is my endeavor to document the process of adopting a new technology stack to build a functional app. This is what I plan to use:

  • Node. Js – Server side coding language
  • WebStorm – JavaScript IDE
  • Mongo – Database
  • Mongoose – ORM      layer
  • Shippable – CI      platform
  • Heroku – Cloud

I’m an absolute N00B and my intention here is that the hurdles I encounter are probably what others in my position would face. There’s a lot of great material on all the above topics out there – THIS IS NOT THAT. This is exactly what I say it is – a newbie’s experience at using a new technology stack.

The ubiquitous Hello World application

I am working on a Windows 8 machine.

Setting up the environment

  • Go to http://nodejs.org/ and install the latest version.
  • Now navigate to the Node installation folder – in my case it was C:\Users\viswka\Documents\nodejs – and install express (http://expressjs.com/) by running the following command:

npm install -g express@2.5.8

Image

The npm command is run with the “-g” flavor. Read more about global vs. local installations here: http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/ .

  • Express is the HTTP server (there are others as well) used for Node development.
    *Using Node, means that server administration as well as application development is the responsibility of the application developer and both these can be achieved using JavaScript
  • At this point of time, I believe I have everything I need to create the Hello World app – everything but an IDE – Visual Studio has spoiled me rotten. Here’s a good blog on the choice of IDE available for Windows developers – http://beletsky.net/2012/06/starting-up-nodejs-development-on.html . I decided to use Web Storm (the free version for now) since I’ve used other JetBrains products in the past and am comfortable with it.

Create the ‘Hello World’ application

  • Start WebStorm and create a new project; I decided to go with the ‘Empty project’ template for now – it looks like there are others like ‘Boilerplate and Express, I’ll delve into those later.
  • Create a new server.js file and add the following code, which will create a basic HTTP server.
var http = require(“http”);
http.createServer(function(request, response) {
response.writeHead(200, {“Content-Type”: “text/plain”});
response.write(“Hello World”);
response.end();
}).listen(8888);

Publishing a gist

Right click the project and click on “Create Gist…”. If you have a github account you will see the code pushed to github; if not create a github account and repeat this step.

You can access my code here : https://gist.github.com/ViswanathKari/9166632