Comparing version 0.1.4 to 0.2.0
153
minitest.js
@@ -31,6 +31,7 @@ // MiniTest.js | ||
var MiniTest = (function (opts) { | ||
var VERSION = '0.1.4'; | ||
var VERSION = '0.2.0'; | ||
var TRACE_FAIL = false; | ||
opts = opts || {pollute: false}; | ||
var global = this; | ||
var assertion_cnt = 0; | ||
var assertionCnt = 0; | ||
@@ -46,9 +47,6 @@ var extend = function (into, obj) { | ||
function Failure (msg) {}; | ||
Failure.prototype = Error; | ||
// ***** | ||
// * Unit assertions and supporting code | ||
var assertions = (function () { | ||
var message = function (msg, default_msg) { | ||
var message = function (msg, defaultMsg) { | ||
var str; | ||
@@ -59,7 +57,7 @@ return function () { | ||
msg = msg + '.'; | ||
msg = msg + "\n" + default_msg(); | ||
msg = msg + "\n" + defaultMsg(); | ||
str = msg.replace(/^\s*/, ''); | ||
return str.replace(/\s*$/, ''); | ||
} else { | ||
return default_msg() + '.'; | ||
return defaultMsg() + '.'; | ||
} | ||
@@ -77,7 +75,7 @@ } | ||
msg = msg || "Failed assertion, no message given"; | ||
assertion_cnt += 1; | ||
assertionCnt += 1; | ||
if (typeof test !== 'function') { | ||
var old_test_val = test; | ||
test = function () { return old_test_val }; | ||
var oldTestVal = test; | ||
test = function () { return oldTestVal }; | ||
} | ||
@@ -90,4 +88,5 @@ | ||
var f = new Failure(); | ||
f.message = msg; | ||
var f = new Error(msg); | ||
f.type = 'failure'; | ||
f.name = 'FailedAssertion'; | ||
throw f; | ||
@@ -101,4 +100,4 @@ } | ||
// * empty Arrays (most common case) | ||
assert_empty: function (obj, msg) { | ||
var my_props = [] | ||
assertEmpty: function (obj, msg) { | ||
var myProps = [] | ||
var prop; | ||
@@ -110,5 +109,5 @@ msg = message(msg, function() { | ||
for (prop in obj) { | ||
if (obj.hasOwnProperty(prop)) my_props.push(prop); | ||
if (obj.hasOwnProperty(prop)) myProps.push(prop); | ||
} | ||
return this.assert(my_props.length === 0, msg); | ||
return this.assert(myProps.length === 0, msg); | ||
}, | ||
@@ -118,3 +117,3 @@ | ||
// * Fails unless +exp+ and +act+ satisfy looser == equality test | ||
assert_equal: function (exp, act, msg) { | ||
assertEqual: function (exp, act, msg) { | ||
msg = message(msg, function() { | ||
@@ -129,3 +128,3 @@ return "Expected " + exp + " not " + act; | ||
// * of +exp+ | ||
assert_in_delta: function (exp, act, delta, msg) { | ||
assertInDelta: function (exp, act, delta, msg) { | ||
delta = delta || 0.001; | ||
@@ -145,5 +144,5 @@ console.log(delta); | ||
// * theorem | ||
assert_in_epsilon: function (a, b, epsilon, msg) { | ||
assertInEpsilon: function (a, b, epsilon, msg) { | ||
epsilon = epsilon || 0.001; | ||
return this.assert_in_delta(a, b, Math.min(a, b) * epsilon, msg); | ||
return this.assertInDelta(a, b, Math.min(a, b) * epsilon, msg); | ||
}, | ||
@@ -153,3 +152,3 @@ | ||
// * Fails if +collection+ does not include +obj+ | ||
assert_includes: function (collection, obj, msg) { | ||
assertIncludes: function (collection, obj, msg) { | ||
var thing, elm; | ||
@@ -159,3 +158,3 @@ msg = message(msg, function () { | ||
}); | ||
this.assert_respond_to(collection, 'pop'); | ||
this.assertRspondTo(collection, 'pop'); | ||
while (elm = collection.pop()) { | ||
@@ -172,3 +171,3 @@ if (elm === obj) { | ||
// * Fails if +obj+ does not have +cls+ in its prototype chain | ||
assert_inherits_from: function (cls, obj, msg) { | ||
assertInheritsFrom: function (cls, obj, msg) { | ||
var proto = obj; | ||
@@ -188,3 +187,3 @@ var thing; | ||
//* Fails if +obj+ does not have +cls+ as its direct prototype | ||
assert_instance_of: function (cls, obj, msg) { | ||
assertInstanceOf: function (cls, obj, msg) { | ||
msg = message(msg, function () { | ||
@@ -198,7 +197,7 @@ return "Expected " + obj + " to be an instance of " + cls; | ||
// * Fails if +str+ does not match +regexp+ | ||
assert_match: function (regexp, str, msg) { | ||
assertMatch: function (regexp, str, msg) { | ||
msg = message(msg, function () { | ||
return "Expected " + regexp + " to match " + str; | ||
}); | ||
this.assert_respond_to(str, "match"); | ||
this.assertRespondTo(str, "match"); | ||
if (typeof regexp === 'string') { | ||
@@ -212,3 +211,3 @@ regexp = new RegExp(regexp); | ||
// * Fails if +obj+ is not null | ||
assert_null: function (obj, msg) { | ||
assertNull: function (obj, msg) { | ||
msg = message(msg, function () { | ||
@@ -222,3 +221,3 @@ return "Expected " + obj + " to be null"; | ||
// * Fails unless +code+ raises an +exp+ | ||
assert_raises: function (exp, code, msg) { | ||
assertRaises: function (exp, code, msg) { | ||
msg = message(msg, function () { | ||
@@ -238,3 +237,3 @@ return "Expected exception of type " + exp.name; | ||
// * Fails unless +obj+ responds to +meth+ | ||
assert_respond_to: function (obj, meth, msg) { | ||
assertRespondTo: function (obj, meth, msg) { | ||
msg = message(msg, function () { | ||
@@ -249,3 +248,3 @@ return "Expected " + obj + " to respond to " + meth; | ||
// * Fails unless +exp+ and +act+ refer to the same object | ||
assert_same: function (exp, act, msg) { | ||
assertSame: function (exp, act, msg) { | ||
msg = message(msg, function () { | ||
@@ -258,5 +257,5 @@ return "Expected " + exp + " and " + act + " to be the same"; | ||
// ***** | ||
// * Fails unless +code+ throws an +exp+ syn for #assert_raises | ||
assert_throws: function (exp, code, msg) { | ||
return this.assert_raises(exp, code, msg); | ||
// * Fails unless +code+ throws an +exp+ syn for #assertRaises | ||
assertThrows: function (exp, code, msg) { | ||
return this.assertRaises(exp, code, msg); | ||
}, | ||
@@ -266,3 +265,3 @@ | ||
// * Fails unless +obj+ is undefined | ||
assert_undefined: function (obj, msg) { | ||
assertUndefined: function (obj, msg) { | ||
msg = message(msg, function () { | ||
@@ -298,3 +297,3 @@ return "Expected " + obj + " to be undefined"; | ||
// * Fails if +obj+ is empty | ||
refute_empty: function (obj, msg) { | ||
refuteEmpty: function (obj, msg) { | ||
msg = message(msg, function () { | ||
@@ -305,3 +304,3 @@ return "Expected " + obj + " to not be empty" | ||
// assert(obj.hasOwnProperty('length')); | ||
this.assert_respond_to(obj, 'pop'); | ||
this.assertRespondTo(obj, 'pop'); | ||
return this.refute(! (obj.pop()), msg); | ||
@@ -312,3 +311,3 @@ }, | ||
// * Fails if +exp+ == +act+ | ||
refute_equal: function (exp, act, msg) { | ||
refuteEqual: function (exp, act, msg) { | ||
msg = message(msg, function () { | ||
@@ -323,3 +322,3 @@ return "Expected " + act + " to not be equal to " + exp; | ||
// * floats. | ||
refute_in_delta: function (exp, act, delta, msg) { | ||
refuteInDelta: function (exp, act, delta, msg) { | ||
delta = delta || 0.001; | ||
@@ -335,5 +334,5 @@ msg = message(msg, function () { | ||
// * how delta and epsilon relate, but I know math and not CS | ||
refute_in_epsilon: function (a, b, epsilon, msg) { | ||
refuteInEpsilon: function (a, b, epsilon, msg) { | ||
epsilon = epsilon || 0.001; | ||
return this.refute_in_delta(a, b, (a * epsilon), msg); | ||
return this.refuteInDelta(a, b, (a * epsilon), msg); | ||
}, | ||
@@ -343,3 +342,3 @@ | ||
// * Fails if +collection+ includes +obj+ | ||
refute_includes: function (collection, obj, msg) { | ||
refuteIncludes: function (collection, obj, msg) { | ||
var thing, elm; | ||
@@ -349,3 +348,3 @@ msg = message(msg, function () { | ||
}); | ||
this.assert_respond_to(collection, 'pop'); | ||
this.assertRespondTo(collection, 'pop'); | ||
while (elm = collection.pop()) { | ||
@@ -362,7 +361,7 @@ if (elm === obj) { | ||
// * Fails if +str+ matches +regexp+ | ||
refute_match: function (regexp, str, msg) { | ||
refuteMatch: function (regexp, str, msg) { | ||
msg = message(msg, function () { | ||
return "Expected " + regexp + " to not match " + act; | ||
}); | ||
this.assert_respond_to(str, "match"); | ||
this.assertRespondTo(str, "match"); | ||
if (typeof regexp === 'string') { | ||
@@ -376,3 +375,3 @@ regexp = new RegExp(regexp); | ||
// * Fails if +obj+ is null | ||
refute_null: function (obj, msg) { | ||
refuteNull: function (obj, msg) { | ||
msg = message(msg, function () { | ||
@@ -386,3 +385,3 @@ return "Expected " + obj + " to not be null"; | ||
// * Fails if +obj+ responds to +meth+ | ||
refute_respond_to: function (obj, meth, msg) { | ||
refuteRespondTo: function (obj, meth, msg) { | ||
msg = message(msg, function () { | ||
@@ -396,3 +395,3 @@ return "Expected " + obj + " to not respond to " + meth; | ||
// * Fails if +exp+ === +act+ | ||
refute_same: function (exp, act, msg) { | ||
refuteSame: function (exp, act, msg) { | ||
msg = message(msg, function () { | ||
@@ -410,6 +409,6 @@ return "Expected " + exp + " and " + act + " to not be the same"; | ||
var report, failures, errors, skips; | ||
var test_count, assertion_count; | ||
var start_time; | ||
var test_cases = []; | ||
var test_space = {}; | ||
var testCount, assertionCount; | ||
var startTime; | ||
var testCases = []; | ||
var testSpace = {}; | ||
var output = console || { | ||
@@ -423,10 +422,23 @@ log: function (msg) { | ||
// local | ||
extend(test_space, assertions); | ||
extend(testSpace, assertions); | ||
// ***** | ||
// * Run a test case | ||
var run_case = function (tc, randomize) { | ||
var runCase = function (tc, randomize) { | ||
var tests = []; | ||
var prop, i, fail, error; | ||
var failures = [], errors = []; | ||
var writer; | ||
var resultChar = '.'; | ||
// i haven't figured out a good way to do this in the browser | ||
if (process !== undefined) { | ||
writer = function (c) {process.stdout.write(c)}; | ||
writer.flush = function () {process.stdout.write("\n");} | ||
} else { | ||
var outStr = ""; | ||
writer = function(c) {outStr = outStr + c;} | ||
writer.flush = function () {console.log(outStr);} | ||
} | ||
randomize = randomize || true; | ||
@@ -451,15 +463,16 @@ | ||
for (i = 0; i < tests.length; i++) { | ||
resultChar = '.'; | ||
if (tc['setup'] && typeof tc['setup'] === 'function') { | ||
tc.setup(); | ||
} | ||
if (process !== undefined) | ||
process.stdout.write("."); | ||
try { | ||
tests[i].apply(test_space); | ||
tests[i].apply(testSpace); | ||
} catch (e) { | ||
e.test = tests[i]; | ||
if (e instanceof Failure) { | ||
if (e.type === 'failure') { | ||
failures.push(e); | ||
resultChar = 'F'; | ||
} else { | ||
errors.push(e); | ||
resultChar = 'E'; | ||
} | ||
@@ -470,7 +483,6 @@ } | ||
} | ||
writer(resultChar); | ||
} | ||
if (process !== undefined) | ||
process.stdout.write("\n"); | ||
writer.flush(); | ||
output.log(); | ||
@@ -482,2 +494,4 @@ | ||
output.log(failures[i].test.__name__ + ": " + failures[i].message); | ||
if (TRACE_FAIL) | ||
output.log(failures[i].stack); | ||
} | ||
@@ -490,3 +504,4 @@ output.log(); | ||
for (var i = 0; i < errors.length; i++) { | ||
output.link(errors[i].type + ": " + errors[i].message); | ||
output.log(errors[i].type + ": " + errors[i].message); | ||
output.log(errors[i].stack); | ||
} | ||
@@ -497,3 +512,3 @@ output.log(); | ||
output.log(tests.length + " tests, " + | ||
assertion_cnt + " assertions, " + | ||
assertionCnt + " assertions, " + | ||
failures.length + " failures, " + | ||
@@ -505,12 +520,12 @@ errors.length + " errors."); | ||
return { | ||
test_cases: function () {return test_cases.slice()}, | ||
new_test_case: function (tc) {test_cases.push(tc)}, | ||
testCases: function () {return testCases.slice()}, | ||
newTestCase: function (tc) {testCases.push(tc)}, | ||
run: function () { | ||
var i; | ||
assertion_cnt = 0; | ||
assertionCnt = 0; | ||
output.log("Starting tests..."); | ||
output.log("Starting tests...\n"); | ||
output.time("Run time"); | ||
for (i = 0; i < test_cases.length; i++) { | ||
run_case(test_cases[i]); | ||
for (i = 0; i < testCases.length; i++) { | ||
runCase(testCases[i]); | ||
} | ||
@@ -517,0 +532,0 @@ output.timeEnd("Run time"); |
{ | ||
"name": "minitest", | ||
"description": "A port of Ruby's MiniTest::Unit", | ||
"version": "0.1.4", | ||
"version": "0.2.0", | ||
"url": "https://github.com/deanh/minitest.js", | ||
@@ -6,0 +6,0 @@ "author": "H. Dean Hudson <dean@ero.com>", |
@@ -8,4 +8,17 @@ # minitest.js # | ||
A small and simple unit test framework for JavaScript based on the lovely | ||
MiniTest::Unit by Ryan Davis. | ||
MiniTest::Unit by Ryan Davis. It's meant to be simple and fast. It provides | ||
lots of assertions and randomizes test sequence. | ||
## CHANGELOG ## | ||
0.2.0: | ||
* Proper stack traces for errors | ||
* Fs and Es for failures and errors as the tests run | ||
* Optional stack traces for failures (via a constant flag) | ||
* CamelCase everything. This breaks the API, but it was weird, needed to be done sooner, | ||
and should be easy to fix | ||
0.1.4: | ||
* Fixed basic messaging bugs | ||
## Synopsis ## | ||
@@ -15,2 +28,46 @@ | ||
// in node land, you have need a runner that looks something like this: | ||
// runner.js | ||
#!/usr/bin/env node | ||
var sys = require('sys'), | ||
fs = require('fs'), | ||
zombie = require('zombie'), // if you want to get headless | ||
MiniTest = require('minitest').MiniTest; | ||
var files = process.argv.slice(2,process.argv.length); | ||
var i = 0; | ||
for(i = 0; i < files.length; i++) { | ||
MiniTest.Unit.newTestCase( | ||
require(process.cwd() + "/" + files[i]).test(zombie)); | ||
} | ||
MiniTest.Unit.run(); | ||
// elsewhere, test files... | ||
// test_foo.js | ||
exports.test = (function (zombie) { | ||
var setupCount = 0; | ||
var teardownCount = 0; | ||
return { | ||
setup: function () {setupCount++}, | ||
test1: function () {this.assert(1 === 1, "equality of 1")}, | ||
testNoMeansNo: function () {this.assert((0 + 2) == 1, "0 + 2 = 1?")}, | ||
testCollection: function () {this.assertEmpty([])}, | ||
testCollection2: function () {this.assertEmpty([1,2,3])}, | ||
testCollection3: function () {this.refuteEmpty([1,2,3])}, | ||
testError: function () {2 = 3;}, | ||
testSlow: function () {for(i=1000000; i>0;i--) this.assert(Math.pow(i,2)) }, | ||
testSlow1: function () {for(i=1000000; i>0;i--) this.assert(Math.pow(i,2)) }, | ||
testSlow2: function () {for(i=1000000; i>0;i--) this.assert(Math.pow(i,2)) }, | ||
testSlow3: function () {for(i=1000000; i>0;i--) this.assert(Math.pow(i,2)) }, | ||
testSlow4: function () {for(i=1000000; i>0;i--) this.assert(Math.pow(i,2)) }, | ||
teardown: function () {teardownCount++} | ||
} | ||
}) | ||
// in a browser, it's more like such: | ||
var setupCount = 0; | ||
@@ -26,17 +83,33 @@ var teardownCount = 0; | ||
MiniTest.Unit.new_test_case(tests); | ||
MiniTest.Unit.newTestCase(tests); | ||
MiniTest.Unit.run(); | ||
/***** Output ***** | ||
/****** Command-line output *****/ | ||
dean@dean:~/Devel/example$ rake test:js | ||
Running JavaScript tests in /Users/dean/Devel/example/tests/js/ | ||
Starting tests... | ||
.. | ||
E.F......F. | ||
Failures: | ||
testCollection2: Expected 1,2,3 to be empty. | ||
testNoMeansNo: 0 + 2 = 1? | ||
2 tests, 2 assertions, 1 failures, 0 errors. | ||
Run time: 2ms | ||
***** Fin *****/ | ||
Errors: | ||
invalid_lhs_in_assignment: Invalid left-hand side in assignment | ||
ReferenceError: Invalid left-hand side in assignment | ||
at Object.<anonymous> (/Users/dean/Devel/sprouting-3/test/js/test_foo.js:12:33) | ||
at /Users/dean/node_modules/minitest/minitest.js:434:30 | ||
at Object.run (/Users/dean/node_modules/minitest/minitest.js:490:21) | ||
at Object.<anonymous> (/Users/dean/Devel/sprouting-3/test/js/runner.js:18:15) | ||
at Module._compile (module.js:407:26) | ||
at Object..js (module.js:413:10) | ||
at Module.load (module.js:339:31) | ||
at Function._load (module.js:298:12) | ||
at Array.0 (module.js:426:10) | ||
at EventEmitter._tickCallback (node.js:126:26) | ||
11 tests, 5000006 assertions, 2 failures, 1 errors. | ||
Run time: 585ms | ||
MiniTest::Assertions provides a rich palette of assertions and refutations for crafting unit | ||
@@ -43,0 +116,0 @@ tests. See source for details. |
Sorry, the diff of this file is not supported yet
24499
461
123