diff --git a/bin/asynct b/bin/asynct new file mode 100755 index 0000000..f3ece1e --- /dev/null +++ b/bin/asynct @@ -0,0 +1,25 @@ +#! /usr/bin/env node + +try { + // always check for a local copy of async_testing first + var testing = require('async_testing'); +} +catch(err) { + if( err.message == "Cannot find module './async_testing'" ) { + // look in the path for async_testing + var testing = require('async_testing'); + } + else { + throw err; + } +} + +exports.test = function (test){ + test.ok(false,"this should not be called!") +} +process.ARGV.shift() //node +process.ARGV.shift() // this file... if i leave this in it tried to run this file as a test, which goes into infinite loop and doesn't exit. +process.ARGV.unshift('node') + +testing.run(process.ARGV); + diff --git a/bin/node-async-test.js b/bin/node-async-test.js new file mode 100755 index 0000000..92ce4c1 --- /dev/null +++ b/bin/node-async-test.js @@ -0,0 +1,32 @@ +#! /usr/bin/env node + +try { + // always check for a local copy of async_testing first + var testing = require('async_testing'); +} +catch(err) { + if( err.message == "Cannot find module './async_testing'" ) { + // look in the path for async_testing + var testing = require('async_testing'); + } + else { + throw err; + } +} + +testing.run(null, process.ARGV, done); + +function done(allResults) { + // we want to have our exit status be the number of problems + + var problems = 0; + + for(var i = 0; i < allResults.length; i++) { + if (allResults[i].tests.length > 0) { + problems += allResults[i].numErrors; + problems += allResults[i].numFailures; + } + } + + process.exit(problems); +} diff --git a/docs/api.html b/docs/api.html new file mode 100644 index 0000000..642e88c --- /dev/null +++ b/docs/api.html @@ -0,0 +1,94 @@ +
testSuite is a test module for example runSuite (require('./test/simpleTest'),opts)
+each property in the object should be a test. A test is just a method which takes one argument (test)
+and then make assertions by calling test.ok(true) etc. and eventually test.finish()
+making an assertion after test.finish() or calling test.finish() twice results in a
+testAlreadyFinished error. not calling test.finish() at all is a an error as well. (see onSuiteDone({'0','exit',...)
Available configuration options: + * ++ parallel: boolean, for whether or not the tests should be run in parallel or serially. Obviously, parallel is faster, but it doesn't give as accurate error reporting ++testName: string or array of strings, the name of a test to be ran ++name: string, the name of the suite being ran ++ onTestStart ++ onTestDone ++ onSuiteDone
+ +example:
+ +
+ { name: 'string'
+ , testName: [array of test names to run]
+ , onTestStart: function (test) {}
+ , onTestDone: function (status,test) {}
+ , onSuiteDone: function (status,report) {}
+ }
+
+
+status may be:
+ +test.finish()currently the report differs for each status
+ +
+ {tests: //list of tests
+ [
+ { name: [name of test]
+ , numAssertions: [number of Assertions in test]
+ , failure: [error which caused failure] // only if this test failed, or errored.
+ , failureType: ['assertion' or 'error']
+ }
+ ]
+ }
+
+
+
+ { err: errorObject
+ , tests: [list of names of tests which where running when err error occured]
+ }
+ //usually an error is caught by the test and it's registered as a failure.
+ //sometimes a test throws an error asyncronously, and async_testing doesn't
+ //know which test it came from.
+
+
+
+ { name: [name of test]
+ , numAssertions: [number of Assertions in test]
+ , failure: [error which caused failure] // only if this test failed, or errored.
+ , failureType: ['assertion' or 'error']
+ }
+
diff --git a/docs/api.markdown b/docs/api.markdown
new file mode 100644
index 0000000..991e481
--- /dev/null
+++ b/docs/api.markdown
@@ -0,0 +1,94 @@
+module: async_testing
+=====================
+
+
+## method: runSuite (testSuite,opts)
+
+`testSuite` is a test module for example `runSuite (require('./test/simpleTest'),opts)`
+each property in the object should be a test. A test is just a method which takes one argument `(test)`
+and then make assertions by calling `test.ok(true)` etc. and eventually `test.finish()`
+making an assertion after `test.finish()` or calling `test.finish()` twice results in a
+testAlreadyFinished error. not calling `test.finish()` at all is a an error as well. (see onSuiteDone({'0','exit',...)
+
+ Available configuration options:
+ *
++ parallel: boolean, for whether or not the tests should be run in parallel or serially. Obviously, parallel is faster, but it doesn't give as accurate error reporting
++testName: string or array of strings, the name of a test to be ran
++name: string, the name of the suite being ran
++ onTestStart
++ onTestDone
++ onSuiteDone
+
+example:
+
+
+ { name: 'string'
+ , testName: [array of test names to run]
+ , onTestStart: function (test) {}
+ , onTestDone: function (status,test) {}
+ , onSuiteDone: function (status,report) {}
+ }
+
+
+###callback arguments: onSuiteDone (status,report)
+
+status may be:
+
++ _complete_ : valid result, success or failure
++ _exit_ : some tests did not call `test.finish()`
++ _loadError_ : an error occured while loading the test, i.e. a syntax error
++ _error_ : the test threw an error.
+
+currently the report differs for each status
+
++ complete
+
+
+ {tests: //list of tests
+ [
+ { name: [name of test]
+ , numAssertions: [number of Assertions in test]
+ , failure: [error which caused failure] // only if this test failed, or errored.
+ , failureType: ['assertion' or 'error']
+ }
+ ]
+ }
+
+
++ exit [list of tests which did not finish]
++ loadError [error message (string)]
++ error
+
+
+ { err: errorObject
+ , tests: [list of names of tests which where running when err error occured]
+ }
+ //usually an error is caught by the test and it's registered as a failure.
+ //sometimes a test throws an error asyncronously, and async_testing doesn't
+ //know which test it came from.
+
+
+###callback arguments: onTestStart (test)
+
++ test: name of the test which has started.
+
+###callback arguments: onTestDone (status,test)
++ status : 'success', or 'failure'
++ report:
+
+
+ { name: [name of test]
+ , numAssertions: [number of Assertions in test]
+ , failure: [error which caused failure] // only if this test failed, or errored.
+ , failureType: ['assertion' or 'error']
+ }
+
+
+
+## method: runFile (modulepath,opts)
+module is the path to the test suite to run. run a test in a child process, opts and callbacks are same as for runSuite.
+
+
+
+
+
diff --git a/lib/asynct_adapter.js b/lib/asynct_adapter.js
new file mode 100644
index 0000000..969da68
--- /dev/null
+++ b/lib/asynct_adapter.js
@@ -0,0 +1,5 @@
+
+exports.runTest = function (file,callbacks){
+ test = require(file)
+ require('async_testing').runSuite(test,callbacks)
+}
diff --git a/lib/child2.js b/lib/child2.js
new file mode 100644
index 0000000..a4904f0
--- /dev/null
+++ b/lib/child2.js
@@ -0,0 +1,149 @@
+var messages = require('./messages2')
+ , assert = require('assert')
+ , inspect = require('inspect')
+// , testing = require('./testing')
+
+if (module == require.main) {
+
+ process.ARGV.shift()//node
+ process.ARGV.shift()//__filename
+ json = process.ARGV.shift()
+
+ var opts = JSON.parse(json)
+
+ assert.ok(opts.start,"expected .start : magic number")
+
+ assert.ok(opts.end,"expected .end : magic number")
+
+ assert.ok(opts.args,"expected .end : magic number")
+ assert.ok('string' == typeof opts.args[0] ,"expected .end : magic number")
+ assert.ok('object' == typeof opts.args[1] ,"expected .end : magic number")
+
+ var file = opts.args[0]
+ , options = opts.args[1]
+ , messager = messages.useMagicNumbers(opts.start,opts.end)
+
+ callbacks = makeCallbacks(options,send)
+
+ function send(message){
+ console.log(messager.messageEncode(message))
+ }
+/* adapter = require(options.adapter || 'async_testing')
+ adapter.runSuite(require(file),callbacks)
+*/
+ adapter = require(options.adapter || 'async_testing/lib/asynct_adapter')
+ adapter.runTest(file,callbacks)
+}
+
+spawn = require('child_process').spawn
+
+//master creates slave, and then slave sends messages back.
+//call master with callbacks,
+//master goes through callbacks and turns gets the name of each one.
+//sends a message to slave of function names.
+//slave creates functions with these names, and then calls runSuite with them
+
+exports.runFile = runFile
+function runFile (file,options) {
+ var normalExit = false;
+ oldOnExit = options.onExit
+ options.onExit = function (status,report){
+ console.log("NORMAL EXIT")
+ normalExit = true;
+ oldOnExit && oldOnExit(status,report)
+ }
+
+ magic = messages.magicNumbers
+ child =
+ spawn('node'
+ , [ __filename
+ , json = JSON.stringify (
+ { start: magic.start
+ , end: magic.end
+ , args: [file, makeMessage (options)] } ) ] )
+
+ var buffer = ''
+ , messager = messages.useMagicNumbers(magic.start,magic.end)
+ child.stdout.on('data', function(data) {
+ data = data.toString();
+
+ var lines = data.split('\n');
+
+ lines[0] = buffer + lines[0];
+ buffer = lines.pop();
+
+ console.log(">\t"+data)
+
+ lines = messager.messageDecode(lines);
+
+ lines.forEach(function (message){
+ if(message)
+ parseMessage(message,options)
+ })
+ })
+ var errorBuffer = '';
+ child.stderr.on('data', function(data) {
+ errorBuffer += data.toString();
+ });
+
+/*
+ always ensure that normal exit has happened?
+ stall on suite done untill exit registered?
+
+*/
+
+ child.stderr.on('close', function() {
+ if (errorBuffer && options.onSuiteDone && !normalExit) {
+ options.onSuiteDone('loadError', {stderr: errorBuffer.trim()});
+ }
+ });
+
+/* child.on('exit', function (code){
+ if(!normalExit)
+ options.onSuiteDone('loadError', {failure: errorBuffer.trim()});
+ })*/
+}
+
+exports.makeMessage = makeMessage
+function makeMessage(callbacks){
+ message = {}
+ for(i in callbacks){
+ if('function' === typeof callbacks[i]){
+ message[i] = 'typeof function'
+ } else {
+ message[i] = callbacks[i]
+ }
+ }
+ return message
+}
+
+exports.makeCallbacks = makeCallbacks
+
+function makeCallbacks(message,sender){
+ var callbacks = {}
+ for(i in message){
+ (function (j){
+ if('typeof function' == message[i]){
+ callbacks[j] = function (){
+ args = []
+ for(i in arguments){
+ args[i] = arguments[i]
+ }
+
+ sender.call(null,[j,args])
+ }
+ } else {
+ callbacks[j] = message[j]
+ }
+ })(i)
+ }
+ return callbacks
+}
+
+exports.parseMessage = parseMessage
+function parseMessage (message,callbacks){
+
+ callbacks[message[0]].apply(null,message[1])
+}
+
+
diff --git a/lib/console-runner.js b/lib/console-runner.js
index 0b9e585..0d2e66f 100644
--- a/lib/console-runner.js
+++ b/lib/console-runner.js
@@ -161,7 +161,9 @@ exports.run = function(list, options, callback) {
}
}
}
-
+ /*
+ OUTPUT STARTS
+ */
var output =
{ testDone: function(suite, result) {
if (!suite.printedName) {
@@ -185,7 +187,7 @@ exports.run = function(list, options, callback) {
output['suite'+suite.status.substr(0,1).toUpperCase()+suite.status.substr(1)](suite);
}
, suiteLoadError: function(suite) {
- var err = suite.results.stderr;
+ var err = suite.results.stderr; //...
if (!suite.printedName) {
console.log(bold(suite.name));
@@ -232,7 +234,8 @@ exports.run = function(list, options, callback) {
for(var i = 0; i < tests.length; i++) {
var r = tests[i];
if (r.failure) {
- var s = r.failure.stack.split("\n");
+
+ var s = r.failure.stack ? r.failure.stack.split("\n"): ['no stack trace']
console.log(r.failureType == 'assertion' ? ' Failure: '+red(r.name) : ' Error: '+yellow(r.name));
@@ -241,6 +244,7 @@ exports.run = function(list, options, callback) {
}
if (options.verbosity == 1) {
+ console.log(s[0].replace(process.cwd(), '.'));//if it's an AssertionError the message is the first line of the stack.
if (s.length > 1) {
console.log(s[1].replace(process.cwd(), '.'));
}
@@ -249,7 +253,7 @@ exports.run = function(list, options, callback) {
}
}
else {
- for(var k = 1; k < s.length; k++) {
+ for(var k = 0; k < s.length; k++) {//on an assertion, this was hiding the default message
console.log(s[k].replace(process.cwd(), '.'));
}
}
@@ -307,22 +311,26 @@ exports.run = function(list, options, callback) {
else {
console.log(' Error: ' + yellow(tests[0]));
}
-
- var s = err.stack.split("\n");
+
if (err.message) {
console.log(' '+err.message);
+ } else {
+ console.log('ERROR:' + err);
}
- if (options.verbosity == 1) {
- if (s.length > 1) {
- console.log(s[1].replace(process.cwd(), '.'));
- }
- if (s.length > 2) {
- console.log(s[2].replace(process.cwd(), '.'));
+ if(err.stack){
+ var s = err.stack.split("\n")
+ if (options.verbosity == 1) {
+ if (s.length > 1) {
+ console.log(s[1].replace(process.cwd(), '.'));
+ }
+ if (s.length > 2) {
+ console.log(s[2].replace(process.cwd(), '.'));
+ }
}
- }
- else {
- for(var k = 1; k < s.length; k++) {
- console.log(s[k]);
+ else {
+ for(var k = 0; k < s.length; k++) {
+ console.log(s[k]);
+ }
}
}
}
@@ -400,4 +408,8 @@ exports.run = function(list, options, callback) {
}
}
}
+ /*
+ OUTPUT ENDS
+ */
+
}
diff --git a/lib/messages.js b/lib/messages.js
new file mode 100644
index 0000000..0f6368d
--- /dev/null
+++ b/lib/messages.js
@@ -0,0 +1,61 @@
+
+var messageFrame = "~m~";
+// these encode/decode functions inspired by socket.io's
+exports.messageDecode = messageDecode
+function messageDecode(lines) {
+ return lines.map(function(str) {
+ if (str.substr(0,3) !== messageFrame) {
+ return str;
+ }
+
+ var msg = [];
+ for (var i = 3, number = '', l = str.length; i < l; i++){
+ var n = Number(str.substr(i, 1));
+ if (str.substr(i, 1) == n){
+ number += n;
+ } else {
+ number = Number(number);
+ var m = str.substr(i+messageFrame.length, number);
+ msg.push(JSON.parse(m));
+ i += messageFrame.length*2 + number - 1;
+ number = '';
+ }
+ }
+ return msg;
+ });
+}
+exports.messageEncode = function() {
+ var r = '';
+
+ for (var i = 0; i < arguments.length; i++) {
+ var json = JSON.stringify(arguments[i]);
+ r += messageFrame + json.length + messageFrame + json;
+ }
+
+ return r;
+}
+
+
+//exports.decode =
+function decodeLine(string){
+ var mm = /~m~(\d+)~m~(.*)/.exec(string)
+ if(!mm){
+ throw new Error("could not decode :" + string + " there was no match for messageFrame ~m~[length]~m~")
+ }
+
+ var frame = mm[0]
+ , len = mm[1]
+ , rest = mm[2]
+ if(len != rest.length){
+ throw new Error("message payload should be :" + len + " long, but was:" + rest.length + "message was:" + rest)
+ }
+ return JSON.parse(rest)
+}
+
+//exports.encode = exports.messageEncode
+//exports.messageDecode = decode
+function decode(lines){
+ return lines.map(function(line){
+ return decodeLine(line)
+ })
+ }
diff --git a/lib/messages2.js b/lib/messages2.js
new file mode 100644
index 0000000..2de8077
--- /dev/null
+++ b/lib/messages2.js
@@ -0,0 +1,29 @@
+
+inspect = require('inspect')
+
+function useMagicNumbers(start,end){
+ start = start || Math.round(Math.random()*10000000)
+ end = end || Math.round(Math.random()*100000000)
+ return {
+ messageEncode: messageEncode
+ , messageDecode: messageDecode
+ , useMagicNumbers:useMagicNumbers
+ , magicNumbers: {start: start, end: end}
+ }
+
+ function messageEncode(x) {
+ return "" + start + JSON.stringify(x) + end
+ }
+
+ function messageDecode(lines){
+ return lines.map(decodeLine)
+ }
+ function decodeLine(string){
+
+ var m = string.match("" + start + "(.*)" + end)
+ if(m)
+ return JSON.parse(m[1])
+ }
+}
+module.exports = useMagicNumbers()
+
diff --git a/lib/script.js b/lib/script.js
new file mode 100644
index 0000000..45e9905
--- /dev/null
+++ b/lib/script.js
@@ -0,0 +1,41 @@
+//script (runs async test as a script, with nothing clever, incase async_testing is causing errors)
+
+assert = require('assert')
+
+if (module == require.main) {
+ process.ARGV.shift()
+ process.ARGV.shift()
+ console.log(process.ARGV)
+ process.ARGV.forEach(runFile)
+}
+
+exports.runFile = runFile
+function runFile(file){
+ test = require(/*process.ENV.PWD + '/' +*/ file)
+ console.log()
+ console.log()
+ console.log("running test suite: " + file)
+
+ tests = Object.keys(test)
+ function next (i){
+
+ if (i >= tests.length){
+ console.log()
+ console.log("all tests completed!")//since an error should exit.
+ return
+ }
+
+ assert.finish = function (){
+ next(i + 1)
+ }
+
+ console.log()
+ console.log(" running test: " + tests[i])
+
+ test[tests[i]](assert)
+ }
+
+ next(0)
+
+}
+
diff --git a/lib/subtree.js b/lib/subtree.js
new file mode 100644
index 0000000..88dff67
--- /dev/null
+++ b/lib/subtree.js
@@ -0,0 +1,47 @@
+//subtree
+var assert = require('assert')
+ , inspect = require('util').inspect
+
+function assert_subtree(little,big,message,chain){
+ message = message || "";
+
+ //check that every property in little is also in big.
+ chain = chain || [];
+
+ if('object' === typeof little) {
+ for (var k in little) {
+ assert.ok(big[k], message
+ + "results did not have a property:"
+ + chain.join(".") + "." + k
+ + " expected " + inspect(little[k]))
+
+ t = assert_subtree(little[k],big[k],message,chain.concat([k]))
+ }
+ } else {
+ assert.notEqual(big,undefined, message
+ + "\nexpected results to contain "
+ + chain.join(".")
+ + " but was undefined");
+ assert.strictEqual(little,big, message
+ + "\nexpected "
+ + chain.join(".") + " === " + little
+ + " (" + typeof big + ")"
+ + " but found: " + big
+ + " (" + typeof big + ")"
+ );
+ }
+ }
+exports.assert_subtree = assert_subtree
+
+
+exports.subtree = function subtree(little,big){
+ try {
+ assert_subtree(little,big);
+ return true;
+ } catch (err){
+ console.log('error');
+ if (err instanceof assert.AssertionError) {
+ return false;
+ } else { throw err };
+ }
+ }
diff --git a/lib/tester.js b/lib/tester.js
new file mode 100644
index 0000000..47ec7fa
--- /dev/null
+++ b/lib/tester.js
@@ -0,0 +1,67 @@
+var path = require ('path')
+ , assert = require('assert')
+ , reports = require('meta-test/test_reports')
+
+
+
+function Tester (filename){
+ var dirname = path.dirname(filename)
+ this.run = run
+
+ function run(callbacks){
+
+
+ var report = reports(filename)
+ report.testNames = [report.name]
+
+ callbacks.onSuiteStart && callbacks.onSuiteStart(report.name,report.suiteStart())
+ callbacks.onTestStart && callbacks.onTestStart(report.name,report.testStart(report.name))
+
+ function onError (error){
+ console.log("ON ERROR!")
+ var r = report.testDone(report.name)
+ callbacks.onTestDone && callbacks.onTestDone(r.status,r)
+ }
+
+ process.on("uncaughtException",onError)
+
+ try{
+ require(filename)
+ } catch (error) { //catch sync error
+ return onError(error)
+ }
+/* callback('success',
+ { test:name
+ , status: 'success' } )*/
+
+ process.on('exit',function (code,status){
+ console.log("ON EXIT: SUITE DONE!")
+ console.log("ON EXIT()!" + !!callbacks.onExit)
+ try{r = report.suiteDone()
+ callbacks.onSuiteDone && callbacks.onSuiteDone(r.status,r)
+
+ callbacks.onExit && callbacks.onExit(code,status)
+
+ } catch (error){
+ console.log(JSON.stringify(error))
+ console.error(error.toString())
+ }
+ })
+
+ }
+}
+
+
+exports = module.exports = Tester
+module.exports.errorType = errorType
+exports.runTest = function (file,callbacks){
+ new Tester(file).run(callbacks)
+}
+
+function errorType(error){
+ if('object' == typeof error){
+ return error.name || error.constructor.name
+ } else {
+ return typeof error
+ }
+}
diff --git a/lib/testing.js b/lib/testing.js
index bd518b8..00a1055 100644
--- a/lib/testing.js
+++ b/lib/testing.js
@@ -2,7 +2,11 @@ var assert = require('assert')
, path = require('path')
, fs = require('fs')
, spawn = require('child_process').spawn
- ;
+ , messages = require('./messages')
+ , inspect = require('inspect')
+ exports.messageDecode = messages.messageDecode //moved these functions to messages.
+ exports.messageEncode = messages.messageEncode //exported them again so i didn't change the interface
+
/* Runs an object with tests. Each property in the object should be a
* test. A test is just a method.
@@ -22,6 +26,7 @@ var assert = require('assert')
* + onTestDone
* + onSuiteDone
*/
+
exports.runSuite = function(obj, options) {
// make sure options exists
options = options || {};
@@ -126,7 +131,11 @@ exports.runSuite = function(obj, options) {
}
function testAlreadyFinished(test, msg) {
- errorHandler(new TestAlreadyFinishedError(test.name + ' already finished!' + (msg ? ' ' + msg : '')), test);
+ console.log("test")
+ console.log(inspect(test))
+ console.log(msg)
+ if(!test.failure) // if the test has already errored, don't shadow it!
+ errorHandler(new TestAlreadyFinishedError(test.name + ' already finished!' + (msg ? ' ' + msg : '')), test);
}
// this is called after each step in a test (each function in the array).
@@ -144,37 +153,43 @@ exports.runSuite = function(obj, options) {
if (!test.failure && problem) {
test.failure = problem;
}
-
- if (test.func.length == test.history.length) {
- testFinished(test);
- }
- else {
- var index = test.history.length;
- var match = test.func.length - index - 1;
-
- if (match >= index) {
- // we are still drilling down into the flow, not doing teardowns
- if (test.failure) {
- // we had a failure, so we don't start any new functions
- test.history.push(false);
- testProgressed(test);
- }
- else {
- // no failure yet, start next step
- runTestFunc(test);
- }
+ if(!test.func){ // I don't know what this is about, but taking this out fixes it.
+ console.log("NO TEST FUNCTION")
+ console.log(test)
+ console.log()
+ console.log()
+ } else {
+ if ( test.func.length == test.history.length) {
+ testFinished(test);
}
else {
- // we are doing teardowns. We always run a teardown function if its
- // matching setup was run
- if (test.history[match]) {
- // according to the history we ran the match
- runTestFunc(test);
+ var index = test.history.length;
+ var match = test.func.length - index - 1;
+
+ if (match >= index) {
+ // we are still drilling down into the flow, not doing teardowns
+ if (test.failure) {
+ // we had a failure, so we don't start any new functions
+ test.history.push(false);
+ testProgressed(test);
+ }
+ else {
+ // no failure yet, start next step
+ runTestFunc(test);
+ }
}
else {
- // didn't run the match so don't run this
- test.history.push(false);
- testProgressed(test);
+ // we are doing teardowns. We always run a teardown function if its
+ // matching setup was run
+ if (test.history[match]) {
+ // according to the history we ran the match
+ runTestFunc(test);
+ }
+ else {
+ // didn't run the match so don't run this
+ test.history.push(false);
+ testProgressed(test);
+ }
}
}
}
@@ -283,14 +298,17 @@ exports.runSuite = function(obj, options) {
function exitHandler() {
if (suite.started.length > 0) {
- if (options.onSuiteDone) {
- options.onSuiteDone('exit', {tests: suite.started.map(function(t) { return t.name; })});
+ if (options.onSuiteDone) {
+ var tests = suite.started.map(function(t) { return t.name; })
+ console.log("SUITE FINISHED -- exitHandler 'exit' :" + tests)
+ options.onSuiteDone('exit', {tests: tests});
}
}
}
// clean up method which notifies all listeners of what happened
function suiteFinished() {
+ console.log("SUITE FINISHED -- onSuiteDone")
if (suite.finished) { return; }
suite.finished = true;
@@ -309,13 +327,14 @@ exports.runSuite = function(obj, options) {
suite.results.forEach(function(r) {
result[r.failure ? 'numFailures' : 'numSuccesses']++;
});
-
options.onSuiteDone('complete', result);
}
}
}
exports.runFile = function(modulepath, options) {
+console.log("runFile:" + modulepath)
+
options = options || {};
if (options.testName && !Array.isArray(options.testName)) {
options.testName = [options.testName];
@@ -354,6 +373,8 @@ exports.runFile = function(modulepath, options) {
});
child.stderr.on('close', function() {
+ console.log("strerr:" + errorBuffer)
+
if (errorBuffer && options.onSuiteDone) {
options.onSuiteDone('loadError', {stderr: errorBuffer.trim()});
}
@@ -504,41 +525,6 @@ exports.getTestsFromObject = function(o, filter, namespace) {
return tests;
}
-var messageFrame = "~m~";
-// these encode/decode functions inspired by socket.io's
-exports.messageDecode = function(lines) {
- return lines.map(function(str) {
- if (str.substr(0,3) !== messageFrame) {
- return str;
- }
-
- var msg = [];
- for (var i = 3, number = '', l = str.length; i < l; i++){
- var n = Number(str.substr(i, 1));
- if (str.substr(i, 1) == n){
- number += n;
- } else {
- number = Number(number);
- var m = str.substr(i+messageFrame.length, number);
- msg.push(JSON.parse(m));
- i += messageFrame.length*2 + number - 1;
- number = '';
- }
- }
- return msg;
- });
-}
-exports.messageEncode = function() {
- var r = '';
-
- for (var i = 0; i < arguments.length; i++) {
- var json = JSON.stringify(arguments[i]);
- r += messageFrame + json.length + messageFrame + json;
- }
-
- return r;
-}
-
var TestAlreadyFinishedError = function(message) {
this.name = "TestAlreadyFinishedError";
this.message = message;
diff --git a/lib/web-runner.js b/lib/web-runner.js
index d53ec62..6e8d63d 100644
--- a/lib/web-runner.js
+++ b/lib/web-runner.js
@@ -11,9 +11,9 @@ try {
}
catch(err) {
if( err.message == "Cannot find module 'util'" ) {
- var util = require('sys');
+ var util = require('sys');
+ }
}
-
exports.name = 'Web';
exports.runnerFlag =
diff --git a/lib/wrap.js b/lib/wrap.js
index 835fe11..3e83cb0 100644
--- a/lib/wrap.js
+++ b/lib/wrap.js
@@ -14,6 +14,9 @@ const PRESETUP = 0
* teardown: a function that should be run after the test
*/
exports.wrap = function(obj) {
+ console.log("returring suite!")
+// return obj.suite;
+// return obj.suite
if (!obj.suite) {
throw new Error('Cannot wrap suite. No suite provided');
}
diff --git a/test/assertions.asynct.js b/test/assertions.asynct.js
new file mode 100644
index 0000000..ec5b267
--- /dev/null
+++ b/test/assertions.asynct.js
@@ -0,0 +1,154 @@
+var inspect = require('util').inspect
+, EventEmitter = require('events').EventEmitter
+var truthy = [true,1]
+, falsey = [0,'',[]]
+, ok = [true,1,2,100,-1,"true",{},[],new Error()]
+, notOk = [false,0,null,undefined,""]
+
+exports['ok'] = function(test){
+
+ ok.forEach(function (t){
+ test.ok(t, "expected " + t + " to evaluate to true" )
+ });
+
+ notOk.forEach(function (t){
+ test.ok(!t, "expected " + t + " to !evaluate to true" )
+ });
+ test.finish();
+}
+
+exports['throws doesNotThrow'] = function (test){
+ var throwable = [new Error('throw me'),"thrown",7,null,undefined,[],{}]
+
+ throwable.forEach(function (t) {
+ test.throws(function(){
+ throw t
+ });
+ });
+ throwable.forEach(function (t) {
+ test.doesNotThrow(function(){
+ return t
+ });
+ });
+ throwable.forEach(function (t) {
+ test.throws(function(){
+ process.emit('error', t)
+ });
+ });
+ test.finish()
+}
+
+function comparison(test,method,a,b) {
+ test[method](a,b,"expected : " + method + "( " + inspect(a) + " , " + inspect(b) + " );")
+}
+exports['equals deepEquals strictEquals'] = function (test){
+ var c1 = [1,2,3]
+ , c2 = [1,2,3]
+
+ c1.push(c1);
+ c2.push(c2);
+ c3 = [1,2,3,c1]
+ /*
+ put a bunch of example comparisons in a hash by method name,
+ then iterate and apply the method
+ */
+ var comparisons = {
+ equal: [
+ [1,1]
+ , [2,2]
+ , [2,2.0]
+ , ['hello',"hello"]
+ , ['36',36]
+ , ['36.0',36]
+ , ['3.6e1',36]
+ , ['.36e2',36]
+ , [null,undefined]
+ , [c1,c1]
+ , [Array,Array]
+ , [true,1] // 'truthy' values
+ , [false,0]//falsey
+ , [false,'']
+ , [false,[]]
+ ]
+ , notEqual: [
+ [1,0]
+ , ['hello',"Hello"]
+ , [[],[]]
+ , [{},{}]
+ , [c1,c2]
+ , [c1,c3]
+ , [function(){},function(){}]
+ , [function(){},'function(){}']
+ , [true,2]
+ , [true,'true']
+ , [false,null]
+ , [false,undefined]
+ , [false,'false']
+ , [false,true]
+ , [false,{}]
+ ]
+ , strictEqual: [
+ [1,1]
+ , ['hello','hello']
+ , [c1,c1]
+ , [Array,Array]
+ , [true,true]
+ , [false,false]
+ , [test,test]
+ ]
+ , notStrictEqual: [
+ [1,'1']
+ , [null,undefined]
+ , [true,1] // 'truthy' values
+ , [false,0] // falsey
+ , [false,'']
+ , [false,[]]
+ , [new EventEmitter(),new EventEmitter()]//not stict equal unless same object
+ ]
+ , deepEqual: [
+ , [[],[]]
+ , [{},{}]
+ , [[1,2,3],[1,2,3]]
+ , [[1,2,3],['1','2.0','.3e1']]
+ , [{hello:'hi',goodbye:'bye'},{hello:'hi',goodbye:'bye'}]
+ , [[1,2,3,{}],[1,2,3,{}]]
+ , [c1,c1]
+ //, [c1,c2] // this causes stackoverflow.
+ , [c1,c3] //but this passes, since c1[3] === c1 and c3[3] === c1
+ , [[1,2,3,[],4],[1,2,3,[],4]]
+ , [[1,2,3,{},4],[1,2,3,{},4]]
+ , [[1,[2,3],[],4],[1,[2,3],[],4]]
+ , [new EventEmitter(),new EventEmitter()]//most new objects of same type should be equal
+ ]
+ , notDeepEqual: [
+ , [new Error(),new Error()]//when a error is created it stack trace gets set, and the message will differ by column number somewhere.
+ ]
+ }
+
+ for (method in comparisons) {
+ comparisons[method].forEach(function(e){
+ comparison(test,method,e[0],e[1])
+ });
+ }
+ test.finish();
+}
+/*
+ I've noticed that async_testing does not seem to report isError throws
+ correctly, make a meta test to fix this.
+
+ also, test should have an errorListener method which registers an error but
+ doesn't throw... & errorListenerThrows, incase thats useful too.
+*/
+
+exports['ifError'] = function (test){
+ //ifError is inverse of ok, but takes no message.
+ notOk.forEach(function (e){
+ test.ifError(e)
+ });
+ ok.forEach(function (e){
+ test.throws(function(){
+ test.ifError(e)
+ });
+ });
+ test.finish();
+}
diff --git a/test/async_testing.options.async.js b/test/async_testing.options.async.js
new file mode 100644
index 0000000..b17165f
--- /dev/null
+++ b/test/async_testing.options.async.js
@@ -0,0 +1,78 @@
+
+
+//check that runSuite callbacks are executed in order.
+ var expected = require('./examples/expected_results')
+ , subtree = require('async_testing/lib/subtree')
+ , asynct = require('async_testing')
+// , asynct = require('async_testing/lib/child_http')
+// , asynct = require('async_testing/lib/child2')
+
+//var testing = require('async_testing/lib/testing')
+ , inspect = require('util').inspect
+
+
+function checkCallbacks (test, filename,expected){
+ var tests = tests
+ , started = []
+ , finished = []
+
+ console.log()
+ console.log("***" + filename)
+
+ var tests = expected.tests.map(function (e){return e.name})
+ var reports = {}
+ expected.tests.forEach(function (e){
+ reports[e.name] = e
+ })
+
+ asynct.runFile(filename,{onTestStart:testStart,onTestDone:testDone,onSuiteDone:suiteDone})
+
+ function testStart(testName){
+ console.log(" testStarted: " + testName)
+
+ test.ok(testName,'testName must be non null')
+ test.ok(tests.indexOf(testName) !== -1, 'test \'' + testName + '\' must be in list of tests: ' + inspect (tests))
+ test.ok(started.indexOf(testName) === -1, 'test hasn\'t already started')
+ test.ok(finished.indexOf(testName) === -1, 'test hasn\'t already finished')
+
+ started.push(testName)
+ }
+ function testDone(status,report){
+ var testName = report.name
+
+ console.log(" ...testDone: " + report.name + " -> " + status)
+ test.ok(testName,'testName must be non null')
+ test.ok(tests.indexOf(testName) !== -1, 'test = ' + testName + ' must be in list of tests' + inspect (tests))
+ test.ok(started.indexOf(testName) !== -1, 'finished test must have already started')
+ test.ok(finished.indexOf(testName) === -1, 'test hasn\'t already finished')
+
+ subtree.assert_subtree(reports[testName],report)
+
+ started.splice(started.indexOf(testName),1)
+ finished.push(testName)
+ }
+ function suiteDone(status,report){
+ console.log("***" + filename + " DONE")
+
+ test.deepEqual(started,[],"onTestStart called for all tests, started tests where :" + inspect(started))
+ test.deepEqual(finished.sort(),tests.sort(),"onTestDone called for all tests")
+
+ subtree.assert_subtree(expected,report)
+
+
+ console.log()
+
+ test.finish()
+ }
+}
+
+//generate tests.
+ for (i in expected.expected){
+ (function (j){
+ exports[j] = function (test){
+ // var tests = expected.expected[j].tests.map(function (e){return e.name})
+ checkCallbacks(test,'async_testing/test/examples/' + j,expected.expected[j])
+ }
+ console.log(j)
+ })(i)
+ }
diff --git a/test/async_testing.reports.async.js b/test/async_testing.reports.async.js
new file mode 100644
index 0000000..b3c582d
--- /dev/null
+++ b/test/async_testing.reports.async.js
@@ -0,0 +1,39 @@
+
+if (module == require.main) {
+ require('async_testing').run(__filename, process.ARGV);
+}
+
+ var expected = require('./examples/expected_results')
+
+//var MetaTest = require('meta_test')
+, subtree = require('async_testing/lib/subtree')
+, inspect = require('util').inspect
+, asynct = require('async_testing')
+
+function runTest (test,filename,expected){
+// var m = MetaTest()
+
+// m.run(filename,{onSuiteDone: suiteDone})
+ console.log("test started: " + filename)
+ asynct.runFile(filename,{onSuiteDone: suiteDone})
+
+ function suiteDone(status,report){
+ console.log("...test done: " + filename)
+ subtree.assert_subtree(expected,report)
+ test.finish();
+ }
+}
+
+
+ for (i in expected.expected){
+ (function (j){
+ exports[j] = function (test){
+ // var tests = expected.expected[j].tests.map(function (e){return e.name})
+ runTest(test,'async_testing/test/examples/' + j,expected.expected[j])
+ }
+ console.log(j)
+ })(i)
+ }
+
+
+
diff --git a/test/child.asynct.js b/test/child.asynct.js
new file mode 100644
index 0000000..c4f305c
--- /dev/null
+++ b/test/child.asynct.js
@@ -0,0 +1,112 @@
+if (module == require.main) {
+ return require('async_testing').run(process.ARGV);
+}
+
+var child = require('async_testing/lib/child2')
+ , inspect = require('inspect')
+
+exports ['can run a simple test'] = function(test){
+
+ child.runFile('async_testing/test/examples/test-all_passing',{onSuiteDone: suiteDone})
+
+ function suiteDone(status,report){
+ console.log("ERROR:")
+ console.log(inspect(report))
+ test.equal(status,'complete')
+
+ // tset.equal(report.test == 'complete')
+ test.finish()
+ }
+
+}
+
+exports ['can make callbacks into message and back'] = function(test){
+
+ var message = 'asdfhasdflsdlf'
+ var masterCallbacks = {
+ send: function(m){
+ test.equal(m,message)
+ test.finish()
+ }
+ }
+
+ mm = child.makeMessage(masterCallbacks)
+
+ cb = child.makeCallbacks(mm,recieve)
+ cb.send(message)
+ function recieve(message){
+ child.parseMessage(message,masterCallbacks)
+ }
+}
+
+/*exports ['ignores noise'] = function(test){
+ child.parseMessage(message,test.ifError)
+}*/
+
+exports ['accepts test adapter'] = function (test){
+ var calls = [/*'onSuiteStart',*/'onTestStart','onTestDone','onSuiteDone','onExit']
+ var callbacks = { adapter: "async_testing/test/lib/dummy_test_adapter" }
+
+ calls.forEach(each)
+
+ function each(fName){
+ callbacks[fName] = function (status,data){
+ thisCall = calls.shift()
+ console.log("dummy test adapter called: " + thisCall + " expected:" + fName)
+ test.equal(thisCall,fName)
+ test.equal(status,fName)
+ test.deepEqual(data , {test: "dummy_test_adapter: " + fName, object: {magicNumber: 123471947194 } } )
+
+ if (calls.length == 0) {
+ test.finish()
+ }
+ }
+ }
+
+ child = require('async_testing/lib/child2')
+ child.runFile("async_testing/test/lib/magic_number" ,callbacks)
+}
+
+exports ['calls onSuiteDone(\'loadError\') if child did not exit properly.'
+ + ' example: syntax error'] = function (test) {
+
+ var callbacks =
+ { adapter: "async_testing/test/lib/dummy_test_adapter"
+ , onSuiteDone: done }
+
+ function done(loadError,data){
+ console.log(data)
+ test.equal(loadError,'loadError')
+ test.finish()
+ }
+
+ child = require('async_testing/lib/child2')
+ child.runFile("async_testing/test/examples/test-error_syntax" ,callbacks)
+}
+
+
+exports ['calls onSuiteDone(\'loadError\') does not confuse stderr with real loadError.'] = function (test) {
+
+ var callbacks =
+ { adapter: "async_testing/test/lib/dummy_test_adapter"
+ , onSuiteDone: done }
+
+ function done(onSuiteDone,data){
+ console.log(data)
+ test.equal(onSuiteDone,'onSuiteDone')
+ process.nextTick(test.finish)
+ }
+
+ child = require('async_testing/lib/child2')
+ child.runFile("async_testing/test/lib/stderr" ,callbacks)
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/test/examples/async_error.script.js b/test/examples/async_error.script.js
new file mode 100644
index 0000000..6103216
--- /dev/null
+++ b/test/examples/async_error.script.js
@@ -0,0 +1,2 @@
+
+process.nextTick(function (){throw new Error("Async Error")})
diff --git a/test/examples/error.script.js b/test/examples/error.script.js
new file mode 100644
index 0000000..baae828
--- /dev/null
+++ b/test/examples/error.script.js
@@ -0,0 +1,6 @@
+
+//require('assert').ok(false, "INTENSIONAL FAIL")
+
+throw new Error ("INTENSIONAL ERROR")
+
+
diff --git a/test/examples/expected_results.js b/test/examples/expected_results.js
new file mode 100644
index 0000000..642a1b1
--- /dev/null
+++ b/test/examples/expected_results.js
@@ -0,0 +1,203 @@
+//expected results
+
+var tests = 'async_testing/test'
+exports.expected =
+ { 'test-all_passing':
+ { tests:
+ [ {name: 'test A'
+ //, status: 'success'
+ }
+ , {name: 'test B'
+ //, status: 'success'
+ }
+ , {name: 'test C'
+ //, status: 'success'
+ }
+ , {name: 'test D'
+ //, status: 'success'
+ }
+ ]
+ }
+ , 'test-async_assertions':
+ { tests: [
+ { name: 'test success'
+ //, status: 'success'
+ }
+ , { name: 'test fail'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ , { name: 'test success -- numAssertions expected'
+ //, status: 'success'
+ }
+ , { name: 'test fail -- numAssertions expected'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ , { name: 'test fail - not enough -- numAssertions expected'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ , { name: 'test fail - too many -- numAssertions expected'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ ]
+ }
+ , 'test-custom_assertions':
+ { tests: [
+ {name: 'test custom assertion pass'
+ //, status: 'success'
+ }
+ , {name: 'test custom assertion fail'
+ //, status: 'failure'
+ , failureType: 'assertion'
+ }
+ ]
+ }
+ , 'test-errors':
+ { tests: [
+ {name: 'test sync error'
+ //, status: 'error'
+ , failure: {}
+ , failureType: 'error'
+ }
+ , {name: 'test async error'
+ //, status: 'error'
+ , failure: {}
+ , failureType: 'error'
+ }
+ ]
+ }
+ , 'test-multiple_errors':
+ { tests: [
+ {name: 'test async error 1'
+ //, status: 'error'
+ , failure: {}
+ , failureType: 'error'
+ }
+ , {name: 'test sync error'
+ //, status: 'error'
+ , failure: {}
+ , failureType: 'error'
+ }
+ , {name: 'test async error 2'
+ //, status: 'error'
+ , failure: {}
+ , failureType: 'error'
+ }
+ , {name: 'test async error 3'
+ //, status: 'error'
+ , failure: {}
+ , failureType: 'error'
+ }
+ ]
+ }
+ , 'test-sync_assertions':
+ { tests: [
+ {name: 'test success'
+ //, status: 'success'
+ }
+ , {name: 'test fail'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ , {name: 'test success -- numAssertions expected'
+ //, status: 'success'
+ }
+ , {name: 'test fail -- numAssertions expected'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ , {name: 'test fail - not enough -- numAssertions expected'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ , {name: 'test fail - too many -- numAssertions expected'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ ]
+ }
+ , 'test-uncaught_exception_handlers':
+ { tests: [
+ {name: 'test catch sync error'
+ //, status: 'success'
+ }
+ , {name: 'test catch async error'
+ //, status: 'success'
+ }
+ , {name: 'test sync error fail'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ , {name: 'test async error fail'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ , {name: 'test sync error async fail'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+ , {name: 'test async error async fail'
+ //, status: 'failure'
+ , failure: {}
+ , failureType: 'assertion'
+ }
+/* , {name: 'test sync error error again'
+ //, status: 'error'
+ , failure: {}
+ , failureType: 'error'
+ }
+ , {name: 'test async error error again'
+ //, status: 'error'
+ , failure: {}
+ , failureType: 'error'
+ }
+ , {name: 'test sync error error again async'
+ //, status: 'error'
+ , failure: {}
+ , failureType: 'error'
+ }
+ , {name: 'test async error error again async'
+ //, status: 'error'
+ , failure: {}
+ , failureType: 'error'
+ }*/
+ ]
+ }
+ , 'test-wrap_tests':
+ { tests: [
+ {name: 'sync wrap → test'
+ //, status: 'success'
+ }
+ , {name: 'async setup → test'
+ //, status: 'success'
+ }
+ , {name: 'async teardown → test'
+ //, status: 'error'
+ }
+ /* , {name: 'test teardown → test'
+ //, status: 'success'
+ }
+ , {name: 'test teardown async → test'
+ //, status: 'success'
+ }*/
+ ]
+ }
+}
+
+
+
+
diff --git a/test/examples/fail.script.js b/test/examples/fail.script.js
new file mode 100644
index 0000000..807dc7e
--- /dev/null
+++ b/test/examples/fail.script.js
@@ -0,0 +1,4 @@
+
+require('assert').ok(false, "INTENSIONAL FAIL")
+
+
diff --git a/test/examples/invalid/test-example1.js b/test/examples/invalid/test-example1.js
new file mode 100644
index 0000000..00de4ce
--- /dev/null
+++ b/test/examples/invalid/test-example1.js
@@ -0,0 +1,15 @@
+
+exports['test pass'] = function (test){
+ test.ok(true);
+ test.finish();
+}
+
+exports['test fail'] = function (test){
+ test.ok(false);
+ test.finish();
+}
+
+exports['test error'] = function (test){
+ throw new Error('INTENSIONAL ERROR')
+}
+
diff --git a/test/examples/invalid/test-finish_then_hang.js b/test/examples/invalid/test-finish_then_hang.js
new file mode 100644
index 0000000..bc12256
--- /dev/null
+++ b/test/examples/invalid/test-finish_then_hang.js
@@ -0,0 +1,7 @@
+
+exports['not finished'] = function (test){
+ test.finish()
+ process.nextTick(function (){while(true){}})
+}
+
+
diff --git a/test/examples/invalid/test-hang.js b/test/examples/invalid/test-hang.js
new file mode 100644
index 0000000..e510cc9
--- /dev/null
+++ b/test/examples/invalid/test-hang.js
@@ -0,0 +1,6 @@
+
+exports['not finished'] = function (test){
+ while(true){}
+}
+
+
diff --git a/test/examples/invalid/test-not_finish.js b/test/examples/invalid/test-not_finish.js
new file mode 100644
index 0000000..7202f84
--- /dev/null
+++ b/test/examples/invalid/test-not_finish.js
@@ -0,0 +1,8 @@
+
+exports['not finished'] = function (test){
+ test.ok(true);
+
+ process.exit();
+}
+
+
diff --git a/test/examples/invalid/test-one_pass.js b/test/examples/invalid/test-one_pass.js
new file mode 100644
index 0000000..6244ebf
--- /dev/null
+++ b/test/examples/invalid/test-one_pass.js
@@ -0,0 +1,5 @@
+
+exports['pass'] = function (test){
+ test.ok(true);
+ test.finish();
+}
diff --git a/test/examples/pass.script.js b/test/examples/pass.script.js
new file mode 100644
index 0000000..e5b2056
--- /dev/null
+++ b/test/examples/pass.script.js
@@ -0,0 +1,7 @@
+
+process.on('exit',function(x){
+console.log('passing test')
+console.log()
+
+
+})
diff --git a/test/test-all_passing.js b/test/examples/test-all_passing.js
similarity index 84%
rename from test/test-all_passing.js
rename to test/examples/test-all_passing.js
index e805a5e..2aa8685 100644
--- a/test/test-all_passing.js
+++ b/test/examples/test-all_passing.js
@@ -1,5 +1,5 @@
if (module == require.main) {
- return require('../lib/async_testing').run(process.ARGV);
+// return require('../lib/async_testing').run(process.ARGV);
}
module.exports = {
diff --git a/test/test-async_assertions.js b/test/examples/test-async_assertions.js
similarity index 88%
rename from test/test-async_assertions.js
rename to test/examples/test-async_assertions.js
index 40ee2df..bcbe5ad 100644
--- a/test/test-async_assertions.js
+++ b/test/examples/test-async_assertions.js
@@ -2,6 +2,8 @@ if (module == require.main) {
return require('../lib/async_testing').run(process.ARGV);
}
+var u = require('util')
+
module.exports = {
'test success': function(test) {
setTimeout(function() {
@@ -12,8 +14,12 @@ module.exports = {
'test fail': function(test) {
setTimeout(function() {
+// console.log("~m~12~m~sdfhlasflasdjflasjdkasdhfklasdhfod")
+
+//u.print('ccccccccccccccccccccccccc')
test.ok(false, 'This should be false');
test.finish();
+//u.print('ccccccccccccccccccccccccc')
}, 500);
},
diff --git a/test/test-custom_assertions.js b/test/examples/test-custom_assertions.js
similarity index 88%
rename from test/test-custom_assertions.js
rename to test/examples/test-custom_assertions.js
index 2873650..2ae659b 100644
--- a/test/test-custom_assertions.js
+++ b/test/examples/test-custom_assertions.js
@@ -1,5 +1,7 @@
-var async_testing = require('../lib/async_testing');
+//require('sys')
+
+var async_testing = require('async_testing');
if (module == require.main) {
return async_testing.run(process.ARGV);
}
diff --git a/test/examples/test-empty.js b/test/examples/test-empty.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/test-error_async.js b/test/examples/test-error_async.js
similarity index 100%
rename from test/test-error_async.js
rename to test/examples/test-error_async.js
diff --git a/test/test-error_outside_suite.js b/test/examples/test-error_outside_suite.js
similarity index 100%
rename from test/test-error_outside_suite.js
rename to test/examples/test-error_outside_suite.js
diff --git a/test/test-error_sync.js b/test/examples/test-error_sync.js
similarity index 100%
rename from test/test-error_sync.js
rename to test/examples/test-error_sync.js
diff --git a/test/test-error_syntax.js b/test/examples/test-error_syntax.js
similarity index 100%
rename from test/test-error_syntax.js
rename to test/examples/test-error_syntax.js
diff --git a/test/test-error_test_already_finished.js b/test/examples/test-error_test_already_finished.js
similarity index 99%
rename from test/test-error_test_already_finished.js
rename to test/examples/test-error_test_already_finished.js
index 23b0009..081cd07 100644
--- a/test/test-error_test_already_finished.js
+++ b/test/examples/test-error_test_already_finished.js
@@ -8,3 +8,4 @@ module.exports = {
test.finish();
},
}
+
diff --git a/test/test-error_test_already_finished_async.js b/test/examples/test-error_test_already_finished_async.js
similarity index 100%
rename from test/test-error_test_already_finished_async.js
rename to test/examples/test-error_test_already_finished_async.js
diff --git a/test/examples/test-error_test_already_finished_then_assertion.js b/test/examples/test-error_test_already_finished_then_assertion.js
new file mode 100644
index 0000000..bf34270
--- /dev/null
+++ b/test/examples/test-error_test_already_finished_then_assertion.js
@@ -0,0 +1,10 @@
+
+if (module == require.main) {
+ return require('../lib/async_testing').run(process.ARGV);
+}
+module.exports = {
+ 'test sync already finished then assertion': function(test) {
+ test.finish();
+ test.ok(true,'this should fail');
+ },
+}
diff --git a/test/test-error_uncaught_exception_handler.js b/test/examples/test-error_uncaught_exception_handler.js
similarity index 100%
rename from test/test-error_uncaught_exception_handler.js
rename to test/examples/test-error_uncaught_exception_handler.js
diff --git a/test/examples/test-errors.js b/test/examples/test-errors.js
new file mode 100644
index 0000000..0b18e63
--- /dev/null
+++ b/test/examples/test-errors.js
@@ -0,0 +1,14 @@
+
+exports['test sync error'] = function(test) {
+ throw new Error();
+};
+
+exports['test async error'] = function(test) {
+ process.nextTick(function() {
+ throw new Error();
+ });
+};
+
+if (module == require.main) {
+ require('../lib/async_testing').run(__filename, process.ARGV);
+}
diff --git a/test/examples/test-multiple_errors.js b/test/examples/test-multiple_errors.js
new file mode 100644
index 0000000..940e57b
--- /dev/null
+++ b/test/examples/test-multiple_errors.js
@@ -0,0 +1,26 @@
+
+exports['test async error 1'] = function(test) {
+ process.nextTick(function() {
+ throw new Error();
+ });
+};
+
+exports['test sync error'] = function(test) {
+ throw new Error('Oooops');
+};
+
+exports['test async error 2'] = function(test) {
+ process.nextTick(function() {
+ throw new Error();
+ });
+};
+
+exports['test async error 3'] = function(test) {
+ process.nextTick(function() {
+ throw new Error();
+ });
+};
+
+if (module == require.main) {
+ require('../lib/async_testing').run(__filename, process.ARGV);
+}
diff --git a/test/test-overview.js b/test/examples/test-overview.js
similarity index 100%
rename from test/test-overview.js
rename to test/examples/test-overview.js
diff --git a/test/examples/test-parse_run_arguments.js b/test/examples/test-parse_run_arguments.js
new file mode 100644
index 0000000..bccaba4
--- /dev/null
+++ b/test/examples/test-parse_run_arguments.js
@@ -0,0 +1,165 @@
+if (module == require.main) {
+ return require('../lib/async_testing').run(process.ARGV);
+}
+
+var parse = require('../lib/running').parseRunArguments;
+
+var flags =
+ { 'group':
+ [ { longFlag: 'first'
+ }
+ , { longFlag: 'flag-with-dashes'
+ }
+ , { longFlag: 'single'
+ , takesValue: 'number'
+ }
+ , { longFlag: 'multiple'
+ , takesValue: 'number'
+ , multiple: true
+ }
+ , { longFlag: 'key'
+ , key: 'keyed'
+ }
+ , { longFlag: 'value'
+ , value: 42
+ }
+ , { longFlag: 'value0'
+ , value: 0
+ }
+ , { longFlag: 'value-key'
+ , key: 'keyedValued'
+ , value: 10
+ }
+ ]
+ };
+
+module.exports =
+ { 'test string': function(test) {
+ var l = [];
+ var o = {};
+
+ parse(['name'], l, o, flags);
+
+ test.deepEqual(['name'], l);
+ test.deepEqual({}, o);
+ test.finish();
+ }
+ , 'test object': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([{first: true}], l, o, flags);
+
+ test.deepEqual([], l);
+ test.deepEqual({first: true}, o);
+ test.finish();
+ }
+ , 'test array': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['name', '--first']], l, o, flags);
+
+ test.deepEqual({first: true}, o);
+ test.finish();
+ }
+ , 'test order1': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([{first: false}, ['--first']], l, o, flags);
+
+ test.deepEqual({first: true}, o);
+ test.finish();
+ }
+ , 'test order2': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['--first'], {first: false}], l, o, flags);
+
+ test.deepEqual({first: false}, o);
+ test.finish();
+ }
+ , 'test flag -> key conversion': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['--flag-with-dashes']], l, o, flags);
+
+ test.deepEqual({'flagWithDashes': true}, o);
+ test.finish();
+ }
+ , 'test single once': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['--single', 'one']], l, o, flags);
+
+ test.deepEqual({'single': 'one'}, o);
+ test.finish();
+ }
+ , 'test single twice': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['--single', 'one', '--single', 'two']], l, o, flags);
+
+ test.deepEqual({'single': 'two'}, o);
+ test.finish();
+ }
+ , 'test multiple once': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['--multiple', 'one']], l, o, flags);
+
+ test.deepEqual({'multiple': ['one']}, o);
+ test.finish();
+ }
+ , 'test multiple twice': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['--multiple', 'one', '--multiple', 'two']], l, o, flags);
+
+ test.deepEqual({'multiple': ['one','two']}, o);
+ test.finish();
+ }
+ , 'test key': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['--key']], l, o, flags);
+
+ test.deepEqual({'keyed': true}, o);
+ test.finish();
+ }
+ , 'test value': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['--value']], l, o, flags);
+
+ test.deepEqual({'value': 42}, o);
+ test.finish();
+ }
+ , 'test 0 value': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['--value0']], l, o, flags);
+
+ test.deepEqual({'value0': 0}, o);
+ test.finish();
+ }
+ , 'test value and key': function(test) {
+ var l = [];
+ var o = {};
+
+ parse([['--value-key']], l, o, flags);
+
+ test.deepEqual({'keyedValued': 10}, o);
+ test.finish();
+ }
+ };
diff --git a/test/examples/test-stderr.js b/test/examples/test-stderr.js
new file mode 100644
index 0000000..fed8a76
--- /dev/null
+++ b/test/examples/test-stderr.js
@@ -0,0 +1,6 @@
+exports.stderr = function (){
+
+ require('sys') //generate some stderr
+ console.error('standard error.... again')
+
+}
diff --git a/test/test-sub_suites.js b/test/examples/test-sub_suites.js
similarity index 100%
rename from test/test-sub_suites.js
rename to test/examples/test-sub_suites.js
diff --git a/test/test-sync_assertions.js b/test/examples/test-sync_assertions.js
similarity index 74%
rename from test/test-sync_assertions.js
rename to test/examples/test-sync_assertions.js
index e279cae..9e9553d 100644
--- a/test/test-sync_assertions.js
+++ b/test/examples/test-sync_assertions.js
@@ -13,24 +13,24 @@ module.exports = {
test.finish();
},
- 'test success -- numAssertionsExpected': function(test) {
+ 'test success -- numAssertions expected': function(test) {
test.numAssertions = 1;
test.ok(true, 'This should be true');
test.finish();
},
- 'test fail -- numAssertionsExpected': function(test) {
+ 'test fail -- numAssertions expected': function(test) {
test.numAssertions = 1;
test.ok(false, 'fail -- numAssertions expected shouldn\'t overwrite failures');
test.finish();
},
- 'test fail - not enough -- numAssertionsExpected': function(test) {
+ 'test fail - not enough -- numAssertions expected': function(test) {
test.numAssertions = 1;
test.finish();
},
- 'test fail - too many -- numAssertionsExpected': function(test) {
+ 'test fail - too many -- numAssertions expected': function(test) {
test.numAssertions = 1;
test.ok(true, 'This should be true');
test.ok(true, 'This should be true');
diff --git a/test/examples/test-throw_null.js b/test/examples/test-throw_null.js
new file mode 100644
index 0000000..bced2da
--- /dev/null
+++ b/test/examples/test-throw_null.js
@@ -0,0 +1,25 @@
+
+exports ['throw null makes test fail'] = function (test){
+ //throw 'string'
+ throw null
+}
+
+if(require.main === module){
+ require('async_testing').run(process.argv)
+ require('async_testing').runSuite(module.exports,{onSuiteDone: d})
+
+ function d(status,report){
+ console.log(status)
+ console.log(report)
+ /*
+ complete
+ { tests:
+ [ { name: 'throw null makes test fail',
+ numAssertions: 0 } ],
+ numFailures: 0,
+ numSuccesses: 1 }
+ */
+ }
+}
+
+
diff --git a/test/test-uncaught_exception_handlers.js b/test/examples/test-uncaught_exception_handlers.js
similarity index 100%
rename from test/test-uncaught_exception_handlers.js
rename to test/examples/test-uncaught_exception_handlers.js
diff --git a/test/test-wrap_tests.js b/test/examples/test-wrap_tests.js
similarity index 97%
rename from test/test-wrap_tests.js
rename to test/examples/test-wrap_tests.js
index 4e57ced..b344f54 100644
--- a/test/test-wrap_tests.js
+++ b/test/examples/test-wrap_tests.js
@@ -1,4 +1,4 @@
-var async_testing = require('../lib/async_testing')
+var async_testing = require('async_testing')
, wrap = async_testing.wrap
;
diff --git a/test/examples/throw_string.script.js b/test/examples/throw_string.script.js
new file mode 100644
index 0000000..a30eaca
--- /dev/null
+++ b/test/examples/throw_string.script.js
@@ -0,0 +1,6 @@
+
+//require('assert').ok(false, "INTENSIONAL FAIL")
+
+throw "INTENSIONAL STRING THROW"
+
+
diff --git a/test/lib/dummy_test_adapter.js b/test/lib/dummy_test_adapter.js
new file mode 100644
index 0000000..ca64d40
--- /dev/null
+++ b/test/lib/dummy_test_adapter.js
@@ -0,0 +1,38 @@
+
+
+exports.runTest = runTest
+
+function runTest(file,callbacks){
+ var test = require(file)
+/*
+ if(callbacks.onSuiteStart){
+ callbacks.onSuiteStart('onSuiteStart', {test: "dummy_test_adapter: onSuiteStart", object: test})
+ }
+ process.nextTick(c)
+ function c (){*/
+ if(callbacks.onTestStart){
+ callbacks.onTestStart('onTestStart', {test: "dummy_test_adapter: onTestStart", object: test})
+ }
+ process.nextTick(c)
+ function c (){
+ console.log("DUMMY TEST ADAPTER: call onTestDone")
+ if(callbacks.onTestDone){
+ callbacks.onTestDone('onTestDone', {test: "dummy_test_adapter: onTestDone", object: test})
+ }
+ process.nextTick(c)
+ function c (){
+ console.log("DUMMY TEST ADAPTER: call onSuiteDone")
+ if(callbacks.onSuiteDone){
+ callbacks.onSuiteDone('onSuiteDone', {test: "dummy_test_adapter: onSuiteDone", object: test})
+ }
+ process.nextTick(c)
+ function c (){
+ console.log("DUMMY TEST ADAPTER: call onSuiteDone")
+ if(callbacks.onExit){
+ callbacks.onExit('onExit', {test: "dummy_test_adapter: onExit", object: test})//to mark a normal exit.
+ }
+ }
+ }
+ }
+ //}
+}
diff --git a/test/lib/magic_number.js b/test/lib/magic_number.js
new file mode 100644
index 0000000..f2ac87c
--- /dev/null
+++ b/test/lib/magic_number.js
@@ -0,0 +1,3 @@
+
+
+exports.magicNumber = 123471947194
diff --git a/test/lib/stderr.js b/test/lib/stderr.js
new file mode 100644
index 0000000..6776eba
--- /dev/null
+++ b/test/lib/stderr.js
@@ -0,0 +1,3 @@
+
+// require('sys')
+ console.error('standard error.... again')
diff --git a/test/messages.asynct.js b/test/messages.asynct.js
new file mode 100644
index 0000000..e0ce32e
--- /dev/null
+++ b/test/messages.asynct.js
@@ -0,0 +1,55 @@
+
+var messages = require('async_testing/lib/messages2')
+ , inspect = require('util').inspect
+ , examples =
+ [ "hello"
+ , 37
+ , 42
+ , null
+ , ''
+ , []
+ , [24,235,436234]
+ , {hello: ['a','b','c']}
+ ]
+exports ['(standard interface) messageDecode (messageEncode(X).split(\'\n\')) returns X'] = function(test) {
+
+ function checkEncodeDecode(x){
+ console.log("message:" + messages.messageEncode(x))
+ test.deepEqual(messages.messageDecode(messages.messageEncode(x).split('\n')),[x])
+ }
+
+ examples.forEach(checkEncodeDecode)
+ checkEncodeDecode(examples)
+
+ test.finish()
+}
+
+exports ['test that messages still works in noise'] = function (test){
+ var noises =
+ [ "dffjasldfjdlsjf"
+ , '0'
+ , ' '
+ , '___'
+ , '~'
+ , '~m~4' ]
+
+ function checkEncodeDecodeWithNoise(x,noise){
+
+ console.log("message:" + messages.messageEncode(x))
+ test.deepEqual(messages.messageDecode((noise + messages.messageEncode(x)).split('\n')),[x])
+ test.deepEqual(messages.messageDecode((messages.messageEncode(x) + noise).split('\n')),[x])
+ }
+
+ noises.forEach(function (n){
+ examples.forEach(function(e){checkEncodeDecodeWithNoise(e,n)})
+ })
+ checkEncodeDecodeWithNoise(examples,"asflasdfjlsdf")
+ test.finish()
+}
+
+exports ['useMagicNumbers'] = function (test){
+ test.ok(messages.useMagicNumbers)
+ messager = messages.useMagicNumbers({start: 213,end:32425})
+ test.ok(messager.useMagicNumbers)
+ test.finish()
+}
diff --git a/test/subtree.asynct.js b/test/subtree.asynct.js
new file mode 100644
index 0000000..53b76b2
--- /dev/null
+++ b/test/subtree.asynct.js
@@ -0,0 +1,58 @@
+var subtree = require("async_testing/lib/subtree")
+, sys = require('util');
+
+
+function sb (test,little,big,bool) {
+ var bool = bool === undefined ? true : false
+ , m = bool ? 'doesNotThrow' : 'throws';
+ /*sys.puts("bool " + bool);
+ sys.puts("little " + sys.inspect(little));
+ sys.puts("big " + sys.inspect(big));*/
+
+ test[m](function(){subtree.assert_subtree(little,big)});
+ test.ok(bool === subtree.subtree(little,big),"expected: subtree of " + sys.inspect(big) + " but got " + sys.inspect(little));
+// subtree.subtree
+}
+exports.test_subtree = function (test) {
+ var little = {a: "a",b:"b"}
+ , big = {a: "a",b:"b",c:"c"}
+ , little2 = {a: "a",b:"b",d:'DEE'}
+ sb(test,little,big);
+ sb(test,little,little2);
+// test.ok(subtree.subtree(little,little2),"expected: subtree of " + sys.inspect(big) + " but got " + sys.inspect(little));
+// test.ok(!subtree.subtree(little2,big),"expected: subtree of " + sys.inspect(big) + " but got " + sys.inspect(little));
+
+ test.finish();
+}
+
+exports.test_subtree_errors = function (test) {
+ var little = {a: "a",b:"b"}
+ , big = {a: "a",b:"b",c:"c"}
+ , little2 = {a: "a",b:"b",d:'DEE'}
+// sb(test,big,little);
+ subtree.assert_subtree(little,big);
+ test.throws(function(){
+ subtree.assert_subtree(big,little);
+ });
+ test.finish();
+}
+
+exports.test_subtree_object = function (test) {
+ var little = {a: "a",b:"b",d:{}}
+ , big = {a: "a",b:"b",c:"c",d:{hi: "hello"}}
+ , big2 = {a: "a",b:"b"}
+ subtree.assert_subtree(little,big);
+ test.throws(function(){
+ subtree.assert_subtree(little,big2);
+ });
+ test.finish();
+}
+
+
+if (module == require.main) {
+ require('async_testing').run(__filename, process.ARGV);
+}
+
+
+
+
diff --git a/test/tester.asynct.js b/test/tester.asynct.js
new file mode 100644
index 0000000..a4cd2eb
--- /dev/null
+++ b/test/tester.asynct.js
@@ -0,0 +1,158 @@
+
+var child = require('async_testing/lib/child2')
+ , inspect = require('inspect')
+ , Tester = require('async_testing/lib/tester')
+ , subtree = require('async_testing/lib/subtree')
+
+//tester.script.asynct.js
+
+/*
+ OKAY!
+ refactor this to run in a child process...
+
+ i've altered child2 so that you call it with a test adapter.
+
+ NEXT: try loading tester as an adapter for child2.
+*/
+
+
+/*
+exports ['can accept a file and return tests for that file'] = function (test){
+
+ t = new Tester ('./examples/pass.script')
+ test.deepEqual(t.tests,['pass.script'])
+ test.finish()
+}
+*/
+ /*
+ am i gonna have to run all tests as a seperate process?
+ that may be the most comprehensive solution...
+
+ or design this to run around the test in the seperate process?
+ - to ensure reporting is correct?
+ - so child 2 is passed the test, then calls this, which calls the test.
+ - child2 just handles communicating results.
+ - this is the adapter to the test framework, & handles making reports
+ */
+// test.finish()
+/*
+exports ['can run a test'] = function (test){
+
+ t = new Tester ('async_testing/test/examples/pass.script')
+ test.deepEqual(t.tests,['pass.script'])
+
+ t.run('pass.script',done)
+
+ function done (status,data){
+ var expected =
+ { test:'pass.script'
+ , status: 'success'
+ }
+ test.equal(status,'success', "expected success:\n" + inspect(data))
+ subtree.assert_subtree(expected,data)
+ test.finish()
+ }
+}
+
+
+exports ['can run a failing test'] = function (test){
+
+ var t = new Tester ('async_testing/test/examples/fail.script')
+ , name = 'fail.script'
+ test.deepEqual(t.tests,[name])
+
+ t.run(name,done)
+
+ function done (status,data){
+ var expected =
+ { test:name
+ , status: 'failure'
+ , failureType: 'AssertionError' //actual type of error. will be string if a string is thrown.
+ , failure: {}
+ }
+ test.equal(status,'failure', "expected 'failure', got:" + status + "\n" + inspect(data))
+ subtree.assert_subtree(expected,data)
+ test.finish()
+ }
+}
+
+
+exports ['can run an erroring test'] = function (test){
+
+ var t = new Tester ('async_testing/test/examples/error.script')
+ , name = 'error.script'
+ , expectedStatus = 'error'
+
+ test.deepEqual(t.tests,[name])
+
+ t.run(name,done)
+
+ function done (status,data){
+ var expected =
+ { test:name
+ , status: expectedStatus
+ , failureType: 'Error' //actual type of error. will be string if a string is thrown.
+ , failure: {} }
+
+ test.equal(status,expectedStatus, "expected '" + expectedStatus + "', got:" + status + "\n" + inspect(data))
+ subtree.assert_subtree(expected,data)
+ test.finish()
+ }
+}
+
+exports ['can run an erroring test, non error thrown'] = function (test){
+
+ var t = new Tester ('async_testing/test/examples/throw_string.script')
+ , name = 'throw_string.script'
+ , expectedStatus = 'error'
+
+ test.deepEqual(t.tests,[name])
+
+ t.run(name,done)
+
+ function done (status,data){
+ var expected =
+ { test:name
+ , status: expectedStatus
+ , failureType: 'string' //actual type of error. will be string if a string is thrown.
+ , failure: "INTENSIONAL STRING THROW"
+ }
+ test.equal(status,expectedStatus, "expected '" + expectedStatus + "', got:" + status + "\n" + inspect(data))
+ subtree.assert_subtree(expected,data)
+ test.finish()
+ }
+}
+*/
+exports ['can run an erroring test, async error'] = function (test){
+
+/*
+ to cleanly catch this sort of error, without interfering with THIS test frameworkm
+ run this test in another process.
+
+ -- or use a script test instead of an asynct test...
+*/
+ var cb = {adapter: "async_testing/lib/tester", onSuiteDone: done}
+
+ child.runFile('async_testing/test/examples/async_error.script',cb)
+// var t = new Tester ()
+ , name = 'async_error.script'
+ , expectedStatus = 'error'
+
+ function done (status,data){
+ var expected =
+ { test:name
+ , status: expectedStatus
+ , failureType: 'string' //actual type of error. will be string if a string is thrown.
+ , failure: "INTENSIONAL STRING THROW"
+ }
+ test.equal(status,expectedStatus, "expected '" + expectedStatus + "', got:" + status + "\n" + inspect(data))
+// subtree.assert_subtree(expected,data)
+
+ //now that I have a good error reporting structure.
+ //I can use it to define what the test results should be!
+
+ test.finish()
+ }
+}
+
+
diff --git a/todo.txt b/todo.txt
index de0fe88..f4239c1 100644
--- a/todo.txt
+++ b/todo.txt
@@ -55,3 +55,4 @@ Docs
----
+ update docs and add list of command line arguments for run and what they do
+ add note about contributing/contacting
+