node-async-testing includes two different means of running suites: A simple, recommended interface for running suite files and a low-level API (which is used by the previous method) which gives you fine-grained control.
node-async-testing assumes you are going to have a one to one mapping between suites and files. So, to run a test suite, you actually tell it to run a file:
require('async_testing').run('test-suite.js');
The run function can take a file name or a directory name (it
recursively searches directories for javascript files that start with test-)
or an array of any combination of those two options.
In order for node-async-testing to run a file, the exports object of the file needs to be the test suite:
exports['first test'] = function(test) { ... };
exports['second test'] = function(test) { ... };
exports['third test'] = function(test) { ... };
// or
module.exports = {
'first test': function(test) { ... },
'second test': function(test) { ... },
'third test': function(test) { ... }
};
To make a file easy to execute with the node command, we need
to make our file run the suite when it is the script being ran. Some where
in the file we put this code (I like to put it at the very top):
// if this module is the script being run, then run the tests:
if (module === require.main) {
return require('async_testing').run(__filename);
}
Assuming we put that suite in a file called test-suite.js, we can now
execute the it by running the following on the command line:
node test-suite.js
The run function can also be passed the process.ARGV
array of command line arguments, so node-async-testing settings can
be altered at run time:
if (module === require.main) {
return require('async_testing').run(process.ARGV);
}
exports['first test'] = function(test) { ... };
exports['second test'] = function(test) { ... };
exports['third test'] = function(test) { ... };
Now, you can tell node-async-testing to run the tests in parallel:
node test-suite.js --parallelOr to only run specific tests:
node test-suite.js --test-name "first test" --test-name "third test"
Use the help flag to see all the options:
node test-suite.js --help
node-async-testing can run multiple files at once this way, because
additional files will get passed with process.ARGV:
node test-suite.js test-suite2.js
For example, you can run all the tests in a test directory by saying:
node test/*With this arrangement, the exit code of the process will be the number of tests that didn't succeed.
node-async-testing comes with a "web" test runner. This runner launches a
web server which can be used to run suites manually. Launch it with the
--web flag:
node test/* --webOnce the server is started, in a browser you can pick and choose which suites to run, and run them as many times as you like. node-async-testing reloads the suites (and any code they use) from scratch each time they are run so you can leave the web server running and switch back and forth between editing tests or code and running the tests. Very handy!
To use the web runner you also need to install Socket.IO.
npm install socket.io[The server is known to work in the lastest versions of Safari, Chrome and Firefox. Any help in getting it to work in Opera would be much appreciated. I don't have means of testing in IE, so I can't tell you how it performs there.]
If you want to organize your suites in a different manner (and say not have them organized by file), or don't like the included test runners, you are going to have to run your suites manually or write your own runner.
node-async-testing comes with the following functions for running suites and test runners:
runSuite(suiteObject, options)
The runSuite function is the heart of node-async-testing.
It receives two arguments.
The first argument is the actual suite that you want to run. See Writing Tests for the details of writing a suite.
The second argument is an object with options for running the suite. This object can have the following properties:
nameonSuiteStart event callback.
parallelrunSuite won't start
another test until the previous one has completely finished.
testNameIn addition to those properties, the options in the events callbacks section are supported.
runSuite adds a listener to the process for uncaught exceptions,
and as such, there should be no other code running while runSuite
is doing its thing, otherwise the other code could interfere with the
suite being ran.
runFile(suitePath, options)
The runFile function is similar to runSuite except instead of
running the suite in the main process, it opens up a child process and runs it
there. The benefits of this are that it is able to report on syntax errors, and
also be run while other suites are running.
The first argument is a module path to the suite for Node's
require() function.
The second argument is an object with options for running the suite. It is practically
the same as the second argument for runSuite, except it has one for additional
event callback. See the events callbacks section for
the full list.
expandFiles(list, [filter], callback)
The expandFiles function takes a list of files and or
directories and returns a list of just files. It recursively searches
through any directories for files that begin with test-. It
is useful for expanding a user supplied list of files and directories. It
takes three properties:
expandFiles is done.
It returns an array of objects which have the following properties:
namepathrequire()ed.run()
The run functions is talked about at length in the
Running Suite Files section. It handles
outputing the results of suites for you, so you don't have to worry about it.
node-async-testing comes with two built-in runners, one for consoles and one
for web browsers.
run can take any number of arguments, which can be any
one of:
process.ARGV.
The last argument can be a callback which will get called when all the specified suites have finished running. The callback will receive one argument, an array with an object for each suite, which has the name, status and suite result object for that suite.
If a callback is not supplied, node-async-testing assumes that you don't
want to do anything after the suites have completed, so the run
function creates its own callback which exits the process and sets the exit
code to the number of suites that didn't complete successfully.
The order matters, latter settings override earlier ones. Here are some examples:
Run a file:
async_testing.run('myFile.js');Change options:
async_testing.run({parallel: true}, 'myFile.js');Use command line arguments:
async_testing.run(process.ARGV);Use command line arguments with defaults:
async_testing.run({parallel: true}, process.ARGV);Overwrite command line arguments:
async_testing.run(process.ARGV, {parallel: true});registerRunner(modulePath, [default])Use this function to add your own custom runners to node-async-testing. See lib/console-runner.js or lib/web-runner.js for examples of how to write a runner.
The first argument is the path to the runner which you are registering. The second variable is for whether or not you want this to be the default runner.
The runSuite and runFile functions can be given event callbacks for outputing
the results of the tests. Using these callbacks it is possible to write your
own test runners and format the output however you'd like. These callbacks
are not for manipulating tests, but purely for reporting.
onTestStart(testName)onTestDone(status, testResult)status is one of the following:onSuiteDone(status, suiteResult)status is one of the following:A suite result is an object that looks like one of the following, depending on what the finish status of the suite was:
occures when all tests finished running, and node-async-testing was able to accurately determine how each one finished.
{ tests: an Array of test results for each test that completed
, numFailures: the number of tests that failed
, numSuccesses: the number of tests that passed
}occures when an uncaught error is thrown from a test and node-async-testing can't determine which test caused it. When this happens, node-async-testing stops running the suite and exits the process.
{ error: the error object that was thrown
, tests: an Array of the names of each test that could have caused the error
}occures when the process running the suite exits and there are still tests that haven't finished. This occurs when people forget to finish their tests or their tests don't work like they expected.
{ tests: an Array of the names of each test that didn't finish
}
this type of result is only produced from runFile, and
occures when the child process can't load the suite.
{ stderr: what was written to <stderr> before the child process exited
}A test result is an object that looks like one of the following, depending on what the finish status of the test was:
the test completed successfully
{ name: test name
, numAssertions: number of assertions completed successfully
}the test failed in some way
{ name: test name
, failureType: 'assertion' or 'error' depending on how this failed
, failure: the error that caused this to fail
}