toolness / tap-prettify Goto Github PK
View Code? Open in Web Editor NEWMake Test Anything Protocol test runner output nicely readable.
License: MIT License
Make Test Anything Protocol test runner output nicely readable.
License: MIT License
If stderr isn't shown and the tests throw an exception, it's possible for tap-prettify
to simply display no output and exit. It also makes debugging tests harder--not only does console.log
not display anything, but console.error
doesn't either, as the user needs to explicitly enable stderr output to see it.
I'm redirecting the output from tape-run
to tap-prettify
. I inserted a console.info(c.stack)
.
$ gulp test | ./node_modules/tap-prettify/bin/tap-prettify.js -
โ login|render|GET https://accounts.crystalcommerce.com/account.json|401|show logged-out
x account/login/login.tag|main
SyntaxError: JSON Parse error: Unexpected identifier "undefined" failure
Traceback (most recent call first):
c.stack { 'at parse ([native code])': '',
'at http': '//localhost:52950/bundle.js?daec7d24:26718:9',
'at baseFindIndex (http': '//localhost:52950/bundle.js?daec7d24:5902:20)',
'at request (http': '//localhost:52950/bundle.js?daec7d24:26769:20)',
'at bound (http': '//localhost:52950/bundle.js?daec7d24:24630:37)',
'at run (http': '//localhost:52950/bundle.js?daec7d24:2446:19)',
'at next (http': '//localhost:52950/bundle.js?daec7d24:24440:18)',
'at drainQueue (http': '//localhost:52950/bundle.js?daec7d24:2417:41)' }
/home/phoenix/workspace/cc/frontend-components/node_modules/tap-prettify/index.js:92
c.stack.forEach(function(line) {
^
TypeError: c.stack.forEach is not a function
at /home/phoenix/workspace/cc/frontend-components/node_modules/tap-prettify/index.js:92:25
at Array.forEach (native)
at TapConsumer.<anonymous> (/home/phoenix/workspace/cc/frontend-components/node_modules/tap-prettify/index.js:78:32)
at emitOne (events.js:82:20)
at TapConsumer.emit (events.js:169:7)
at TapConsumer._parseLine (/home/phoenix/workspace/cc/frontend-components/node_modules/tap-prettify/node_modules/tap/lib/tap-consumer.js:133:20)
at TapConsumer.write (/home/phoenix/workspace/cc/frontend-components/node_modules/tap-prettify/node_modules/tap/lib/tap-consumer.js:77:10)
at Socket.ondata (_stream_readable.js:521:20)
at emitOne (events.js:77:13)
at Socket.emit (events.js:169:7)
stream.js:74
throw er; // Unhandled stream error in pipe.
^
Error: write EPIPE
at Object.exports._errnoException (util.js:812:11)
at exports._exceptionWithHostPort (util.js:835:20)
at WriteWrap.afterWrite (net.js:758:14)
A simple TAP stream like this:
TAP version 13
ok 1 - foo
ok 2 - bar # SKIP nope
not ok 3 - baz
1..3
Will not output the passes and skips when ran through tap-prettify -
The logic in index.js seems to read out the pass and skips as objects, but then not output them until a non-object line (such as a comment) is encountered. This is not per the spec.
The logic should be something along this:
const CHECKMARK = "\u2713";
const OK_FINISH_REGEXP = /^ok$/;
const FAIL_FINISH_REGEXP = /^fail[0-9\s]+$/;
const SKIP_FINISH_REGEXP = /^skip[0-9\s]+$/;
const CURRENT_TEST_START = {
name: "",
total: 0,
skipped: false,
failed: [],
ok: []
};
var colors = require("colors");
var tap = require("tap");
function copy(obj) {
return JSON.parse(JSON.stringify(obj));
}
function isUsefulLine(line, usefulSubstrings) {
for (var i = 0; i < usefulSubstrings.length; i++) {
if (line.indexOf(usefulSubstrings[i]) != -1)
return true;
}
return false;
}
function prettifyTapOutput(options) {
var tc = options.tapConsumer;
var log = options.log || console.log.bind(console);
var usefulTracebackSubstrings = options.usefulTracebackSubstrings || [];
var debug = options.debug;
var passed = 0;
var failed = 0;
var skipped = 0;
var currentTest = copy(CURRENT_TEST_START);
var lastOutput = null;
tc.on("bailout", function(info) {
log("BAILOUT".red, info);
process.exit(1);
});
tc.on("data", function (c) {
if (typeof(c) == "object") {
if (debug)
log("DEBUG object".magenta, JSON.stringify(c, null, 2).grey);
currentTest.total++;
if (currentTest.name != c.name) {
currentTest = copy(CURRENT_TEST_START);
currentTest.name = c.name;
}
if (c.ok) {
if (c.skip) {
currentTest.skipped = true;
skipped++;
} else {
currentTest.ok.push(c);
passed++;
}
} else {
if (c.timedOut)
log("TIMEOUT".red, c.name.trim());
if (c.exit)
process.exit(c.exit);
currentTest.failed.push(c);
failed++;
}
if (currentTest.name) {
if (currentTest.failed.length) {
log("x".red, currentTest.name.grey);
log();
currentTest.failed.forEach(function(c) {
log(" " + c.name.trim(), "failure".grey);
if ('found' in c && 'wanted' in c) {
log(" found ".grey, JSON.stringify(c.found));
log(" wanted".grey, JSON.stringify(c.wanted));
if (c.diff) {
log(" diff".grey);
c.diff.split('\n').forEach(function(line) {
log(" " + line);
});
}
}
if (c.stack) {
log("\n Traceback (most recent call first):".grey);
c.stack.forEach(function(line) {
log(" " + (isUsefulLine(line, usefulTracebackSubstrings)
? line.white
: line.grey));
});
} else if (c.file) {
log(" @ ".grey + c.file + ":".grey + c.line);
}
log();
});
} else if (currentTest.skipped) {
log("S".yellow, currentTest.name.grey);
} else {
log(CHECKMARK.green, currentTest.name.grey);
}
}
} else {
if (debug) log("DEBUG foo".magenta, c.grey);
if (currentTest.total) {
if (OK_FINISH_REGEXP.test(currentTest.name) ||
FAIL_FINISH_REGEXP.test(currentTest.name) ||
SKIP_FINISH_REGEXP.test(currentTest.name)) {
if (currentTest.ok.length) {
console.log("\nFinished testing ".grey +
currentTest.ok[0].name.trim() + ".\n".grey);
}
}
}
}
});
tc.on("end", function () {
var total = passed + failed;
var count = passed + "/" + total;
log(passed == total ? count.green : count.red,
"tests passed,".grey,
(skipped ? skipped.toString().yellow : "none".grey),
"skipped.".grey);
process.exit(failed);
});
}
module.exports = Object.create(tap);
module.exports.prettify = prettifyTapOutput;
// Exported for unit testing purposes only.
module.exports._isUsefulLine = isUsefulLine;
It would be nice for the tap-prettify.js
executable to accept & format piped TAP inputs.
In a brand new directory:
$ yarn add tap-prettify
yarn add v0.21.3
[1/4] ๐ Resolving packages...
warning tap-prettify > tap > glob > [email protected]: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
[2/4] ๐ Fetching packages...
[3/4] ๐ Linking dependencies...
error Couldn't find a package.json file in "/Users/jamesseppi/CODE/test-tap-prettify/node_modules/tap/node_modules/tap-consumer"
info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.
The big advantage for me with tape is that that I can use any executable enviroment and not some "helpful" runner like mocha, making transpilation and node harmony arguments really difficult to use. I'd love to use this, but there is no way to fit it into my environment now.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.