12/31/2012

Using Jasmine-Node to Test Your Node Server

I've been working with Jasmine to test my client side code, however, my code extends beyond the client. I am working on server side JavaScript using Node.js. It would be great to apply my test driven process to my node server as well. Luckily, the Node community is large, helpful, and talented. Jasmine has been ported to the server with the jasmine-node project by Miško Hevery (https://github.com/mhevery/jasmine-node). The github readme summarizes the process of setting up jasmine-node, so this post will expound on those points.

The jasmine-node project is installed with the standard npm install process, and the author suggests using the global switch. Jasmine-node is started from the command line. The jasmine runner is invoked by using "jasmine-node path_to_testing_directory" command. Jasmine-node will recurse through nested directories and will run all test files that end with .spec.js.

There is a lot of power in that implementation. Invoking jasmine-node on the command line means that it can be automated. Build servers such as Jenkins can be configured to run the unit tests automatically with each build. Node.js can also write to the command line, which means you can use a Node server to test your Node server. An example scenario might be to run tests on server startup or when the configuration changes. Another scenario might be to use one Node server to monitor the health of other Node servers, or itself, through running unit tests and then reporting findings. This would be useful in environments where an additional build server is not available or has limited access.

The code for the unit test is identical to a unit test on a client. The one huge difference between the client and the server is the need to make http requests of a server. If we are testing a server, we want to test that a server operation is returning the expected response to an external caller. The tests will need to make a request of the server and run the expect clause against the result.

A simple test example is to have the server issue a request to a url it handles. The jasmine-node suite runs under a node process giving it access to all the node packages. We can get the code we need to make a request by requiring the http or https packages at the beginning of the spec file.

var request = require ('http');
The http package in node will provide the request and the http.get shortcut functions that are needed to tell node to reach out to a url.

Now that the request can be sent, how does jasmine-node know to wait for a response? The author and contributors of jasmine-node thought of this and provided a mechanism for us: we can use a done callback function. Unlike a regular jasmine function, the callback function for the it clause can pass in a function. Call the passed in function when the asynchronous part of the request is complete, and the test will finish. This is a typical jasmine unit test:

it('Server should respond to /', function (){
    request.get('http://test_server', function(response){
        expect(response.statusCode).toBe(200);
    });
});​

This is the same unit test using the asynchronous process provided by jasmine-node. Notice the inclusion of the done parameter in the it clause's callback. The test will only complete when the async process calls the done function.

it('Server should respond to /', function (done){
    request.get('http://test_server', function(response){
        expect(response.statusCode).toBe(200);
        done();
    });
});​

A simple install, regular node tooling, and the inclusion of the done function bring test driven development to the server. Ain't the Node community great.