Save time managing and deploying your node.js app

Nodejitsu has joined GoDaddy

We are excited to join GoDaddy to help spearhead their largest Node.js product: Website Builder. Please read our blog post to learn more about customer transition plans and our continued support for Open Source within the node community.

Want to know all the details?
Read the full blog post or read the GoDaddy Announcement.

Vows custom test runner

About the author

nodejitsu nodejitsu

Other popular posts

- Scaling Isomorphic Javascript Code - Keep a node.js server up with Forever - Package.json dependencies done right
- npm cheat sheet - 6 Must Have Node.js Modules

I recently ported an IRC bot that I wrote from Python to node.js and took the opportunity to try BDD for the first time. My results were very positive. BDD seems to play out a lot like a unittest, but with much more readability.

I used vows, a very well documented BDD library for node.js that has an amazing website and a helpful developer. The principle is that in a given test case, you have a topic. This topic is a specific facet of your program that you'd like to test.

In my example, I test two objects: the pattern, and the pattern list. In prose, its easy to say that "The pattern list is an array that contains objects. You can add something to it by registering something." The tests follow that almost exactly. The topic is the noun, a pattern list. For each clause describing it, you create a new test. There's a test to validate its an array, another to ensure it contains objects, and a third to check that when you register something, the list grows. All fairly straight forward.

The product of this is a very simple list of dots followed by the time it took to run and how many tests passed. You can pass some arguments, if you're using the vows command, and you'll get nice RSpec output. Very fancy.

What if we wanted something different? Perhaps a bit retro? Look no further than asciimo, which makes it quite easy to get ascii art with little effort. You can even throw in some color for fun.

var asciimo = require('/path/to/asciimo').Figlet,  
    colors = require('/path/to/colors');

asciimo.write('Test', 'drpepper', function(art) {  

Tying this into vows turns out not to be terribly difficult either. After some initial trouble getting custom test reporters registered, I was pointed the right way by cloudhead on #node.js, the author of vows. Turns out I was using an non-public API along with not exporting my test suite into a form that vows understood. Custom reporters only need to implement a report method which takes two arguments. From what I could tell, the second method wasn't used (at least not for standard test running), but the first argument provides a wealth of information about the test suite.

The first argument is a list whose first element is a string which is followed by an optional second item. The string seems to represent which portion of BDD's tree based structure you're on. The second element in the array is some structure describing the first argument. In the example of an actual test, it shows the test name and whether it passed (was honored) or failed, among other things. Some examples include:

[ 'subject', 'imbot patterns' ]
[ 'context', 'The pattern list' ]
[ 'vow'
   , { title: 'is an array'
     , context: 'The pattern list'
     , status: 'honored'
     , exception: null
[ 'end' ]
[ 'finish'
   , { honored: 6
     , broken: 0
     , errored: 0
     , pending: 0
     , total: 6
     , time: 0.007

Based on this, we really only need to pay attention for the 'finish' message to be passed. For instance, a simple custom reporter might look like:

var sys = require('sys');  
var colors = require('../../colors.js/colors');  
var asciimo = require('../../asciimo/lib/asciimo').Figlet;  
var report_font = 'drpepper'; = function (data, s) {  
  if (data[0] == 'vow') {
  if (data[0] == 'finish') {
    sys.print('\n'); // clear a newline
    var result = 'failed';
    if (data[1].broken == 0 && data[1].errored == 0) {
      result = 'passed';
    asciimo.write(result, report_font, function (art) {
        if (result  == 'passed')
        var output = '';
        output += 'Passed: ' + data[1].honored + ' \n';
        output += 'Failed: ' + data[1].broken + ' \n';
        output += 'Errored: ' + data[1].errored + ' \n';
        output += 'in ' + data[1].time + 'sec';

And the result of that is an ascii art of the words passed or failed in green or red respectively, followed by how many things passed and failed and the total execution time. Not too shabby for under 30 lines of code. For the sake of another example, below is another simple example using the say.js and play.js libraries.

// using say.js
var say = require('say'); = function (data, s) {  
  if (data[0] == 'finish') {
      var result = 'You had ' + data[1].broken +' broken, ' 
          + data[1].errored + ' errored, and '
          + data[1].honored + ' passing tests.';
    say.speak('Alex', result);

// using play.js
var play = require('play'); = function (data, s) {  
    if (data[0] == 'finish') {
        if (data[1].broken + data[1].errored > 0) {
        } else {