Skip to content
Browse files

added support for nested tests and testCase

  • Loading branch information...
1 parent 781f9ab commit 22a8eeafdb61d446c49ce82a4e26150d569b3b49 @caolan committed Sep 18, 2010
Showing with 212 additions and 6 deletions.
  1. +48 −0 README.md
  2. +74 −6 lib/nodeunit.js
  3. +39 −0 test/test-runmodule.js
  4. +51 −0 test/test-testcase.js
View
48 README.md
@@ -111,6 +111,54 @@ to use the test.expect() method at the start of your test functions, and
test.done() when finished.
+Groups, setUp and tearDown
+--------------------------
+
+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 its possible to add setUp and tearDown functions to your
+tests. Nodeunit has a utility function called testCase which 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():
+
+ var testCase = require('nodeunit').testCase;
+
+ module.exports = testCase({
+ setUp: function () {
+ this.foo = 'bar';
+ },
+ tearDown: function () {
+ // clean up
+ },
+ test1: function (test) {
+ test.equals(this.foo, 'bar');
+ test.done();
+ }
+ });
+
+In this way, its possible to have multiple groups of tests in a module, each group
+with its own setUp and tearDown functions.
+
+
Running Tests
-------------
View
80 lib/nodeunit.js
@@ -51,25 +51,53 @@ exports.runTest = function (name, fn, opt, callback) {
};
/**
- * Run each exported test from a loaded module in series.
+ * Takes an object containing test functions or other test suites as properties
+ * and runs each in series. After all tests have completed, the callback is
+ * called with a list of all assertions as the second argument.
+ *
+ * If a name is passed to this function it is prepended to all test and suite
+ * names that run within it.
+ *
+ * @param {String} name
+ * @param {Object} suite
+ * @param {Object} opt
+ * @param {Function} callback
+ * @api public
+ */
+
+exports.runSuite = function (name, suite, opt, callback) {
+ var keys = Object.keys(suite);
+
+ async.concatSeries(keys, function (k, cb) {
+ var prop = suite[k];
+ var n = name ? name + ' - ' + k: k;
+
+ if (typeof prop === 'function') {
+ exports.runTest(n, suite[k], opt, cb);
+ }
+ else {
+ exports.runSuite(n, suite[k], opt, cb);
+ }
+ }, callback);
+};
+
+/**
+ * Run each exported test function or test suite from a loaded module.
*
* @param {String} name
* @param {Object} mod
* @param {Object} opt
* @param {Function} callback
+ * @api public
*/
exports.runModule = function (name, mod, opt, callback) {
var options = types.options(opt);
- var keys = Object.keys(mod);
options.moduleStart(name);
var start = new Date().getTime();
- async.concatSeries(keys, function (k, cb) {
- exports.runTest(k, mod[k], options, cb);
- },
- function (err, a_list) {
+ exports.runSuite(null, mod, opt, function (err, a_list) {
var end = new Date().getTime();
var assertion_list = types.assertionList(a_list, end-start);
options.moduleDone(name, assertion_list);
@@ -85,6 +113,7 @@ exports.runModule = function (name, mod, opt, callback) {
*
* @param {Array} paths
* @param {Object} opt
+ * @api public
*/
exports.runFiles = function (paths, opt) {
@@ -108,3 +137,42 @@ exports.runFiles = function (paths, opt) {
});
};
+
+/**
+ * Utility for wrapping a suite of test functions with setUp and tearDown
+ * functions.
+ *
+ * @param {Object} suite
+ * @return {Object}
+ * @api public
+ */
+
+exports.testCase = function (suite) {
+ var tests = {};
+
+ var setUp = suite.setUp;
+ var tearDown = suite.tearDown;
+ delete suite.setUp;
+ delete suite.tearDown;
+
+ var keys = Object.keys(suite);
+
+ return keys.reduce(function (tests, k) {
+ tests[k] = function (test) {
+ var context = {};
+ if (setUp) {
+ setUp.call(context);
+ }
+ if (tearDown) {
+ var done = test.done;
+ test.done = function (err) {
+ tearDown.call(context);
+ done(err);
+ };
+ }
+ suite[k].call(context, test);
+ };
+
+ return tests;
+ }, {});
+};
View
39 test/test-runmodule.js
@@ -74,3 +74,42 @@ exports.testRunModuleEmpty = function(test){
}
}, test.done);
};
+
+exports.testNestedTests = function(test){
+ var call_order = [];
+ var m = {
+ test1: function(test){
+ test.done();
+ },
+ suite: {
+ t1: function(test){
+ test.done();
+ },
+ t2: function(test){
+ test.done();
+ },
+ another_suite: {
+ t3: function(test){
+ test.done();
+ }
+ }
+ }
+ };
+ nodeunit.runModule('modulename', m, {
+ testStart: function(name){
+ call_order.push('testStart ' + name);
+ },
+ testDone: function(name, assertions){
+ call_order.push('testDone ' + name);
+ }
+ }, function(){
+ test.same(call_order, [
+ 'testStart test1', 'testDone test1',
+ 'testStart suite - t1', 'testDone suite - t1',
+ 'testStart suite - t2', 'testDone suite - t2',
+ 'testStart suite - another_suite - t3',
+ 'testDone suite - another_suite - t3'
+ ]);
+ test.done();
+ });
+};
View
51 test/test-testcase.js
@@ -0,0 +1,51 @@
+var nodeunit = require('../lib/nodeunit');
+var testCase = nodeunit.testCase;
+
+exports.testTestCase = function(test){
+ test.expect(7);
+ var call_order = [];
+ var s = testCase({
+ setUp: function(){
+ call_order.push('setUp');
+ test.equals(this.one, undefined);
+ this.one = 1;
+ },
+ tearDown: function(){
+ call_order.push('tearDown');
+ test.ok(true, 'tearDown called');
+ },
+ test1: function(t){
+ call_order.push('test1');
+ test.equals(this.one, 1);
+ this.one = 2;
+ t.done();
+ },
+ test2: function(t){
+ call_order.push('test2');
+ test.equals(this.one, 1);
+ t.done();
+ }
+ });
+ nodeunit.runSuite(null, s, {}, function(){
+ test.same(call_order, [
+ 'setUp', 'test1', 'tearDown',
+ 'setUp', 'test2', 'tearDown'
+ ]);
+ test.done();
+ });
+};
+
+exports.tearDownAfterError = function(test){
+ test.expect(1);
+ var s = testCase({
+ tearDown: function(){
+ test.ok(true, 'tearDown called');
+ },
+ test: function(t){
+ throw new Error('some error');
+ }
+ });
+ nodeunit.runSuite(null, s, {}, function(){
+ test.done();
+ });
+};

0 comments on commit 22a8eea

Please sign in to comment.
Something went wrong with that request. Please try again.