Easy unit testing in node.js, based on the assert module.
$ npm install nodeunit
Simple syntax, powerful tools. Nodeunit provides easy async unit testing for node.js and the browser.
The project is very stale. We've kept it working on new versions of node, and sometimes merged small PRs that help teams relying on nodeunit.
Nodeunit was the arguably first testing framework developed for node. It was very useful at the time, but there's an overwhelming number of other worthwhile testing solutions out there that are actively maintained. tap, ava, tape, mocha, jasmine, jest, ... the list goes on and on.
If Nodeunit were truly bringing some different philosophy to the testing scene I'd say yes effort should be made to shore up it's development, but given how many other great options there are out there, a benefit of letting it atrophy is it's one less choice people have to make when choosing a testing solution. You are strongly encouraged to check out other more modern testing options.
Also, check out gerad's nodeunit-dsl project, which implements a 'pretty dsl on top of nodeunit'.
More contributor information can be found in the CONTRIBUTORS.md file.
Here is an example unit test module:
exports.testSomething = function(test) {
test.expect(1);
test.ok(true, "this assertion should pass");
test.done();
};
exports.testSomethingElse = function(test) {
test.ok(false, "this assertion should fail");
test.done();
};
When run using the included test runner, this will output the following:
There are two options for installing nodeunit:
Clone / download nodeunit from github, then:
make && sudo make install
Install via npm:
npm install nodeunit -g
Nodeunit uses the functions available in the node.js assert module:
Nodeunit also provides the following functions within tests:
Nodeunit aims to be simple and easy to learn. This is achieved through using existing structures (such as node.js modules) to maximum effect, and reducing the API where possible, to make it easier to digest.
Tests are simply exported from a module, but they are still run in the order they are defined.
Note: Users of old nodeunit versions may remember using ok
, equals
and
same
in the style of qunit, instead of the assert functions above. These
functions still exist for backwards compatibility, and are simply aliases to
their assert module counterparts.
When testing asynchronous code, there are a number of sharp edges to watch out for. Thankfully, nodeunit is designed to help you avoid as many of these pitfalls as possible. For the most part, testing asynchronous code in nodeunit just works.
While running tests in parallel seems like a good idea for speeding up your test suite, in practice I've found it means writing much more complicated tests. Because of node's module cache, running tests in parallel means mocking and stubbing is pretty much impossible. One of the nicest things about testing in javascript is the ease of doing stubs:
var _readFile = fs.readFile;
fs.readFile = function(path, callback) {
// it's a stub!
};
// test function that uses fs.readFile
// we're done
fs.readFile = _readFile;
You cannot do this when running tests in parallel. In order to keep testing as simple as possible, nodeunit avoids it. Thankfully, most unit-test suites run fast anyway.
When testing async code it's important that tests end at the correct point, not
just after a given number of assertions. Otherwise your tests can run short,
ending before all assertions have completed. It's important to detect too
many assertions as well as too few. Combining explicit ending of tests with
an expected number of assertions helps to avoid false test passes, so be sure
to use the test.expect()
method at the start of your test functions, and
test.done()
when finished.
Nodeunit allows the nesting of test functions:
exports.test1 = function (test) {
...
}
exports.group = {
test2: function (test) {
...
},
test3: function (test) {
...
}
}
This would be run as:
test1
group - test2
group - test3
Using these groups, Nodeunit allows you to define a setUp
function, which is
run before each test, and a tearDown
function, which is run after each test
calls test.done()
:
module.exports = {
setUp: function (callback) {
this.foo = 'bar';
callback();
},
tearDown: function (callback) {
// clean up
callback();
},
test1: function (test) {
test.equals(this.foo, 'bar');
test.done();
}
};
In this way, it's possible to have multiple groups of tests in a module, each group with its own setUp and tearDown functions.
Nodeunit comes with a basic command-line test runner, which can be installed
using sudo make install
. Example usage:
nodeunit testmodule1.js testfolder [...]
If no entry file specified, test
defaults.
The default test reporter uses color output, because I think that's more fun :) I intend to add a no-color option in future. To give you a feeling of the fun you'll be having writing tests, lets fix the example at the start of the README:
Ahhh, Doesn't that feel better?
When using the included test runner, it will exit using the failed number of assertions as the exit code. This means it exits with 0 when all tests pass.
Nodeunit tests can also be run inside the browser. For example usage, see the examples/browser folder. The basic syntax is as follows:
test.html
<html>
<head>
<title>Example Test Suite</title>
<link rel="stylesheet" href="nodeunit.css" type="text/css" />
<script src="nodeunit.js"></script>
<script src="suite1.js"></script>
<script src="suite2.js"></script>
</head>
<body>
<h1 id="nodeunit-header">Example Test Suite</h1>
<script>
nodeunit.run({
'Suite One': suite1,
'Suite Two': suite2
});
</script>
</body>
</html>
Here, suite1
and suite2
are just object literals containing test functions
or groups, as would be returned if you did require('test-suite')
in node.js:
suite1.js
this.suite1 = {
'example test': function (test) {
test.ok(true, 'everything is ok');
test.done();
}
};
If you wish to use a commonjs format for your test suites (using exports), it is up to you to define the commonjs tools for the browser. There are a number of alternatives and it's important it fits with your existing code, which is why nodeunit does not currently provide this out of the box.
In the example above, the tests will run when the page is loaded.
The browser-version of nodeunit.js is created in dist/browser when you do, make browser
. You'll need UglifyJS installed in
order for it to automatically create nodeunit.min.js.
If you don't want people to have to install the nodeunit command-line tool, you'll want to create a script that runs the tests for your project with the correct require paths set up. Here's an example test script, that assumes you have nodeunit in a suitably located node_modules directory.
#!/usr/bin/env node
var reporter = require('nodeunit').reporters.default;
reporter.run(['test']);
If you're using git, you might find it useful to include nodeunit as a submodule. Using submodules makes it easy for developers to download nodeunit and run your test suite, without cluttering up your repository with the source code. To add nodeunit as a git submodule do the following:
git submodule add git://github.com/caolan/nodeunit.git node_modules/nodeunit
This will add nodeunit to the node_modules folder of your project. Now, when cloning the repository, nodeunit can be downloaded by doing the following:
git submodule init
git submodule update
Let's update the test script above with a helpful hint on how to get nodeunit, if it's missing:
#!/usr/bin/env node
try {
var reporter = require('nodeunit').reporters.default;
}
catch(e) {
console.log("Cannot find nodeunit module.");
console.log("You can download submodules for this project by doing:");
console.log("");
console.log(" git submodule init");
console.log(" git submodule update");
console.log("");
process.exit();
}
process.chdir(__dirname);
reporter.run(['test']);
Now if someone attempts to run your test suite without nodeunit installed they will be prompted to download the submodules for your project.
Nodeunit exports runTest(fn, options), runModule(mod, options) and runFiles(paths, options). You'll most likely want to run test suites from files, which can be done using the latter function. The options argument can contain callbacks which run during testing. Nodeunit provides the following callbacks:
The assertion object:
The assertionList object:
For a reference implementation of a test reporter, see lib/reporters/default.js in the nodeunit project directory.
This is a function which evaluates JavaScript files in a sandbox and returns the context. The sandbox function can be used for testing client-side code or private un-exported functions within a module.
var sandbox = require('nodeunit').utils.sandbox;
var example = sandbox('example.js');
sandbox(files, sandbox) - Evaluates JavaScript files in a sandbox, returning the context. The first argument can either be a single filename or an array of filenames. If multiple filenames are given their contents are concatenated before evaluation. The second argument is an optional context to use for the sandbox.
Note: When working with the sandbox if your script depends on outside sources
(i.e. using require
) then you will want to pass that into the optional
context when setting up the sandbox.
var sandbox = require('nodeunit').utils.sandbox;
// pass in some node globals
var box_globals = {
// Passing module.exports into the sandbox will give your code access to it.
module: {exports: exports},
// Passing require into the sandbox will give your code access to use it AND
// will share the cache with modules already required from outside the sandbox.
require: require,
// Passing console into the sandbox will give your code access to it
console: console
};
var example = sandbox('example.js', box_globals);
The tests for nodeunit are written using nodeunit itself as the test framework. However, the module test-base.js first does some basic tests using the assert module to ensure that test functions are actually run, and a basic level of nodeunit functionality is available.
To run the nodeunit tests do:
make test
Note: There was a bug in node v0.2.0 causing the tests to hang, upgrading to v0.2.1 fixes this.
The default reporter is readable for human but not for machine analysis. When you want to analyze the output of nodeunit, use machineout reporter and you will get
There is nodeunit.vim so you can use nodeunit with VIM.
That compiler uses machineout reporter and it is useful to use with vim-makegreen.
Contributions to the project are most welcome, so feel free to fork and improve.
When submitting a pull request, please run make lint
first to ensure
we're following a consistent coding style.
© 2010 - cnpmjs.org x YWFE | Home | YWFE