Browse Source

[reporters] Added min and fixed xunit reporter

master
Muthu Kumar 6 years ago
parent
commit
292fe0aac0
  1. 2
      package.json
  2. 5
      sample/sample7.test.js
  3. 66
      shrinkwrap.yaml
  4. 2
      src/gunner.js
  5. 10
      src/lib/testrunner.js
  6. 1
      src/reporters/index.js
  7. 52
      src/reporters/min.js
  8. 116
      src/reporters/xunit.js
  9. 13
      src/util/constants.js

2
package.json

@ -28,7 +28,7 @@
"@codefeathers/iseq": "^1.2.1",
"@codefeathers/promise.object": "^0.9.5",
"json-stringify-safe": "^5.0.1",
"tap-xunit": "^2.3.0"
"jsontoxml": "^1.0.0"
},
"devDependencies": {
"babel-cli": "^6.26.0",

5
sample/sample7.test.js

@ -6,7 +6,7 @@
const Gunner = require('../es6');
const expect = Gunner.expect;
const expectMany = Gunner.expectMany;
const gunner = new Gunner({ name: 'sample tests' });
const gunner = new Gunner('sample tests');
const a = 1;
// gunner.before(Gunner.Start, () => console.log('Started tests!'));
@ -99,4 +99,5 @@ gunner.test('(should fail) should not resolve to 5', () =>
const trace = process.argv.slice(2).indexOf('--trace') !== -1;
const reporter = process.argv.slice(2).indexOf('--log') !== -1;
gunner.run({ trace, reporter }).then(console.log);
gunner.run({ trace, reporter });
// gunner.run({ reporter:'xunit' });

66
shrinkwrap.yaml

@ -2,7 +2,7 @@ dependencies:
'@codefeathers/iseq': 1.2.1
'@codefeathers/promise.object': 0.9.5
json-stringify-safe: 5.0.1
tap-xunit: 2.3.0
jsontoxml: 1.0.0
devDependencies:
babel-cli: 6.26.0
babel-plugin-transform-object-rest-spread: 6.26.0
@ -121,6 +121,7 @@ packages:
/argparse/1.0.10:
dependencies:
sprintf-js: 1.0.3
dev: true
resolution:
integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
/arr-diff/2.0.0:
@ -1169,6 +1170,7 @@ packages:
resolution:
integrity: sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==
/core-util-is/1.0.2:
dev: true
resolution:
integrity: sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
/create-ecdh/4.0.3:
@ -1371,11 +1373,6 @@ packages:
npm: '>=1.2'
resolution:
integrity: sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
/duplexer/0.1.1:
dev: false
resolution:
integrity: sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=
tarball: 'http://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz'
/duplexer2/0.1.4:
dependencies:
readable-stream: 2.3.6
@ -1504,6 +1501,7 @@ packages:
resolution:
integrity: sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==
/esprima/4.0.1:
dev: true
engines:
node: '>=4'
hasBin: true
@ -1537,10 +1535,6 @@ packages:
node: '>=0.10.0'
resolution:
integrity: sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=
/events-to-array/1.1.2:
dev: false
resolution:
integrity: sha1-LUH1Y+H+QA7Uli/hpNXGp1Od9/Y=
/events/2.1.0:
dev: true
engines:
@ -1997,6 +1991,7 @@ packages:
resolution:
integrity: sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
/inherits/2.0.3:
dev: true
resolution:
integrity: sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
/inline-source-map/0.6.2:
@ -2292,6 +2287,7 @@ packages:
resolution:
integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
/isarray/1.0.0:
dev: true
resolution:
integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
/isarray/2.0.4:
@ -2330,6 +2326,7 @@ packages:
dependencies:
argparse: 1.0.10
esprima: 4.0.1
dev: true
hasBin: true
resolution:
integrity: sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==
@ -2376,6 +2373,12 @@ packages:
'0': node >= 0.2.0
resolution:
integrity: sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
/jsontoxml/1.0.0:
dev: false
engines:
node: '>=0.2.0'
resolution:
integrity: sha512-oOwlpPl8MIQVEm9ejxMPDfRxdX2vNdWxAmI3n+kXa7rt0C6IEsNONDxTmd1A7Zh+Sq5RM4Lov9wm8t5kA+SSMQ==
/kind-of/3.2.2:
dependencies:
is-buffer: 1.1.6
@ -2434,6 +2437,7 @@ packages:
resolution:
integrity: sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==
/lodash/4.17.11:
dev: true
resolution:
integrity: sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
/loose-envify/1.4.0:
@ -2547,6 +2551,7 @@ packages:
integrity: sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
tarball: 'http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz'
/minimist/1.2.0:
dev: true
resolution:
integrity: sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
tarball: 'http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz'
@ -2883,6 +2888,7 @@ packages:
resolution:
integrity: sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
/process-nextick-args/2.0.0:
dev: true
resolution:
integrity: sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
/process/0.11.10:
@ -2973,6 +2979,7 @@ packages:
safe-buffer: 5.1.2
string_decoder: 1.1.1
util-deprecate: 1.0.2
dev: true
resolution:
integrity: sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
tarball: 'http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz'
@ -3163,6 +3170,7 @@ packages:
resolution:
integrity: sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==
/safe-buffer/5.1.2:
dev: true
resolution:
integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
/safe-regex/1.1.0:
@ -3346,6 +3354,7 @@ packages:
resolution:
integrity: sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
/sprintf-js/1.0.3:
dev: true
resolution:
integrity: sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
/static-extend/0.1.2:
@ -3411,6 +3420,7 @@ packages:
/string_decoder/1.1.1:
dependencies:
safe-buffer: 5.1.2
dev: true
resolution:
integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
/strip-ansi/3.0.1:
@ -3480,29 +3490,6 @@ packages:
node: '>=4.0.0'
resolution:
integrity: sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==
/tap-parser/1.2.2:
dependencies:
events-to-array: 1.1.2
inherits: 2.0.3
js-yaml: 3.12.0
dev: false
hasBin: true
optionalDependencies:
readable-stream: 2.3.6
resolution:
integrity: sha1-Xi9pcGEfB5x8+FfeHceqG0gN56U=
/tap-xunit/2.3.0:
dependencies:
duplexer: 0.1.1
minimist: 1.2.0
tap-parser: 1.2.2
through2: 2.0.3
xmlbuilder: 4.2.1
xtend: 4.0.1
dev: false
hasBin: true
resolution:
integrity: sha512-YVsURNvn1wfVUWb5wjansxhfbfeo2hOBTUbVgZoaMO8lyZzpiSi9IiZTZ7JG56m6A49LeWjfJIx/SnAre41V/A==
/text-table/0.2.0:
dev: true
resolution:
@ -3516,6 +3503,7 @@ packages:
dependencies:
readable-stream: 2.3.6
xtend: 4.0.1
dev: true
resolution:
integrity: sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=
/timers-browserify/1.4.2:
@ -3667,6 +3655,7 @@ packages:
resolution:
integrity: sha1-K1viOjK2Onyd640PKNSFcko98ZA=
/util-deprecate/1.0.2:
dev: true
resolution:
integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
/util/0.10.3:
@ -3716,15 +3705,8 @@ packages:
node: '>=0.10.0'
resolution:
integrity: sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=
/xmlbuilder/4.2.1:
dependencies:
lodash: 4.17.11
dev: false
engines:
node: '>=0.8.0'
resolution:
integrity: sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=
/xtend/4.0.1:
dev: true
engines:
node: '>=0.4'
resolution:
@ -3741,4 +3723,4 @@ specifiers:
browserify: ^16.2.2
eslint: ^5.2.0
json-stringify-safe: ^5.0.1
tap-xunit: ^2.3.0
jsontoxml: ^1.0.0

2
src/gunner.js

@ -100,7 +100,7 @@ class Gunner {
? {
[options.request]:
reporters[options.request].convert(results),
json: results }
default: results }
: results);
});
}

10
src/lib/testrunner.js

@ -3,10 +3,10 @@
const Gunner = require('../gunner');
Promise.object = require('@codefeathers/promise.object');
const { performance } = require('perf_hooks');
const { last, pipe, pick, assignToObject } = require('../util');
const { eventMap } = require('../util/constants');
const emitter = require('./emitter');
const buildTestQueue = require('./buildTestQueue');
const findSkip = (skip, unit) => {
@ -65,6 +65,12 @@ const reduceQueue =
|| result.rejection
|| result.description})
};
emitter.emit(
eventMap[status],
resultObject
);
acc.results.push(resultObject);
} else {

1
src/reporters/index.js

@ -3,5 +3,6 @@ module.exports = {
default: require('./default'),
tap: require('./tap'),
xunit: require('./xunit'),
min: require('./min'),
};

52
src/reporters/min.js

@ -0,0 +1,52 @@
const { eventMap, eventVerbs } = require('../util/constants');
const convert = x => x;
const count = {
pass: 0,
fail: 0,
skip: 0,
collapse: function() {
return this.pass + this.fail + this.skip;
}
};
const clear = () => {
// clear screen
process.stdout.write('\u001b[2J');
// set cursor position to top
process.stdout.write('\u001b[1;1H');
};
const doneHandler = event => {
clear();
const mapEvent = eventMap[event.status];
count[mapEvent]++;
console.log(`${count[mapEvent]} tests ${eventVerbs[mapEvent][2]}`
+ ` (total: ${count.collapse()})`);
};
const Min = runner => {
runner.on('start', () => console.log('Started tests'));
runner.on('pass', doneHandler);
runner.on('fail', doneHandler);
runner.on('skip', doneHandler);
runner.on('end', results => {
clear();
console.log(`Test suite ${results.name} has done running.`);
console.log('Success ratio:', results.successPercent, '%');
});
};
module.exports = Min;
module.exports.convert = convert;

116
src/reporters/xunit.js

@ -1,72 +1,58 @@
const tag = (name, attrs, close, content) => {
const end = close ? "/>" : ">";
const pairs = [];
let tag;
Object.keys(attrs).forEach(key => {
if (Object.prototype.hasOwnProperty.call(attrs, key)) {
pairs.push(key + '="' + (attrs[key]) + '"');
}
});
tag = "<" + name + (pairs.length ? " " + pairs.join(" ") : "") + end;
if (content) {
tag += content + "</" + name + end;
}
return new String(tag);
};
const convert = results => {
const { count, success, failures, skipped } = results;
return '<?xml version="1.0"?>' + tag(
'testsuites',
{},
false,
tag(
'testsuite',
{
name: results.name,
tests: count,
success: success.length,
failures: failures.length,
skipped: skipped.length,
timestamp: new Date().toUTCString(),
time: (results.duration / 1000) || 0,
},
false,
results.reduce((acc, r) => {
const close = r.status === 'ok';
const content = r.status !== 'ok' &&
(r.status === 'skip'
? tag('skipped', {}, true)
: tag(
'failure', {},
!r.reason, r.reason ? r.reason : ''));
acc += tag(
'testcase',
{
name: r.description,
time: (r.duration / 1000) || 0,
},
close,
content || ''
);
return acc;
}, '')
)
);
const toXML = require('jsontoxml');
const toJSON = resultsArray => {
return {
testsuites: resultsArray.map(results => {
const { name, count, success, failures, skipped } = results;
return {
name: 'testsuite',
attrs: {
name,
tests: count,
success: success.length,
failures: failures.length,
skipped: skipped.length,
timestamp: new Date().toUTCString(),
time: (results.duration / 1000) || 0,
},
children: results.reduce((acc, r) => {
const content = r.status !== 'ok' &&
(r.status === 'skip'
? 'skipped'
: {
name: 'failure',
text: r.reason
? (r.reason && r.reason.stack) : ''
});
acc.push({
name: 'testcase',
attrs: {
name: r.description,
time: (r.duration / 1000) || 0,
},
...(typeof content === 'object'
&& { text: content && content.stack }),
...(typeof content === 'object'
&& { children: [ content ]}),
});
return acc;
}, []),
};
})
};
};
const xunit = runner => {
runner.on("end", results => {
const convert = results =>
toXML(toJSON(results),
{ xmlHeader: { standalone: true }});
console.log(convert(results));
});
};
const xunit = runner =>
runner.on("end", results => console.log(convert([ results ])));
module.exports = xunit;
module.exports.convert = convert;

13
src/util/constants.js

@ -1,8 +1,15 @@
const chalk = require('chalk');
const { EOL } = require('os');
module.exports = {
greenLine: chalk.green('------------------------------------'),
redLine: chalk.red('------------------------------------'),
EOL,
eventMap: {
'ok': 'pass',
'notOk': 'fail',
'skip': 'skip',
},
eventVerbs: {
pass: [ 'pass', 'passing', 'passed' ],
fail: [ 'fail', 'failing', 'failed' ],
skip: [ 'skip', 'skipping', 'skipped' ],
},
};

Loading…
Cancel
Save