├── .gitignore ├── .travis.yml ├── Makefile ├── Readme.md ├── browser.js ├── index.js ├── lib ├── Collection.js ├── TestCase.js └── reporter │ ├── BashReporter.js │ └── ConsoleReporter.js ├── package.json ├── syntax.json └── test ├── system ├── test-console-reporter.js ├── test-example.js └── test-run-selected-tests.js └── unit ├── test-BashReporter.js ├── test-Collection.js ├── test-ConsoleReporter.js └── test-TestCase.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.un~ 2 | /node_modules/* 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.4 4 | - 0.6 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | test: 4 | @find test -name test-*.js -type f | xargs -tn1 node 5 | 6 | .PHONY: test 7 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # utest 2 | 3 | [![Build Status](https://secure.travis-ci.org/felixge/node-utest.png)](http://travis-ci.org/felixge/node-utest) 4 | 5 | The minimal unit testing library. 6 | 7 | ## Why yet another test library? 8 | 9 | I wanted something simple, that just does unit tests (no async) and where each 10 | test is a standalone UNIX program. Now it exists. 11 | 12 | ## How do I run async tests? 13 | 14 | Currently there is only one sane way: Do not use a framework. Instead use one 15 | file per test. 16 | 17 | If that becomes an issue, you should write more unit tests. (It is not a unit 18 | test if it does I/O). 19 | 20 | ## Install 21 | 22 | ``` 23 | npm install utest 24 | ``` 25 | 26 | ## Usage 27 | 28 | Running a test with utest is very simple: 29 | 30 | ```js 31 | var test = require('utest'); 32 | var assert = require('assert'); 33 | 34 | test('Number#toFixed', { 35 | 'returns a string': function() { 36 | assert.equal(typeof (5).toFixed(), 'string'); 37 | }, 38 | 39 | 'takes number of decimal places': function() { 40 | assert.equal((5).toFixed(1), '5.0'); 41 | }, 42 | 43 | 'does not round': function() { 44 | assert.equal((5.55).toFixed(1), '5.5'); 45 | }, 46 | }); 47 | ``` 48 | 49 | It is also possible to define a before/after method: 50 | 51 | ```js 52 | var test = require('utest'); 53 | var assert = require('assert'); 54 | 55 | test('Date', { 56 | before: function() { 57 | this.date = new Date; 58 | }, 59 | 60 | after: function() { 61 | this.date = null; 62 | }, 63 | 64 | 'lets you manipulate the year': function() { 65 | this.date.setYear(2012); 66 | assert.equal(this.date.getFullYear(), 2012); 67 | }, 68 | 69 | 'can be coerced into a number': function() { 70 | assert.equal(typeof +this.date, 'number'); 71 | }, 72 | }); 73 | ``` 74 | 75 | Last but not least, you can run individual tests by prefixing them with an 76 | exclamation mark. This is useful when putting debug statements into the subject 77 | under test: 78 | 79 | ```js 80 | var test = require('utest'); 81 | var assert = require('assert'); 82 | 83 | test('MyTest', { 84 | '!will be executed': function() { 85 | // ... 86 | }, 87 | 88 | 'will not be exectuted': function() { 89 | // ... 90 | }, 91 | }); 92 | ``` 93 | 94 | ## Future Features 95 | 96 | I want to keep this library as minimal as possible, but I do consider the 97 | addition of the following features: 98 | 99 | * Nested test cases 100 | * TAP output (if TAP=1 in the environment, switch to TapReporter class) 101 | * Leak detection (automatically add a final test that fails if there are global 102 | leaks). 103 | 104 | ## License 105 | 106 | This module is licensed under the MIT license. 107 | -------------------------------------------------------------------------------- /browser.js: -------------------------------------------------------------------------------- 1 | if (!Function.prototype.bind) { 2 | Function.prototype.bind = function (scope) { 3 | var fn = this; 4 | return function () { 5 | return fn.apply(scope, arguments); 6 | }; 7 | }; 8 | } 9 | 10 | // Not shimed by Browserify: 11 | process.exit = function () {}; 12 | 13 | var test = require('./index'); 14 | test.Reporter = test.ConsoleReporter; 15 | 16 | module.exports = function (name, tests) { 17 | process.nextTick(function () { 18 | test(name, tests); 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = utest; 2 | utest.Collection = require('./lib/Collection'); 3 | utest.TestCase = require('./lib/TestCase'); 4 | utest.BashReporter = require('./lib/reporter/BashReporter'); 5 | utest.ConsoleReporter = require('./lib/reporter/ConsoleReporter'); 6 | utest.Reporter = utest.BashReporter; 7 | 8 | var collection; 9 | var reporter; 10 | function utest(name, tests) { 11 | if (!collection) { 12 | collection = new utest.Collection(); 13 | reporter = new utest.Reporter({collection: collection}); 14 | 15 | process.nextTick(collection.run.bind(collection)); 16 | collection.on('complete', function(stats) { 17 | process.exit(stats.fail ? 1 : 0); 18 | }); 19 | } 20 | 21 | var testCase = new utest.TestCase({name: name, tests: tests}); 22 | collection.add(testCase); 23 | }; 24 | -------------------------------------------------------------------------------- /lib/Collection.js: -------------------------------------------------------------------------------- 1 | var util = require('util'); 2 | var EventEmitter = require('events').EventEmitter; 3 | 4 | module.exports = Collection; 5 | util.inherits(Collection, EventEmitter); 6 | function Collection(options) { 7 | this._pass = 0; 8 | this._fail = 0; 9 | this._skip = 0; 10 | this._testCases = []; 11 | this._onlyRunSelectedTests = false; 12 | } 13 | 14 | Collection.prototype.add = function(testCase) { 15 | this._testCases.push(testCase); 16 | if (testCase.hasSelectedTests()) this._onlyRunSelectedTests = true; 17 | }; 18 | 19 | Collection.prototype.run = function() { 20 | this._start = this._start || Date.now(); 21 | for (var i = 0; i < this._testCases.length; i++) { 22 | var testCase = this._testCases[i]; 23 | this._runTestCase(testCase); 24 | } 25 | this.emit('complete', this.stats()); 26 | }; 27 | 28 | Collection.prototype._runTestCase = function(testCase) { 29 | this.emit('run', testCase); 30 | var self = this; 31 | testCase 32 | .on('pass', function(name) { 33 | self._pass++; 34 | self.emit('pass', testCase, name); 35 | }) 36 | .on('fail', function(name, err) { 37 | self._fail++; 38 | self.emit('fail', testCase, name, err); 39 | }) 40 | .on('skip', function(name, err) { 41 | self._skip++; 42 | self.emit('skip', testCase, name); 43 | }) 44 | .run(this._onlyRunSelectedTests); 45 | }; 46 | 47 | Collection.prototype.stats = function() { 48 | return { 49 | pass : this._pass, 50 | fail : this._fail, 51 | skip : this._skip, 52 | duration : Date.now() - this._start, 53 | }; 54 | }; 55 | -------------------------------------------------------------------------------- /lib/TestCase.js: -------------------------------------------------------------------------------- 1 | var util = require('util'); 2 | var EventEmitter = require('events').EventEmitter; 3 | var doNothing = function() {}; 4 | 5 | module.exports = TestCase; 6 | util.inherits(TestCase, EventEmitter); 7 | function TestCase(properties) { 8 | this.name = properties.name; 9 | this._tests = properties.tests; 10 | } 11 | 12 | TestCase.prototype.run = function(onlyRunSelectedTests) { 13 | var before = this._tests.before || doNothing; 14 | var after = this._tests.after || doNothing; 15 | 16 | for (var test in this._tests) { 17 | if (test === 'before' || test === 'after') continue; 18 | 19 | if (onlyRunSelectedTests && !this._isSelected(test)) { 20 | this.emit('skip', test); 21 | continue; 22 | } 23 | 24 | var fn = this._tests[test]; 25 | var context = {}; 26 | var err = null; 27 | 28 | try { 29 | before.call(context); 30 | fn.call(context); 31 | } catch (_err) { 32 | err = _err; 33 | } finally { 34 | try { 35 | after.call(context); 36 | } catch (_err) { 37 | if (!err) { 38 | err = _err; 39 | } 40 | } 41 | } 42 | 43 | if (!err) { 44 | this.emit('pass', test); 45 | } else { 46 | this.emit('fail', test, err); 47 | } 48 | } 49 | }; 50 | 51 | TestCase.prototype.hasSelectedTests = function() { 52 | for (var test in this._tests) { 53 | if (this._isSelected(test)) return true; 54 | } 55 | 56 | return false; 57 | }; 58 | 59 | TestCase.prototype._isSelected = function(test) { 60 | return test.substr(0, 1) === '!'; 61 | }; 62 | -------------------------------------------------------------------------------- /lib/reporter/BashReporter.js: -------------------------------------------------------------------------------- 1 | var Util = require('util'); 2 | 3 | module.exports = BashReporter; 4 | function BashReporter(options) { 5 | this._process = options.process || process; 6 | this._collection = options.collection; 7 | 8 | this._collection.on('fail', this._handleFail.bind(this)); 9 | this._collection.on('complete', this._handleComplete.bind(this)); 10 | } 11 | 12 | BashReporter.prototype._handleFail = function(testCase, test, error) { 13 | this._process.stdout.write('Failed: ' + testCase.name + ' ' + test + '\n\n'); 14 | var stack = (error.stack) 15 | ? error.stack 16 | : 'Exception without stack: ' + Util.inspect(error); 17 | 18 | stack = stack.replace(/^/gm, ' '); 19 | this._process.stdout.write(stack + '\n\n'); 20 | }; 21 | 22 | BashReporter.prototype._handleComplete = function(stats) { 23 | var output = 24 | stats.fail + ' fail | ' + 25 | stats.pass + ' pass | ' + 26 | stats.duration + ' ms ' + 27 | '\n'; 28 | 29 | if (stats.skip) { 30 | output = stats.skip + ' SKIPPED | ' + output; 31 | } 32 | 33 | this._process.stdout.write(output); 34 | }; 35 | -------------------------------------------------------------------------------- /lib/reporter/ConsoleReporter.js: -------------------------------------------------------------------------------- 1 | var Util = require('util'); 2 | 3 | module.exports = ConsoleReporter; 4 | function ConsoleReporter(options) { 5 | this._collection = options.collection; 6 | 7 | this._collection.on('run', this._handleRun.bind(this)); 8 | this._collection.on('fail', this._handleFail.bind(this)); 9 | this._collection.on('complete', this._handleComplete.bind(this)); 10 | } 11 | 12 | ConsoleReporter.prototype._handleRun = function(testCase) { 13 | console.log('Running: ' + testCase.name); 14 | }; 15 | 16 | ConsoleReporter.prototype._handleFail = function(testCase, test, error) { 17 | var msg = 'Failed: ' + testCase.name + ' ' + test; 18 | var stack = (error.stack) 19 | ? error.stack 20 | : 'Exception without stack: ' + Util.inspect(error); 21 | 22 | stack = stack.replace(/^/gm, ' '); 23 | console.error(msg + '\n\n' + stack + '\n'); 24 | }; 25 | 26 | ConsoleReporter.prototype._handleComplete = function(stats) { 27 | if (stats.skip) { 28 | console.warn(stats.skip + ' SKIPPED'); 29 | } 30 | console.info(stats.fail + ' fail | ' + 31 | stats.pass + ' pass | ' + 32 | stats.duration + ' ms'); 33 | 34 | }; 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Felix Geisendörfer (http://debuggable.com/)", 3 | "name": "utest", 4 | "description": "The minimal unit testing library.", 5 | "homepage": "https://github.com/felixge/node-utest", 6 | "version": "0.0.8", 7 | "repository": { 8 | "url": "" 9 | }, 10 | "main": "./index", 11 | "scripts": { 12 | "test": "make test" 13 | }, 14 | "engines": { 15 | "node": "*" 16 | }, 17 | "browser": "./browser.js", 18 | "dependencies": {}, 19 | "devDependencies": {}, 20 | "optionalDependencies": {} 21 | } 22 | -------------------------------------------------------------------------------- /syntax.json: -------------------------------------------------------------------------------- 1 | { 2 | "addSemicolons": true, 3 | "trimWhitespace": true, 4 | "quotes": "'" 5 | } 6 | -------------------------------------------------------------------------------- /test/system/test-console-reporter.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var test = require('../..'); 3 | 4 | var infoCalls = 0; 5 | var warnCalls = 0; 6 | var errorCalls = 0; 7 | 8 | console.info = function() { 9 | infoCalls++; 10 | }; 11 | console.warn = function() { 12 | warnCalls++; 13 | }; 14 | console.error = function() { 15 | errorCalls++; 16 | }; 17 | 18 | test.Reporter = test.ConsoleReporter; 19 | 20 | test('console', { 21 | 'skipped': function() {}, 22 | '!fails': function() { throw new Error(); }, 23 | '!fails again': function() { throw new Error(); } 24 | }); 25 | 26 | process.on('exit', function() { 27 | assert.equal(infoCalls, 1); 28 | assert.equal(warnCalls, 1); 29 | assert.equal(errorCalls, 2); 30 | 31 | // Override return code or 'make' will always fail 32 | process.reallyExit(0); 33 | }); 34 | -------------------------------------------------------------------------------- /test/system/test-example.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var test = require('../..'); 3 | 4 | var executed = 0; 5 | test('Number#toFixed', { 6 | 'returns a string': function() { 7 | assert.equal(typeof (5).toFixed(), 'string'); 8 | executed++; 9 | }, 10 | 11 | 'takes number of decimal places': function() { 12 | assert.equal((5).toFixed(1), '5.0'); 13 | executed++; 14 | }, 15 | 16 | 'does not round': function() { 17 | assert.equal((5.55).toFixed(1), '5.5'); 18 | executed++; 19 | }, 20 | }); 21 | 22 | process.on('exit', function() { 23 | assert.equal(executed, 3); 24 | }); 25 | -------------------------------------------------------------------------------- /test/system/test-run-selected-tests.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var test = require('../..'); 3 | 4 | var tests = []; 5 | 6 | test('1', { 7 | '!a': function() {tests.push('a');}, 8 | 'b': function() {tests.push('b');}, 9 | }); 10 | 11 | test('2', { 12 | '!c': function() {tests.push('c');}, 13 | 'd': function() {tests.push('d');}, 14 | }); 15 | 16 | process.on('exit', function() { 17 | assert.deepEqual(tests, ['a', 'c']); 18 | }); 19 | -------------------------------------------------------------------------------- /test/unit/test-BashReporter.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var BashReporter = require('../../lib/reporter/BashReporter'); 3 | var EventEmitter = require('events').EventEmitter; 4 | 5 | (function testOutputOfFailedTests() { 6 | var process = new EventEmitter(); 7 | var collection = new EventEmitter(); 8 | var reporter = new BashReporter({process: process, collection: collection}); 9 | 10 | var stdout = ''; 11 | process.stdout = { 12 | write: function(chunk) { 13 | stdout += chunk; 14 | }, 15 | }; 16 | 17 | var testCase = {name: 'MyTestCase'}; 18 | var test = 'is awesome'; 19 | var error = {stack: 'Something went wrong:\nLine2\nLine3'}; 20 | 21 | collection.emit('fail', testCase, test, error); 22 | 23 | assert.equal( 24 | stdout, 25 | 'Failed: MyTestCase is awesome\n' + 26 | '\n' + 27 | ' Something went wrong:\n' + 28 | ' Line2\n' + 29 | ' Line3\n' + 30 | '\n' 31 | ); 32 | })(); 33 | -------------------------------------------------------------------------------- /test/unit/test-Collection.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var Collection = require('../../lib/Collection'); 3 | var TestCase = require('../../lib/TestCase'); 4 | 5 | (function testRunningTwoTestCases() { 6 | var caseA = new TestCase({ 7 | name: 'a', 8 | tests: { 9 | '1': function() {}, 10 | '2': function() {}, 11 | }, 12 | }); 13 | var caseB = new TestCase({ 14 | name: 'b', 15 | tests: { 16 | '3': function() {}, 17 | '4': function() {}, 18 | }, 19 | }); 20 | 21 | var collection = new Collection(); 22 | 23 | collection.add(caseA); 24 | collection.add(caseB); 25 | 26 | var pass = []; 27 | collection.on('pass', function(testCase, name) { 28 | pass.push(testCase.name + ':' + name); 29 | }); 30 | 31 | collection.run(); 32 | 33 | assert.deepEqual(pass, ['a:1', 'a:2', 'b:3', 'b:4']); 34 | 35 | var stats = collection.stats(); 36 | assert.equal(stats.pass, 4); 37 | })(); 38 | 39 | (function testFailingTestCase() { 40 | var testCase = new TestCase({ 41 | tests: { 42 | 'good test': function() { 43 | }, 44 | 'bad test': function() { 45 | throw new Error('failure'); 46 | } 47 | }, 48 | }); 49 | 50 | var collection = new Collection(); 51 | collection.add(testCase); 52 | 53 | var fail = []; 54 | collection.on('fail', function(testCase, name, error) { 55 | fail.push({testCase: testCase, name: name, error: error}); 56 | }); 57 | 58 | collection.run(); 59 | 60 | assert.equal(fail.length, 1); 61 | assert.equal(fail[0].testCase, testCase); 62 | assert.equal(fail[0].name, 'bad test'); 63 | assert.equal(fail[0].error.message, 'failure'); 64 | 65 | var stats = collection.stats(); 66 | assert.equal(stats.pass, 1); 67 | assert.equal(stats.fail, 1); 68 | assert.ok(stats.duration >= 0); 69 | })(); 70 | 71 | (function testEmitCompleteTestCase() { 72 | var testCase = new TestCase({ 73 | tests: { 74 | 'good test': function() { 75 | }, 76 | 'bad test': function() { 77 | throw new Error('failure'); 78 | } 79 | }, 80 | }); 81 | 82 | var collection = new Collection(); 83 | collection.add(testCase); 84 | 85 | var stats; 86 | collection.on('complete', function(arg) { 87 | stats = arg; 88 | }); 89 | 90 | collection.run(); 91 | 92 | assert.equal(stats.pass, 1); 93 | assert.equal(stats.fail, 1); 94 | assert.ok(stats.duration >= 0); 95 | })(); 96 | 97 | (function testEmitRunTestCase() { 98 | var testCase1 = new TestCase({ 99 | tests: { 100 | 'good test': function() {} 101 | }, 102 | }); 103 | var testCase2 = new TestCase({ 104 | tests: { 105 | 'bad test': function() { 106 | throw new Error('failure'); 107 | } 108 | }, 109 | }); 110 | 111 | var collection = new Collection(); 112 | collection.add(testCase1); 113 | collection.add(testCase2); 114 | 115 | var runs = []; 116 | collection.on('run', function(testCase) { 117 | runs.push(testCase); 118 | }); 119 | 120 | collection.run(); 121 | 122 | assert.equal(runs.length, 2); 123 | assert.strictEqual(runs[0], testCase1); 124 | assert.strictEqual(runs[1], testCase2); 125 | })(); 126 | -------------------------------------------------------------------------------- /test/unit/test-ConsoleReporter.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var ConsoleReporter = require('../../lib/reporter/ConsoleReporter'); 3 | var EventEmitter = require('events').EventEmitter; 4 | 5 | (function testOutputOfFailedTests() { 6 | var collection = new EventEmitter(); 7 | var reporter = new ConsoleReporter({collection: collection}); 8 | 9 | var out; 10 | console.error = function (str) { 11 | out = str; 12 | }; 13 | 14 | var testCase = {name: 'MyTestCase'}; 15 | var test = 'is awesome'; 16 | var error = {stack: 'Something went wrong:\nLine2\nLine3'}; 17 | 18 | collection.emit('fail', testCase, test, error); 19 | 20 | assert.equal( 21 | out, 22 | 'Failed: MyTestCase is awesome\n' + 23 | '\n' + 24 | ' Something went wrong:\n' + 25 | ' Line2\n' + 26 | ' Line3\n' 27 | ); 28 | })(); 29 | 30 | (function testOutputOfCompleteTests() { 31 | var collection = new EventEmitter(); 32 | var reporter = new ConsoleReporter({collection: collection}); 33 | 34 | var out; 35 | console.info = function (str) { 36 | out = str; 37 | }; 38 | 39 | var stats = {fail:2, pass:1, duration:42}; 40 | 41 | collection.emit('complete', stats); 42 | 43 | assert.equal(out, '2 fail | 1 pass | 42 ms'); 44 | })(); 45 | 46 | (function testOutputOfCompleteWithSkippedTests() { 47 | var collection = new EventEmitter(); 48 | var reporter = new ConsoleReporter({collection: collection}); 49 | 50 | var out; 51 | console.warn = function (str) { 52 | out = str; 53 | }; 54 | 55 | var stats = {skip:11, fail:2, pass:1, duration:42}; 56 | 57 | collection.emit('complete', stats); 58 | 59 | assert.equal(out, '11 SKIPPED'); 60 | })(); 61 | 62 | (function testOutputOfRunningTests() { 63 | var collection = new EventEmitter(); 64 | var reporter = new ConsoleReporter({collection: collection}); 65 | 66 | var out; 67 | console.log = function (str) { 68 | out = str; 69 | }; 70 | 71 | collection.emit('run', {name: 'MyTest'}); 72 | 73 | assert.equal(out, 'Running: MyTest'); 74 | })(); 75 | -------------------------------------------------------------------------------- /test/unit/test-TestCase.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var TestCase = require('../../lib/TestCase'); 3 | 4 | (function testRunEmitsPassAndFail() { 5 | var test = new TestCase({tests: { 6 | a: function() { 7 | assert.equal(1, 1); 8 | }, 9 | b: function() { 10 | assert.equal(2, 1); 11 | }, 12 | }}); 13 | 14 | var fail = []; 15 | var pass = []; 16 | 17 | test 18 | .on('pass', function(name) { 19 | assert.equal(name, 'a'); 20 | pass.push(name); 21 | }) 22 | .on('fail', function(name, err) { 23 | assert.ok(err instanceof Error); 24 | assert.equal(name, 'b'); 25 | fail.push(name); 26 | }); 27 | 28 | 29 | test.run(); 30 | 31 | assert.equal(pass.length, 1); 32 | assert.equal(fail.length, 1); 33 | })(); 34 | 35 | (function testBeforeAndAfter() { 36 | var events = []; 37 | var test = new TestCase({tests: { 38 | before: function() { 39 | events.push('before'); 40 | }, 41 | after: function() { 42 | events.push('after'); 43 | }, 44 | 45 | a: function() { 46 | events.push('a'); 47 | }, 48 | }}); 49 | 50 | test.run(); 51 | 52 | assert.deepEqual(events, ['before', 'a', 'after']); 53 | })(); 54 | 55 | (function testBeforeAndAfterContext() { 56 | var aCalled = false; 57 | var test = new TestCase({tests: { 58 | before: function() { 59 | this.foo = 'bar'; 60 | }, 61 | 62 | after: function() { 63 | assert.deepEqual(this, {foo: false}); 64 | }, 65 | 66 | a: function() { 67 | assert.deepEqual(this, {foo: 'bar'}); 68 | this.foo = false; 69 | aCalled = true; 70 | }, 71 | }}); 72 | 73 | test.run(); 74 | 75 | assert.ok(aCalled); 76 | })(); 77 | 78 | (function testErrorInOneTestDoesNotAffectOthers() { 79 | var test = new TestCase({tests: { 80 | a: function() { 81 | assert.equal(2, 1); 82 | }, 83 | b: function() { 84 | assert.equal(1, 1); 85 | }, 86 | }}); 87 | 88 | var fail = []; 89 | var pass = []; 90 | 91 | test 92 | .on('pass', function(name) { 93 | pass.push(name); 94 | }) 95 | .on('fail', function(name, err) { 96 | fail.push(name); 97 | }); 98 | 99 | 100 | test.run(); 101 | 102 | assert.deepEqual(pass, ['b']); 103 | assert.deepEqual(fail, ['a']); 104 | })(); 105 | 106 | (function testErrorInTestStillCallsAfter() { 107 | var called = false; 108 | var test = new TestCase({tests: { 109 | after: function () { 110 | called = true; 111 | }, 112 | a: function() { 113 | throw new Error(); 114 | } 115 | }}); 116 | 117 | test.run(); 118 | 119 | assert(called); 120 | })(); 121 | 122 | (function testErrorInAfterFailsTest() { 123 | var test = new TestCase({tests: { 124 | after: function () { 125 | throw new Error(); 126 | }, 127 | a: function() {}, 128 | b: function() {} 129 | }}); 130 | 131 | var fail = []; 132 | var pass = []; 133 | 134 | test 135 | .on('pass', function(name) { 136 | pass.push(name); 137 | }) 138 | .on('fail', function(name, err) { 139 | fail.push(name); 140 | }); 141 | 142 | 143 | test.run(); 144 | 145 | assert.deepEqual(pass, []); 146 | assert.deepEqual(fail, ['a', 'b']); 147 | })(); 148 | 149 | (function testErrorInAfterDoesNotHideTestError() { 150 | var test = new TestCase({tests: { 151 | after: function () { 152 | throw new Error('after'); 153 | }, 154 | a: function() { 155 | throw new Error('test'); 156 | } 157 | }}); 158 | 159 | var err; 160 | 161 | test.on('fail', function(name, _err) { 162 | err = _err; 163 | }); 164 | 165 | test.run(); 166 | 167 | assert.equal(err.message, 'test'); 168 | })(); 169 | --------------------------------------------------------------------------------