Port of QUnit unit testing framework to nodejs
Switch branches/tags
Nothing to show
Pull request Compare This branch is 173 commits behind qunitjs:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.


This is a port of QUnit unit testing framework to nodejs



  • the simplest API of the world :)
  • 100% identical API for client and node (passing all unit tests from QUnit)
  • simple asynchronous testing
  • tests inside of one testfile run synchronous, but every testfile runs async
  • tests from each file run in its own spawned node instance
  • usage via CLI or testrunner
  • uses the assert module
  • test coverage via http://siliconforks.com/jscoverage


To install the latest release:

npm install qunit

To install the latest stable release

npm install qunit@stable

At this moment the latest release depends on the 0.5.x (UNSTABLE) series of node. Install qunit@stable unless you are prepared to upgrade to the unstable node. See https://github.com/joyent/node/issues/search?q=unstable for many issues with using the unstable releases.




// Add a test to run.
test( name, expected, test )

// Add an asynchronous test to run. The test must include a call to start().
asyncTest( name, expected, test )

// Specify how many assertions are expected to run within a test.
expect( amount );

// Separate tests into modules.
module( name, lifecycle )


// A boolean assertion, equivalent to JUnit's assertTrue. Passes if the first argument is truthy.
ok( state, message )

// A comparison assertion, equivalent to JUnit's assertEquals. Uses "==".
equals( actual, expected, message )

// A comparison assertion. Uses "===".
strictEqual( actual, expected, message )

// A deep recursive comparison assertion, working on primitive types, arrays and objects.
same( actual, expected, message )

// Assertion to test if a callback throws an exception when run.
raises( actual, message )

Asynchronous Testing

// Start running tests again after the testrunner was stopped.

// Stop the testrunner to wait to async tests to run. Call start() to continue.
stop( timeout )


Command line

Some usage examples, read full cli api doc using "--help":

$ qunit -h

$ qunit -c ./code.js -t ./tests.js

$ qunit -c ./code.js -t ./tests.js -p /path/for/require /path1/for/require --cov false

By default, code and dependencies are added to the global scope. To specify requiring them into a namespace object, prefix the path or module name with the variable name to be used for the namespace object, followed by a colon:

$ qunit -c code:./code.js -d utils:utilmodule -r ./time.js

via api

var testrunner = require( "qunit" );


    errorsOnly: false, // set it to true if you want to report only errors
    errorStack: true, // set it to false if you want to get error stack in report
    summary: true, // print a summary about all tested stuff after finish
    coverage: true, // display coverage
    paths: null // add paths to require of test environment

// to change any option - change it :)

testrunner.options.optionName = value;

// one code and tests file
    code: "/path/to/your/code.js",
    tests: "/path/to/your/tests.js"

// require code into a namespace object, rather than globally
    code: {path: "/path/to/your/code.js", namespace: "code"},
    tests: "/path/to/your/tests.js"

// one code and multiple tests file
    code: "/path/to/your/code.js",
    tests: ["/path/to/your/tests.js", "/path/to/your/tests1.js"]

// array of code and test files
        code: "/path/to/your/code.js",
        tests: "/path/to/your/tests.js"
        code: "/path/to/your/code.js",
        tests: "/path/to/your/tests.js"

// using testrunner callback
    code: "/path/to/your/code.js",
    tests: "/path/to/your/tests.js"
}, function( report ) {

// specify dependency
    deps: "/path/to/your/dependency.js",
    code: "/path/to/your/code.js",
    tests: "/path/to/your/tests.js"

// dependencies can be modules or files
    deps: "modulename",
    code: "/path/to/your/code.js",
    tests: "/path/to/your/tests.js"

// dependencies can required into a namespace object
    deps: {path: "utilmodule", namespace: "utils"},
    code: "/path/to/your/code.js",
    tests: "/path/to/your/tests.js"

// specify multiple dependencies
    deps: ["/path/to/your/dependency1.js", "/path/to/your/dependency2.js"],
    code: "/path/to/your/code.js",
    tests: "/path/to/your/tests.js"


Use stderr if you want to debug something while running via qunit. console.error("This will not brake qunit report"); // or require("util").debug("This will not brake qunit report");

Writing tests

QUnit API and code which have to be tested are already loaded and attached to the global context.

Because nodejs modules reserved "module" namespace we have to redefine it from QUnit namespace.

module = QUnit.module;

Basically QUnit API can ba accessed directly from global object or optional via "QUnit" object.


Some tests examples

test("a basic test example", function() {
  ok( true, "this test is fine" );
  var value = "hello";
  equals( "hello", value, "We expect value to be hello" );

module("Module A");

test("first test within module", 1, function() {
  ok( true, "all pass" );

test("second test within module", 2, function() {
  ok( true, "all pass" );

module("Module B", {
    setup: function() {
        // do some initial stuff before every test for this module
    teardown: function() {
        // do some stuff after every test for this module

test("some other test", function() {
  equals( true, false, "failing test" );
  equals( true, true, "passing test" );

module("Module C", {
    setup: function() {
        // setup a shared environment for each test
        this.options = {test: 123};

test("this test is using shared environment", 1, function() {
  same( {test:123}, this.options, "passing test" );

asyncTest("this is an async test example", 2, function() {
    setTimeout(function() {
        ok(true, "finished async test");
        strictEqual( true, true, "Strict equal assertion uses ===" );
    }, 100);

Run tests

$ make test


Using JSCoverage 0.3.1 (from the ubuntu universe repositories) resulted in a "jscoverage: unknown file type" error. Updating to the JSCoverage 0.5.1 from http://siliconforks.com/jscoverage/ resolves this issue.