Skip to content

Commit

Permalink
Merge pull request #1218 from jut-io/xunit-output-file
Browse files Browse the repository at this point in the history
reporter-specific options and support for the xunit reporter to output to a file (#2)
  • Loading branch information
Travis Jeffery committed Dec 15, 2014
2 parents 8b88b3b + 82bba0c commit 81d6b94
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 14 deletions.
16 changes: 15 additions & 1 deletion bin/_mocha
Expand Up @@ -65,6 +65,7 @@ program
.option('-c, --colors', 'force enabling of colors')
.option('-C, --no-colors', 'force disabling of colors')
.option('-G, --growl', 'enable growl notification support')
.option('-O, --reporter-options <k=v,k2=v2,...>', 'reporter-specific options')
.option('-R, --reporter <name>', 'specify the reporter to use', 'spec')
.option('-S, --sort', "sort test files")
.option('-b, --bail', "bail after first test failure")
Expand Down Expand Up @@ -196,9 +197,22 @@ program.parse(process.argv);

Error.stackTraceLimit = Infinity; // TODO: config

// reporter options

var reporterOptions = {};
if (program.reporterOptions !== undefined) {
program.reporterOptions.split(",").forEach(function(opt) {
var L = opt.split("=");
if (L.length != 2) {
throw new Error("invalid reporter option '" + opt + "'");
}
reporterOptions[L[0]] = L[1];
});
}

// reporter

mocha.reporter(program.reporter);
mocha.reporter(program.reporter, reporterOptions);

// interface

Expand Down
18 changes: 14 additions & 4 deletions lib/mocha.js
Expand Up @@ -80,7 +80,7 @@ function Mocha(options) {
this.suite = new exports.Suite('', new exports.Context);
this.ui(options.ui);
this.bail(options.bail);
this.reporter(options.reporter);
this.reporter(options.reporter, options.reporterOptions);
if (null != options.timeout) this.timeout(options.timeout);
this.useColors(options.useColors)
if (options.enableTimeouts !== null) this.enableTimeouts(options.enableTimeouts);
Expand Down Expand Up @@ -131,10 +131,10 @@ Mocha.prototype.addFile = function(file){
* Set reporter to `reporter`, defaults to "spec".
*
* @param {String|Function} reporter name or constructor
* @param {Object} reporterOptions optional options
* @api public
*/

Mocha.prototype.reporter = function(reporter){
Mocha.prototype.reporter = function(reporter, reporterOptions){
if ('function' == typeof reporter) {
this._reporter = reporter;
} else {
Expand All @@ -149,6 +149,7 @@ Mocha.prototype.reporter = function(reporter){
if (!_reporter) throw new Error('invalid reporter "' + reporter + '"');
this._reporter = _reporter;
}
this.options.reporterOptions = reporterOptions;
return this;
};

Expand Down Expand Up @@ -405,5 +406,14 @@ Mocha.prototype.run = function(fn){
exports.reporters.Base.useColors = options.useColors;
}
exports.reporters.Base.inlineDiffs = options.useInlineDiffs;
return runner.run(fn);

function done(failures) {
if (reporter.done) {
reporter.done(failures, fn);
} else {
fn(failures);
}
}

return runner.run(done);
};
50 changes: 41 additions & 9 deletions lib/reporters/xunit.js
Expand Up @@ -4,6 +4,7 @@

var Base = require('./base')
, utils = require('../utils')
, fs = require('fs')
, escape = utils.escape;

/**
Expand All @@ -29,12 +30,19 @@ exports = module.exports = XUnit;
* @api public
*/

function XUnit(runner) {
function XUnit(runner, options) {
Base.call(this, runner);
var stats = this.stats
, tests = []
, self = this;

if (options.reporterOptions && options.reporterOptions.output) {
if (! fs.createWriteStream) {
throw new Error('file output not supported in browser');
}
self.fileStream = fs.createWriteStream(options.reporterOptions.output);
}

runner.on('pending', function(test){
tests.push(test);
});
Expand All @@ -48,7 +56,7 @@ function XUnit(runner) {
});

runner.on('end', function(){
console.log(tag('testsuite', {
self.write(tag('testsuite', {
name: 'Mocha Tests'
, tests: stats.tests
, failures: stats.failures
Expand All @@ -58,22 +66,46 @@ function XUnit(runner) {
, time: (stats.duration / 1000) || 0
}, false));

tests.forEach(test);
console.log('</testsuite>');
tests.forEach(function(t) { self.test(t); });
self.write('</testsuite>');
});
}

/**
* Override done to close the stream (if it's a file).
*/
XUnit.prototype.done = function(failures, fn) {
if (this.fileStream) {
this.fileStream.end(function() {
fn(failures);
});
} else {
fn(failures);
}
};

/**
* Inherit from `Base.prototype`.
*/

XUnit.prototype.__proto__ = Base.prototype;

/**
* Write out the given line
*/
XUnit.prototype.write = function(line) {
if (this.fileStream) {
this.fileStream.write(line + '\n');
} else {
console.log(line);
}
};

/**
* Output tag for the given `test.`
*/

function test(test) {
XUnit.prototype.test = function(test, ostream) {
var attrs = {
classname: test.parent.fullTitle()
, name: test.title
Expand All @@ -82,13 +114,13 @@ function test(test) {

if ('failed' == test.state) {
var err = test.err;
console.log(tag('testcase', attrs, false, tag('failure', {}, false, cdata(escape(err.message) + "\n" + err.stack))));
this.write(tag('testcase', attrs, false, tag('failure', {}, false, cdata(escape(err.message) + "\n" + err.stack))));
} else if (test.pending) {
console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
this.write(tag('testcase', attrs, false, tag('skipped', {}, true)));
} else {
console.log(tag('testcase', attrs, true) );
this.write(tag('testcase', attrs, true) );
}
}
};

/**
* HTML tag helper.
Expand Down

0 comments on commit 81d6b94

Please sign in to comment.