run = function (files, callback) { var filesCount = 0; callback || (callback = noop); if (!Array.isArray(files)) { files = [files]; } if (options.coverage || files[0].coverage) coverage.setup(options.coverage); files.forEach(function(file) { var opts = _.extend({}, options, file); !opts.log && (opts.log = {}); opts.deps = absPaths(opts.deps); opts.code = absPath(opts.code); opts.tests = absPaths(opts.tests); runOne(opts, function(err) { if (err) { return callback(err, log.stats()); } filesCount++; if (filesCount >= files.length) { _.each(opts.log, function(val, name) { if (val && log.print[name]) { log.print[name](); } }); // Write coverage report. if (opts.coverage) coverage.report(); callback(null, log.stats()); } }); }); }
...
log: {
summary: true
}
});
// one code and tests file
testrunner.run({
code: "/path/to/your/code.js",
tests: "/path/to/your/tests.js"
}, callback);
// require code into a namespace object, rather than globally
testrunner.run({
code: {path: "/path/to/your/code.js", namespace: "code"},
...
setup = function (opts) { _.extend(options, opts); }
...
```
```javascript
// change any option for all tests globally
testrunner.options.optionName = value;
// or use setup function
testrunner.setup({
log: {
summary: true
}
});
// one code and tests file
...
isGeneratorFn = function (fn) { return fn.constructor.name == 'GeneratorFunction'; }
...
/**
* Support generators.
*/
global.test = QUnit.test = function(testName, callback) {
var fn;
if (generators.isGeneratorFn(callback)) {
fn = function(assert) {
var done = assert.async();
co.wrap(callback).call(this, assert).then(function() {
done();
}).catch(function (err) {
console.log(err.stack);
done();
...
run = function (files, callback) { var filesCount = 0; callback || (callback = noop); if (!Array.isArray(files)) { files = [files]; } if (options.coverage || files[0].coverage) coverage.setup(options.coverage); files.forEach(function(file) { var opts = _.extend({}, options, file); !opts.log && (opts.log = {}); opts.deps = absPaths(opts.deps); opts.code = absPath(opts.code); opts.tests = absPaths(opts.tests); runOne(opts, function(err) { if (err) { return callback(err, log.stats()); } filesCount++; if (filesCount >= files.length) { _.each(opts.log, function(val, name) { if (val && log.print[name]) { log.print[name](); } }); // Write coverage report. if (opts.coverage) coverage.report(); callback(null, log.stats()); } }); }); }
...
log: {
summary: true
}
});
// one code and tests file
testrunner.run({
code: "/path/to/your/code.js",
tests: "/path/to/your/tests.js"
}, callback);
// require code into a namespace object, rather than globally
testrunner.run({
code: {path: "/path/to/your/code.js", namespace: "code"},
...
setup = function (opts) { _.extend(options, opts); }
...
```
```javascript
// change any option for all tests globally
testrunner.options.optionName = value;
// or use setup function
testrunner.setup({
log: {
summary: true
}
});
// one code and tests file
...
add = function (type, obj) { if (obj) { data[type].push(obj); } return data[type]; }
...
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;
...
reset = function () { data = { assertions: [], tests: [], summaries: [], coverages: [] }; }
...
// globalCoverage: true,
// log currently testing code file
testing: true
};
// reset log stats every time .next is called
chain.next = function() {
log.reset();
return chainer.prototype.next.apply(this, arguments);
};
chain.add('base testrunner', function() {
tr.run({
code: fixtures + '/testrunner-code.js',
tests: fixtures + '/testrunner-tests.js',
...
stats = function () { var stats = { files: 0, assertions: 0, failed: 0, passed: 0, runtime: 0 }; data.summaries.forEach(function(file) { stats.files++; stats.assertions += file.total; stats.failed += file.failed; stats.passed += file.passed; stats.runtime += file.runtime; }); stats.tests = data.tests.length; stats.coverage = { files: 0, statements: { covered: 0, total: 0 }, branches: { covered: 0, total: 0 }, functions: { covered: 0, total: 0 }, lines: { covered: 0, total: 0 } }; data.coverages.forEach(function(file) { stats.coverage.files++; stats.coverage.statements.covered += file.statements.covered; stats.coverage.statements.total += file.statements.total; stats.coverage.branches.covered += file.branches.covered; stats.coverage.branches.total += file.branches.total; stats.coverage.functions.covered += file.functions.covered; stats.coverage.functions.total += file.functions.total; stats.coverage.lines.covered += file.lines.covered; stats.coverage.lines.total += file.lines.total; }); return stats; }
...
});
log('\nSummary:\n' + table.toString());
};
print.globalSummary = function() {
var table,
data = exports.stats();
table = new Table({
head: ['Files', 'Tests', 'Assertions', 'Failed', 'Passed', 'Runtime
x27;]
});
table.push([data.files, data.tests, data.assertions, data.failed,
data.passed, data.runtime]);
...
assertions = function () { var table, currentModule, module, currentTest, test; table = new Table({ head: ['Module', 'Test', 'Assertion', 'Result'] }); data.assertions.forEach(function(data) { // just easier to read the table if (data.module === currentModule) { module = ''; } else { module = currentModule = data.module; } // just easier to read the table if (data.test === currentTest) { test = ''; } else { test = currentTest = data.test; } table.push([module, test, data.message || '', data.result ? 'ok' : 'fail']); }); log('\nAssertions:\n' + table.toString()); }
n/a
coverage = function () { var table; if (!data.coverages.length) return; table = new Table({ head: ['File', 'Statements', 'Branches', 'Functions', 'Lines'] }); data.coverages.forEach(function(coverage) { table.push([ truncFile(coverage.code), getMet(coverage.statements), getMet(coverage.branches), getMet(coverage.functions), getMet(coverage.lines)]); }); log('\nCoverage:\n' + table.toString()); }
n/a
errors = function () { var errors = []; data.assertions.forEach(function(data) { if (!data.result) { errors.push(data); } }); if (errors.length) { log('\n\nErrors:'); errors.forEach(function(data) { log('\nModule: ' + data.module + ' Test: ' + data.test); if (data.message) { log(data.message); } if (data.source) { log(data.source); } if (data.expected != null || data.actual != null) { //it will be an error if data.expected !== data.actual, but if they're //both undefined, it means that they were just not filled out because //no assertions were hit (likely due to code error that would have been logged as source or message). log('Actual value:'); log(data.actual); log('Expected value:'); log(data.expected); } }); } }
n/a
globalCoverage = function () { var coverage, table; if (!data.coverages.length) return; coverage = exports.stats().coverage; table = new Table({ head: ['Files', 'Statements', 'Branches', 'Functions', 'Lines'] }); table.push([ coverage.files, getMet(coverage.statements), getMet(coverage.branches), getMet(coverage.functions), getMet(coverage.lines) ]); log('\nGlobal coverage:\n' + table.toString()); }
n/a
globalSummary = function () { var table, data = exports.stats(); table = new Table({ head: ['Files', 'Tests', 'Assertions', 'Failed', 'Passed', 'Runtime'] }); table.push([data.files, data.tests, data.assertions, data.failed, data.passed, data.runtime]); log('\nGlobal summary:\n' + table.toString()); }
n/a
summary = function () { var table; table = new Table({ head: ['File', 'Failed', 'Passed', 'Total', 'Runtime'] }); data.summaries.forEach(function(data) { table.push([truncFile(data.code), data.failed, data.passed, data.total, data.runtime]); }); log('\nSummary:\n' + table.toString()); }
n/a
tests = function () { var table, currentModule, module; table = new Table({ head: ['Module', 'Test', 'Failed', 'Passed', 'Total'] }); data.tests.forEach(function(data) { // just easier to read the table if (data.module === currentModule) { module = ''; } else { module = currentModule = data.module; } table.push([module, data.name, data.failed, data.passed, data.total]); }); log('\nTests:\n' + table.toString()); }
n/a