chuhai
Version:
Test driven benchmarking.
223 lines (187 loc) • 5.55 kB
JavaScript
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
/* global window */
var Promise = require('bluebird');
var fnName = require('fn-name');
var debug = require('debug')('chuhai');
// require('loud-rejection/api')(process);
var benchmark = require('benchmark');
/* istanbul ignore next */
if (typeof window !== 'undefined') {
var _ = require('lodash');
var _process = require('process');
benchmark = benchmark.runInContext({ _: _, process: _process });
window.Benchmark = benchmark;
}
// Promise.longStackTraces();
var reporterKey = process.env.REPORTER || 'markdown';
var reporters = {
markdown: require('./reporters/markdown')
};
var reporter = reporters[reporterKey];
function noop() {}
// maybe usefull later
// check if the test is being run in AVA cli
// const isAva = typeof process.send === 'function';
// const ava = isAva ? require('ava/api') : undefined;
// process.on('message', message => {
// debug('message ->', message);
// });
/* main api */
exports = module.exports = function (title, fn) {
if (typeof title === 'function') {
fn = title;
title = fnName(fn) || '[anonymous]';
}
return new Promise(function (resolve, reject) {
createSuite(title, function (b) {
b.error(reject);
fn(b);
b.run(resolve);
});
});
};
exports.skip = noop;
exports.failing = noop;
exports.cb = createSuite;
/* warning, experimental api below */
/* macros supported in ava > 0.15.0*/
exports.macro = function (t, fn) {
return new Promise(function (resolve, reject) {
createSuite(t._test.title, function (b) {
fn(Object.assign(t, b));
b.error(reject);
b.run(resolve);
});
});
};
exports.macro.cb = function (t, fn) {
createSuite(t._test.title, function (b) {
fn(Object.assign(t, b));
});
};
/* experimental wrapper should work in ava or blue-tape */
exports.wrapper = function (test) {
var wrappedTest = wrapTest(test);
wrappedTest.failing = test.failing ? wrapTest(test.failing) : noop;
wrappedTest.skip = test.skip || noop;
return wrappedTest;
function wrapTest(test) {
return function wrappedTest(title, fn) {
test(title, function (t) {
return new Promise(function (resolve, reject) {
createSuite(title, function (b) {
fn(Object.assign(t, b));
b.error(reject);
b.run(resolve);
});
});
});
};
}
};
/* experimental wrapper should work in tape */
exports.wrapper.cb = function (test) {
return function wrappedTest(title, fn) {
test(title, function (t) {
var _end = t.end;
var _error = t.error;
createSuite(title, function (b) {
fn(Object.assign(t, b, {
end: function end() {
b.run(_end);
b.error(_error);
}
}));
});
});
};
};
/* internal */
function createSuite(suiteTitle, fn) {
if (typeof suiteTitle === 'function') {
fn = suiteTitle;
suiteTitle = fnName(fn) || '[anonymous]';
}
debug('create suite > %s', suiteTitle);
var defaultOpts = {
// we default to sync in the browser
async: typeof window === 'undefined'
};
var suite = new benchmark.Suite(suiteTitle);
var api = {
set: function set(key, value) {
defaultOpts[key] = value;
},
bench: function bench(title, fn, opts) {
opts = _extends({}, defaultOpts, opts);
debug('adding bench > %s > %s', suiteTitle, title);
suite.add(title, fn, opts);
},
burn: function burn(title, fn, opts) {
opts = _extends({}, defaultOpts, opts, { burn: true });
debug('adding burn > %s > %s', suiteTitle, title);
suite.add(title, fn, opts);
},
xbench: noop,
xburn: noop,
complete: function complete(fn) {
debug('adding completed callback > %s', suiteTitle);
suite.on('complete', function (ev) {
try {
fn(ev);
} catch (e) {
ev.target.error = new Error(String(e));
}
});
},
// these don't work as expected
/* setup(fn) {
opts.setup = fn;
},
teardown(fn) {
opts.teardown = fn;
}, */
cycle: function cycle(fn) {
debug('adding cycle callback > %s', suiteTitle);
suite.on('cycle', function (ev) {
// try to catch asserts that don't throw
// power-asserts return null when failed, undefined when passed
try {
fn(ev);
} catch (e) {
ev.target.error = new Error(String(e));
}
});
},
error: function error(fn) {
debug('adding error callback > %s', suiteTitle);
suite.on('error', function (ev) {
fn(ev.target.error);
});
},
run: function run(cb) {
/* istanbul ignore next */
if (debug.enabled) {
debug('started > %s', suiteTitle);
suite.on('cycle', function (e) {
debug('cycled after > %s > %s', suiteTitle, e.target.name);
});
suite.on('error', function (e) {
debug('errored after > %s > %s', suiteTitle, e.target.name);
});
}
suite.on('complete', function () {
debug('completed > %s', suiteTitle);
reporter(suite);
if (cb) {
cb();
}
});
suite.run(defaultOpts);
}
};
// aliases
api.after = api.complete;
fn(api);
}
;