diff --git a/bin/cli.js b/bin/cli.js index dade70a..d131ac0 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -8,7 +8,7 @@ var root = __dirname + '/..', args = argsparser.parse(), testrunner = require(root), o = testrunner.options, - code, tests, + code, tests, debug, help; help = '' @@ -17,6 +17,7 @@ help = '' + '\nOptions:' + '\n -c, --code path to code you want to test' + '\n -t, --tests path to tests (space separated)' + + '\n --debug debugging port' + '\n -d, --deps dependency paths - files required before code (space separated)' + '\n -l, --log logging options, json have to be used' + '\n --cov create tests coverage report' @@ -65,6 +66,9 @@ for (var key in args) { // of QUnit in browsers. tests = args[key]; break; + case '--debug': + debug = args[key]; + break; case '-d': case '--deps': o.deps = args[key]; @@ -105,7 +109,11 @@ if(!code || !tests) { return; } -testrunner.run({ code: code, tests: tests, deps: o.deps, log: o.log }, function(err, stats) { +debug = debug || process.execArgv.reduce(function (prevArg, curArg) { + return prevArg || curArg.indexOf('--debug') === 0; +}, false); + +testrunner.run({ code: code, tests: tests, deps: o.deps, log: o.log, debug: debug }, function(err, stats) { if (err) { console.error(err); process.exit(1); diff --git a/lib/child.js b/lib/child.js index a4a3411..7a710fe 100644 --- a/lib/child.js +++ b/lib/child.js @@ -16,13 +16,15 @@ var options = JSON.parse(process.argv.pop()), currentModule = path.basename(options.code.path, '.js'), currentTest; -// send ping messages to when child is blocked. -// after I sent the first ping, testrunner will start to except the next ping -// within maxBlockDuration, otherwise this process will be killed -process.send({event: 'ping'}); -setInterval(function() { +if(!options.debug) { + // send ping messages to when child is blocked. + // after I sent the first ping, testrunner will start to except the next ping + // within maxBlockDuration, otherwise this process will be killed process.send({event: 'ping'}); -}, Math.floor(options.maxBlockDuration / 2)); + setInterval(function () { + process.send({event: 'ping'}); + }, Math.floor(options.maxBlockDuration / 2)); +} process.on('uncaughtException', function(err) { if (QUnit.config.current) { diff --git a/lib/testrunner.js b/lib/testrunner.js index 08d3f77..2dfe914 100644 --- a/lib/testrunner.js +++ b/lib/testrunner.js @@ -3,6 +3,7 @@ var fs = require('fs'), coverage = require('./coverage'), cp = require('child_process'), _ = require('underscore'), + freeport = require('freeport'), log = exports.log = require('./log'); var options, @@ -48,7 +49,10 @@ options = exports.options = { namespace: null, // max amount of ms child can be blocked, after that we assume running an infinite loop - maxBlockDuration: 2000 + maxBlockDuration: 2000, + + // port that should be used for debugging + debug: null }; /** @@ -60,9 +64,23 @@ function runOne(opts, callback) { var child; var pingCheckTimeoutId; var argv = process.argv.slice(); + var debug = opts.debug; argv.push(JSON.stringify(opts)); - child = cp.fork(__dirname + '/child.js', argv, {env: process.env}); + + if (debug) { + if (typeof debug === 'boolean') { + freeport(function (er, port) { + process.execArgv.push('--debug-brk=' + port); + fork(); + }); + } else { + process.execArgv.push('--debug-brk=' + debug); + fork(); + } + } else { + fork(); + } function kill() { process.removeListener('exit', kill); @@ -75,40 +93,43 @@ function runOne(opts, callback) { callback(err, data) } - child.on('message', function(msg) { - switch (msg.event) { - case 'ping': - clearTimeout(pingCheckTimeoutId); - pingCheckTimeoutId = setTimeout(function() { - complete(new Error('Process blocked for too long')); - }, opts.maxBlockDuration); - break; - case 'assertionDone': - log.add('assertions', msg.data); - break; - case 'testDone': - log.add('tests', msg.data); - break; - case 'done': - clearTimeout(pingCheckTimeoutId); - msg.data.code = opts.code.path; - log.add('summaries', msg.data); - if (opts.coverage) { - coverage.add(msg.data.coverage); - msg.data.coverage = coverage.get(); - msg.data.coverage.code = msg.data.code; - log.add('coverages', msg.data.coverage); - } - if (opts.log.testing) { - console.log('done'); - } - complete(null, msg.data); - break; - case 'uncaughtException': - complete(_.extend(new Error(), msg.data)); - break; - } - }); + function fork() { + child = cp.fork(__dirname + '/child.js', argv, {env: process.env}); + child.on('message', function (msg) { + switch (msg.event) { + case 'ping': + clearTimeout(pingCheckTimeoutId); + pingCheckTimeoutId = setTimeout(function () { + complete(new Error('Process blocked for too long')); + }, opts.maxBlockDuration); + break; + case 'assertionDone': + log.add('assertions', msg.data); + break; + case 'testDone': + log.add('tests', msg.data); + break; + case 'done': + clearTimeout(pingCheckTimeoutId); + msg.data.code = opts.code.path; + log.add('summaries', msg.data); + if (opts.coverage) { + coverage.add(msg.data.coverage); + msg.data.coverage = coverage.get(); + msg.data.coverage.code = msg.data.code; + log.add('coverages', msg.data.coverage); + } + if (opts.log.testing) { + console.log('done'); + } + complete(null, msg.data); + break; + case 'uncaughtException': + complete(_.extend(new Error(), msg.data)); + break; + } + }); + } process.on('exit', kill); diff --git a/package.json b/package.json index 436325e..cf46ec7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "qunit", "description": "QUnit testing framework for nodejs", - "version": "0.7.5", + "version": "0.7.6", "author": "Oleg Slobodskoi ", "contributors": [ { @@ -39,6 +39,7 @@ "argsparser": "^0.0.6", "cli-table": "^0.3.0", "co": "^3.0.6", + "freeport": "^1.0.3", "qunitjs": "1.10.0", "tracejs": "^0.1.8", "underscore": "^1.6.0"