forked from zendeskarchive/jessie
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
XUnit formatter added. Based on VowsJS' reporter.
- Loading branch information
1 parent
e8769a2
commit f0188fe
Showing
3 changed files
with
202 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
var sys = require('sys'); | ||
|
||
exports.formatter = { | ||
specStart: function(spec) { | ||
spec.duration = Number(new Date); | ||
}, | ||
|
||
reportSpecResults: function(spec) { | ||
spec.duration = (Number(new Date) - spec.duration); | ||
}, | ||
|
||
finish: function(result, runner) { | ||
sys.puts(tag('testsuite', { | ||
name: 'Jasmine Tests', | ||
tests: result.total, | ||
failures: result.failed, | ||
skip: result.pending, | ||
timestamp: (new Date).toUTCString(), | ||
time: result.duration / 1000 | ||
}, false)); | ||
runner.suites().forEach(handleSuite); | ||
sys.puts(end('testsuite')); | ||
} | ||
}; | ||
|
||
function handleSuite(suite) { | ||
suite.specs().forEach(handleSpec); | ||
} | ||
|
||
function handleSpec(spec) { | ||
var r = extractResult(spec); | ||
var attributes = { | ||
classname: spec.suite.getFullName(), | ||
name: spec.description, | ||
time: spec.duration / 1000 | ||
}; | ||
|
||
var reason = r.pending? pendingSpecTag(spec) : r.fail? failedSpecTag(spec) : ''; | ||
var specTag = reason? | ||
tag('testcase', attributes, false, reason) : | ||
tag('testcase', attributes, true) | ||
|
||
sys.puts(specTag); | ||
} | ||
|
||
function pendingSpecTag(spec) { | ||
return tag('skipped', { message: encode(spec.results().getItems()[0].trace.message) }, true); | ||
} | ||
|
||
function failedSpecTag(spec) { | ||
var reason = spec.results().getItems()[0]; | ||
var attributes = { message: encode(reason.message) }; | ||
reason.trace.type && (attributes.type = reason.trace.type) | ||
return tag('failure', attributes, false, cdata(reason.trace.stack)); | ||
} | ||
|
||
function extractResult(spec) { | ||
var pending = false | ||
spec.results().getItems().forEach(function(item) { | ||
pending = item.pending || false; | ||
}); | ||
return { pending: pending, fail: spec.results().failedCount > 0 }; | ||
} | ||
|
||
function encode(value) { | ||
return !value ? value : | ||
String(value) | ||
.replace(/&/g, '&') | ||
.replace(/>/g, '>') | ||
.replace(/</g, '<') | ||
.replace(/"/g, '"') | ||
.replace(/\u001b\[\d{1,2}m/g, ''); | ||
} | ||
|
||
function tag(name, attribs, single, content) { | ||
var tag; | ||
var end = single ? ' />' : '>' | ||
var strAttr = []; | ||
for (var attr in attribs) { | ||
attribs.hasOwnProperty(attr) && strAttr.push(attr + '="' + encode(attribs[attr]) + '"'); | ||
} | ||
|
||
tag = '<' + name + (strAttr.length? ' ' + strAttr.join(' ') : '' ) + end | ||
tag = content? (tag + content + '</' + name + end) : tag | ||
return tag; | ||
} | ||
|
||
function end(name) { | ||
return '</' + name + '>'; | ||
} | ||
|
||
function cdata(data) { | ||
return '<![CDATA[' + encode(data) + ']]>'; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
function outputAsArray(output) { | ||
var array = output.split('\n'); | ||
return array.splice(0, array.length-1); | ||
} | ||
|
||
/* Remove the surrounding testsuite tag */ | ||
function specsAsArray(output) { | ||
var array = outputAsArray(output); | ||
return array.splice(1, array.length-1); | ||
} | ||
|
||
describe('XUnit formatter', function() { | ||
var formatter = new (require('jessie/reporter')).reporter('xunit').formatter | ||
|
||
var knownResults; | ||
var emptyRunner; | ||
var runnerWithOneSpec; | ||
|
||
beforeEach(function() { | ||
knownResults = { total: 2, failed: 1, pending: 1, duration: 2500 }; | ||
emptyRunner = { suites: function() { return []; } }; | ||
var suiteStub = { getFullName: function() { return 'SuiteName'; } }; | ||
var items = [ { message: 'ReasonMessage' , trace: { | ||
type: 'ReasonType', | ||
message: 'TraceReasonMessage', | ||
stack: 'FailureStack' | ||
}}]; | ||
var results = { getItems: function() { return items; } } | ||
var specStub = { description: 'SpecName', suite: suiteStub, duration: 5000, | ||
results: function() { return results; } | ||
}; | ||
suiteStub.specs = function() { return [ specStub ]; }; | ||
runnerWithOneSpec = { suites: function() { return [ suiteStub ]; } }; | ||
}); | ||
|
||
it('should record the start time of a spec', function() { | ||
var emptySpec = {}; | ||
formatter.specStart(emptySpec); | ||
expect(emptySpec.duration != undefined).toEqual(true); | ||
expect(emptySpec.duration > 0).toEqual(true); | ||
}); | ||
|
||
it('should add an open testsuite tag with the summary in the first position of the output buffer', function() { | ||
capture = require('helpers/stdout').capture(function() { | ||
formatter.finish(knownResults, emptyRunner); | ||
}); | ||
var tag = outputAsArray(capture.output())[0]; | ||
tag.should_match('<testsuite'); | ||
tag.should_match('name="Jasmine Tests"'); | ||
tag.should_match('tests="2"'); | ||
tag.should_match('failures="1"'); | ||
tag.should_match('skip="1"'); | ||
tag.should_match('time="2.5"'); | ||
tag.should_match('timestamp="'); | ||
tag.should_match('>'); | ||
}); | ||
|
||
it('should have the last tag as a close testsuite tag', function() { | ||
capture = require('helpers/stdout').capture(function() { | ||
formatter.finish(knownResults, emptyRunner); | ||
}); | ||
var output = outputAsArray(capture.output()); | ||
var tag = output[output.length - 1]; | ||
tag.should_be('</testsuite>'); | ||
}); | ||
|
||
it('should add an open tastcase tag with the summary to the output buffer for successful specs', function() { | ||
capture = require('helpers/stdout').capture(function() { | ||
formatter.finish(knownResults, runnerWithOneSpec); | ||
}); | ||
var tag = specsAsArray(capture.output())[0]; | ||
tag.should_match('<testcase'); | ||
tag.should_match('classname="SuiteName"'); | ||
tag.should_match('name="SpecName"'); | ||
tag.should_match('time="5"'); | ||
tag.should_match('/>'); | ||
}); | ||
|
||
it('should add the reasons of a pended spec to the output buffer', function() { | ||
runnerWithOneSpec.suites()[0].specs()[0].results().getItems()[0].pending = true; | ||
capture = require('helpers/stdout').capture(function() { | ||
formatter.finish(knownResults, runnerWithOneSpec); | ||
}); | ||
var tag = specsAsArray(capture.output())[0]; | ||
tag.should_match('<skipped'); | ||
tag.should_match('message="TraceReasonMessage"'); | ||
tag.should_match('/>'); | ||
}); | ||
|
||
it('should add the reasons of a failed spec to the output buffer', function() { | ||
runnerWithOneSpec.suites()[0].specs()[0].results().failedCount = 1; | ||
capture = require('helpers/stdout').capture(function() { | ||
formatter.finish(knownResults, runnerWithOneSpec); | ||
}); | ||
var tag = specsAsArray(capture.output())[0]; | ||
tag.should_match('<failure'); | ||
tag.should_match('message="ReasonMessage"'); | ||
tag.should_match('type="ReasonType"'); | ||
tag.should_match(/<!\[CDATA\[FailureStack\]\]>/); | ||
tag.should_match('</failure>'); | ||
}); | ||
}); | ||
|