Expresso - TDD Framework For NodeJS

A few days ago I rolled out a new TDD framework for Node. Although node has many BDD and TDD frameworks to offer, I wanted a simple, fast, and thin layer built upon node’s core assert module. Among other features I wanted an executable that I could re-use for my future node projects, this project is named expresso.

Performance

Although expresso stands short in the reporting department, tests are not run serially, which means synchronous and asynchronous tests alike will run insanely quick. Even with hundreds of “heavy” async tests I have yet to see them take more than a half a second to execute.

Writing Tests

A test simply consists of an exported function as shown below, which passing the assert module as the first argument, however you can require it at the top of the file if you prefer:

module.exports = {
    'test version': function(assert){
        assert.ok(/^\d+\.\d+\.\d+$/.test(connect.version), 'Test framework version format');
    }
}

Executable Test Runner

The test runner packaged with expresso is aptly named…. expresso!. To get started running tests you can simply shove your *.test.js files in the ./test directory, and execute:

$ expresso

If that is not to your liking, you can also customize the glob pattern used for matching test files:

$ expresso test/*.js

On top of that you can continue passing files, if you want to get more specific:

$ expresso test/{a,b}.test.js test/d.test.js

Output

For output I took the unix “if nothing when wrong, don’t output anything” approach, however for sanity if all tests pass you will see the following output:

100% passes

Exceptions will be reported in a clean fashion, also colored with ansi escape sequences unless the —boring flag is present:

   1) test failures: AssertionError: true == false
at /Users/tjholowaychuk/projects/expresso/test/helpers.a.test.js:27:16
at next (/usr/local/bin/expresso:294:17)
at next (/usr/local/bin/expresso:300:13)
at next (/usr/local/bin/expresso:300:13)
at next (/usr/local/bin/expresso:300:13)
at runSuite (/usr/local/bin/expresso:302:6)
at /usr/local/bin/expresso:249:43
at Array.forEach (native)
at run (/usr/local/bin/expresso:248:15)
at Object.<anonymous> (/usr/local/bin/expresso:307:13)

Test Coverage

Last but not least, we have the test coverage support. This is another feature that I really wanted in, and although this project too a little less than an hour, it is a great feature to have implemented. For test coverage I use the node-jscoverage project which is nearly identical to the regular browser project, however I tweaked the C instrumentation code to work with SSJS and node.

When testing libraries it is a good idea to abstract the idea of where the library files came from, so I would suggest typically doing something like this in your test file:

 var mylib = require('mylib');

over:

var mylib = require('./../lib/mylib');

The expresso exectuable allows us to unshift out library directory onto require.paths so that it is available to our tests:

$ expresso -I lib

To add test coverage, we can run the exact same command, however passing the —cov switch, which will generate ./lib-cov and utilize the newly instrumented version of the library during runtime:

$ expresso -I lib --cov

If you have a complex recipe I recommend creating a Makefile (or similar) so that users can simply execute:

$ make test

Oh, and you are probably wondering what the test coverage output currently looks like :) here you go:

CI Friendly

To become CI friendly your test runner must exit with a > 0 exit status when one or more failures occur. Both for CI server support, and for us developers the exit status of expresso is simply the number of failures which occurred.

More Information

To read more about the project and to get started installing it, visit the Github page.

Notes

  1. tjholowaychuk posted this