A light-weight RSpec-esque testing framework designed and built specifically for NodeJS.
- Ground-up support for NodeJS convention callbacks
- Only one test running at a time
- No global variables
- RSpec style syntactic sugar
- Nested contexts
- Easy to use setup/teardown
- Subject helpers
- Pluggable mocking support
- Native assertions
- Easy to extend or replace the default assertions
- Multiple output formatters on the same test run (not yet implemented)
If you'd like to contribute
- Fork the repository on github
- Make your changes
- Run the unit tests
- Run the cucumber tests with cucumber -p all
- Push back to github and send me a pull request
If you're fixing a bug, please add a testcase to prove it was broken and is fixed, if you're adding a new feature, please add cucumber feature file for it.
To be able to run cucumber, you'll need Ruby and Bundler installed, then do bundle install.
Via npm:
npm install nodespec
Or clone directly from github:
git clone git://github.com/glenjamin/nodespec cd nodespec npm link
Require the module into test files to use it:
var nodespec = require('nodespec');
And then at the end of each test file:
nodespec.exec();
Simple spec:
nodespec.describe("Addition", function() { this.example("1 + 1 = 2", function() { this.assert.equal(1 + 1, 2); }); });
Simple async spec:
nodespec.describe("nextTick", function() { // Accept 1 argument in the definition for an async test this.example("fires the callback", function(test) { this.expect(2); this.assert.strictEqual(this, test); process.nextTick(function() { this.assert.strictNotEqual(this, test); // async tests must call test.done() test.done(); }); }); });
Before/After Hooks:
// Hooks share `this` with tests, but it's rebuilt each time nodespec.describe("Some databasey test", function() { this.before(function(hook) { this.assert.strictEqual(this, hook); db_connect(function (err, conn) { hook.db = conn; hook.db.start_transaction(function(err, tx) { hook.tx = tx; hook.done(); }); }); }); this.after(function() { this.tx.rollback(); }); this.example("database interaction", function(test) { test.expect(2); test.db.insert({field: 1}, function(err, result) { test.assert.strictEqual(result.affected, 1); test.db.get(function(err, result) { test.assert.strictEqual(result.field, 1); test.done(); }); }); }); });
Nested contexts with subject:
nodespec.describe("My Server", function() { // This function is executed once when `this.server` is accessed this.subject('server', function() { return new Server(1337); }); this.context("Strict Mode", function() { this.before(function() { this.server.use_strict_mode(); }); this.example("invalid request fails", function(test) { test.expect(1); test.server.request('invalid', function(err, result) { test.assert.notEqual(err, null); test.done(); }); }); }); this.context("Not Strict Mode", function() { this.before(function() { this.server.dont_use_strict_mode(); }); this.example("invalid request fails silently", function(test) { test.expect(2); test.server.request('invalid', function(err, result) { test.assert.equal(err, null); test.assert.equal(result, null); test.done(); }); }); }); });
Copyright © 2011 The NodeSpec Authors. See LICENSE and AUTHORS for details.