feat(@embark/test-runner): add reports to tests (#1864)

This commit is contained in:
André Medeiros 2019-09-03 13:38:36 -04:00 committed by GitHub
parent f9557d4c93
commit 230fe592a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1698 additions and 2772 deletions

View File

@ -16,7 +16,7 @@ class ContractsManager {
this.contracts = {}; this.contracts = {};
this.contractDependencies = {}; this.contractDependencies = {};
this.deployOnlyOnConfig = false; this.deployOnlyOnConfig = false;
this.compileError = false; this.compileError = null;
this.compileOnceOnly = options.compileOnceOnly; this.compileOnceOnly = options.compileOnceOnly;
this._web3 = null; this._web3 = null;
@ -532,12 +532,12 @@ class ContractsManager {
} }
], function (err) { ], function (err) {
if (err) { if (err) {
self.compileError = true; self.compileError = err;
self.events.emit("status", __("Build error")); self.events.emit("status", __("Build error"));
self.events.emit("outputError", __("Error building Dapp, please check console")); self.events.emit("outputError", __("Error building Dapp, please check console"));
self.logger.error(__("Error Building contracts")); self.logger.error(__("Error Building contracts"));
} else { } else {
self.compileError = false; self.compileError = null;
} }
self.logger.trace("finished".underline); self.logger.trace("finished".underline);

View File

@ -48,14 +48,16 @@
"@babel/cli": "7.2.3", "@babel/cli": "7.2.3",
"@babel/core": "7.2.2", "@babel/core": "7.2.2",
"@types/async": "2.0.50", "@types/async": "2.0.50",
"async": "3.1.0",
"cross-env": "5.2.0", "cross-env": "5.2.0",
"eslint": "5.7.0", "eslint": "5.7.0",
"mocha": "6.2.0",
"npm-run-all": "4.1.5", "npm-run-all": "4.1.5",
"rimraf": "3.0.0", "rimraf": "3.0.0",
"tslint": "5.16.0", "tslint": "5.16.0",
"typescript": "3.4.5", "typescript": "3.4.5"
},
"dependencies": {
"async": "2.6.1",
"mocha": "6.2.0",
"web3": "1.2.1" "web3": "1.2.1"
}, },
"engines": { "engines": {

View File

@ -37,6 +37,7 @@ class MochaTestRunner {
run(options, cb) { run(options, cb) {
const {events} = this.embark; const {events} = this.embark;
const {reporter} = options;
const Module = require("module"); const Module = require("module");
const originalRequire = require("module").prototype.require; const originalRequire = require("module").prototype.require;
@ -67,6 +68,10 @@ class MochaTestRunner {
next(); next();
} }
], (err) => { ], (err) => {
// Reset the gas accumulator so that we don't show deployment gas on the
// first test.
reporter.resetGas();
if (acctCb) { if (acctCb) {
acctCb(err, accounts); acctCb(err, accounts);
} }
@ -80,8 +85,8 @@ class MochaTestRunner {
(next) => { // request provider (next) => { // request provider
events.request("blockchain:client:provider", "ethereum", next); events.request("blockchain:client:provider", "ethereum", next);
}, },
(bcProvider, next) => { // set provider (provider, next) => { // set provider
web3 = new Web3(bcProvider); web3 = new Web3(provider);
next(); next();
}, },
(next) => { // get accounts (next) => { // get accounts
@ -126,7 +131,7 @@ class MochaTestRunner {
(next) => { // initialize Mocha (next) => { // initialize Mocha
const mocha = new Mocha(); const mocha = new Mocha();
mocha.reporter(Reporter, { reporter: options.reporter }); mocha.reporter(Reporter, { reporter: reporter });
const describeWithAccounts = (scenario, cb) => { const describeWithAccounts = (scenario, cb) => {
Mocha.describe(scenario, cb.bind(mocha, accounts)); Mocha.describe(scenario, cb.bind(mocha, accounts));
}; };

View File

@ -1,11 +1,8 @@
const Mocha = require('mocha'); const Mocha = require('mocha');
const { const {
// EVENT_RUN_BEGIN, EVENT_TEST_BEGIN,
// EVENT_RUN_END,
EVENT_TEST_FAIL, EVENT_TEST_FAIL,
EVENT_TEST_PASS EVENT_TEST_PASS
// EVENT_SUITE_BEGIN,
// EVENT_SUITE_END
} = Mocha.Runner.constants; } = Mocha.Runner.constants;
class Reporter { class Reporter {
@ -17,14 +14,19 @@ class Reporter {
} }
wireRunner() { wireRunner() {
// let testName = ''; let startTime;
this.runner this.runner
.on(EVENT_TEST_BEGIN, _test => {
startTime = Date.now();
})
.on(EVENT_TEST_PASS, test => { .on(EVENT_TEST_PASS, test => {
this.reporter.report(test.fullTitle(), true); const duration = (Date.now() - startTime) / 1000.0;
this.reporter.report(test.fullTitle(), duration, true);
}) })
.on(EVENT_TEST_FAIL, (test, err) => { .on(EVENT_TEST_FAIL, (test, err) => {
this.reporter.report(test.fullTitle(), false, err.message); const duration = (Date.now() - startTime) / 1000.0;
this.reporter.report(test.fullTitle(), duration, false, err.message);
}); });
} }
} }

View File

@ -3,17 +3,17 @@ class Reporter {
this.reporter = reporter; this.reporter = reporter;
} }
report(payload) { report(_err, payload) {
switch(payload.type) { switch(payload.type) {
case 'contract': case 'contract':
this.contract = payload.value; this.contract = payload.value;
this.file = payload.filename; this.file = payload.filename;
break; break;
case 'testPass': case 'testPass':
this.reporter.report(`${this.contract} ${payload.value}`, true); this.reporter.report(`${ this.contract } ${ payload.value }`, payload.time, true);
break; break;
case 'testFailure': case 'testFailure':
this.reporter.report(`${this.contract} ${payload.value}`, false, payload.errMsg); this.reporter.report(`${ this.contract } ${ payload.value }`, payload.time, false, payload.errMsg);
break; break;
default: default:
console.log('dont know how to handle'); console.log('dont know how to handle');
@ -23,4 +23,3 @@ class Reporter {
} }
module.exports = Reporter; module.exports = Reporter;

View File

@ -48,6 +48,7 @@
"dependencies": { "dependencies": {
"@babel/runtime-corejs2": "7.3.1", "@babel/runtime-corejs2": "7.3.1",
"async": "2.6.1", "async": "2.6.1",
"chalk": "2.4.2",
"embark-i18n": "^4.1.1", "embark-i18n": "^4.1.1",
"embark-utils": "^4.1.1", "embark-utils": "^4.1.1",
"fs-extra": "7.0.1", "fs-extra": "7.0.1",

View File

@ -30,7 +30,7 @@ class TestRunner {
} }
run(options, cb) { run(options, cb) {
const reporter = new Reporter(); const reporter = new Reporter(this.embark);
const testPath = options.file || "test"; const testPath = options.file || "test";
async.waterfall([ async.waterfall([

View File

@ -1,7 +1,32 @@
const chalk = require('chalk');
class Reporter { class Reporter {
constructor() { constructor(embark) {
this.embark = embark;
this.passes = 0; this.passes = 0;
this.fails = 0; this.fails = 0;
this.gasAccumulator = 0;
this.wireGasUsage();
}
wireGasUsage() {
const {events} = this.embark;
events.on('blockchain:proxy:response', (params) => {
const {result} = params.respData;
if (!result || !result.gasUsed) {
return;
}
const gas = parseInt(result.gasUsed);
this.gasAccumulator += gas;
});
}
resetGas() {
this.gasAccumulator = 0;
} }
header() { header() {
@ -18,15 +43,30 @@ class Reporter {
} }
} }
report(test, passed, message) { report(test, time, passed, message) {
let timeFormat = 'green';
if (time > 0.7) {
timeFormat = 'yellow';
} else if(time > 1) {
timeFormat = 'red';
}
const formattedGas = this.formatNumber(this.gasAccumulator);
if (passed) { if (passed) {
this.passes++; this.passes++;
process.stdout.write(chalk`{bgGreen.white.bold ${' PASS '}} {underline ${ test }} {bold >} {${ timeFormat } ${ time }s} {bold >} {bold ${ formattedGas } gas}\n`);
process.stdout.write(`>>> ${test} > PASS\n`);
} else { } else {
this.fails++; this.fails++;
process.stdout.write(`>>> ${test} > FAIL (${message || 'no error message'})\n`); process.stdout.write(chalk`{bgRed.white.bold ${' FAIL '}} {underline ${ test }} {bold >} {${ timeFormat } ${ time }s} {bold >} {bold ${ formattedGas } gas} > {red ${message || 'no error message'}}\n`);
} }
this.resetGas();
}
// stolen from https://blog.abelotech.com/posts/number-currency-formatting-javascript/
formatNumber(num) {
return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
} }
} }

4369
yarn.lock

File diff suppressed because it is too large Load Diff