Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for --coverage-map=<module> #533

Merged
merged 5 commits into from
Apr 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions bin/jack.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,24 @@ Much more documentation available at: https://www.node-tap.org/
coverage entirely with --no-coverage.`,
}),

'coverage-map': opt({
short: 'M',
hint: 'module',
description: `Provide a path to a node module that exports a single
function. That function takes a test file as an argument,
and returns an array of files to instrument with coverage
when that file is run.

This is useful in cases where a unit test should cover
a single portion of the system under test.

Return 'null' to not cover any files by this test.

Return an empty array [] to cover the set that nyc would
pull in by default. Ie, returning [] is equivalent to not
using a coverage map at all.`,
}),

coverage: flag({
default: true,
short: 'cov',
Expand Down
32 changes: 29 additions & 3 deletions bin/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const defaultFiles = options => new Promise((res, rej) => {
const files = []
finder.on('file', addFile(files))
finder.on('end', () => res(files))
finder.on('error', er => rej(er))
finder.on('error', /* istanbul ignore next */ er => rej(er))
})
}))).then(a => res(a.reduce((a, i) => a.concat(i), []))).catch(rej)
})
Expand Down Expand Up @@ -139,7 +139,10 @@ const main = async options => {
try {
if (options._.length === 0 && isTTY)
options._.push.apply(options._, await defaultFiles(options))
} catch (er) {
} /* istanbul ignore next */ catch (er) /* istanbul ignore next */ {
// This gets tested on Mac, but not Linux/travis, and is
// somewhat challenging to do in a cross-platform way.
/* istanbul ignore next */
return require('../lib/tap.js').threw(er)
}

Expand Down Expand Up @@ -231,7 +234,11 @@ const pipeToCoveralls = async options => {

/* istanbul ignore next */
const respawnWithCoverage = options => {
runNyc([], [
// If we have a coverage map, then include nothing by default here.
runNyc(options['coverage-map'] ? [
'--include=',
'--no-exclude-after-remap',
] : [], [
'--',
node,
...process.execArgv,
Expand Down Expand Up @@ -431,6 +438,17 @@ const getEnv = options => options['test-env'].reduce((env, kv) => {
return env
}, {...process.env})

// the test that checks this escapes from NYC, so it'll never show up
/* istanbul ignore next */
const coverageMapOverride = (env, file, coverageMap) => {
if (coverageMap) {
/* istanbul ignore next */
env.NYC_CONFIG_OVERRIDE = JSON.stringify({
include: coverageMap(file) || ''
})
}
}

const runAllFiles = (options, saved, tap) => {
let doStdin = false
let parallelOk = Object.create(null)
Expand All @@ -456,9 +474,15 @@ const runAllFiles = (options, saved, tap) => {
tap.fail('no tests specified')
}

/* istanbul ignore next */
const processDB = options.coverage && process.env.NYC_CONFIG
? new ProcessDB() : null

/* istanbul ignore next */
const coverageMap = options['coverage-map']
? require(path.resolve(options['coverage-map']))
: null

for (let i = 0; i < options.files.length; i++) {
const file = options.files[i]

Expand All @@ -484,6 +508,8 @@ const runAllFiles = (options, saved, tap) => {
} else {
const opt = { env, file, processDB }

coverageMapOverride(env, file, coverageMap)

if (options.timeout)
opt.timeout = options.timeout * 1000

Expand Down
22 changes: 22 additions & 0 deletions coverage-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const glob = require('glob')
const path = require('path')
module.exports = t => {
const parts = path.relative(process.cwd(), path.resolve(t)).split(/\\|\//)
const unit = path.basename(parts[1], '.js')
if (unit === 'run')
return glob.sync('bin/*.js')
if (unit === 'coverage-map')
return [ path.basename(__filename) ]
const cov = glob.sync(`lib/${unit}.js`)
if (!cov.length)
return null
return cov
}

/* istanbul ignore next */
if (module === require.main) {
const tests = process.argv.length > 2
? process.argv.slice(2)
: glob.sync('test/**/*.js')
console.log(tests.map(t => [t, module.exports(t)]))
}
15 changes: 15 additions & 0 deletions docs/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,21 @@ Code Coverage Options:
coverage checking with --no-check-coverage, or disable
coverage entirely with --no-coverage.

-M<module> --coverage-map=<module>
Provide a path to a node module that exports a single
function. That function takes a test file as an
argument, and returns an array of files to instrument
with coverage when that file is run.

This is useful in cases where a unit test should cover
a single portion of the system under test.

Return 'null' to not cover any files by this test.

Return an empty array [] to cover the set that nyc
would pull in by default. Ie, returning [] is
equivalent to not using a coverage map at all.

-cov --coverage Capture coverage information using 'nyc' This is
enabled by default.

Expand Down
3 changes: 2 additions & 1 deletion lib/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class Base extends MiniPass {
this.output = ''
this.results = null
this.bailedOut = false
this.childId = +ownOrEnv(options, 'childId', 'TAP_CHILD_ID') || 0
this.childId = +ownOrEnv(options, 'childId', 'TAP_CHILD_ID')
|| /* istanbul ignore next */ 0
const skip = ownOr(options, 'skip', false)
const todo = ownOr(options, 'todo', false)
if (skip || todo)
Expand Down
4 changes: 3 additions & 1 deletion lib/spawn.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ class Spawn extends Base {
options.env = process.env
this.env = {
...(options.env),
TAP_CHILD_ID: options.childId || options.env.TAP_CHILD_ID || this.childId,
TAP_CHILD_ID: options.childId
|| options.env.TAP_CHILD_ID
|| /* istanbul ignore next */ 0,
TAP: '1',
TAP_BAIL: this.bail ? '1' : '0',
}
Expand Down
3 changes: 2 additions & 1 deletion lib/tap.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ class TAP extends Test {
constructor (options) {
super(options)
this.runOnly = process.env.TAP_ONLY === '1'
this.childId = +process.env.TAP_CHILD_ID || 0
this.childId = +process.env.TAP_CHILD_ID
|| /* istanbul ignore next */ 0
this.start = Date.now()
this[_didPipe] = false
}
Expand Down
2 changes: 1 addition & 1 deletion lib/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class Test extends Base {
constructor (options) {
options = options || {}
super(options)
this[_nextChildId] = 0
this[_nextChildId] = 1
this.pushedEnd = false
this.jobs = ownOr(options, 'jobs', 1)

Expand Down
18 changes: 9 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
"import-jsx": "^2.0.0",
"isexe": "^2.0.0",
"istanbul-lib-processinfo": "^1.0.0",
"jackspeak": "^1.3.4",
"jackspeak": "^1.3.5",
"minipass": "^2.3.5",
"mkdirp": "^0.5.1",
"nyc": "^14.0.0",
"nyc": "github:isaacs/nyc#conf-override",
"opener": "^1.5.1",
"own-or": "^1.0.0",
"own-or-env": "^1.0.1",
Expand Down Expand Up @@ -65,7 +65,7 @@
"repository": "https://github.com/tapjs/node-tap.git",
"scripts": {
"snap": "bash scripts/snap.sh",
"test": "node bin/run.js test",
"test": "node bin/run.js test -M coverage-map.js",
"unit": "bash scripts/unit.sh",
"posttest": "rm -rf cli-tests-*",
"postunit": "npm run posttest",
Expand Down
2 changes: 1 addition & 1 deletion scripts/unit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ else
include=$(echo +(bin|lib)/$1.js)
if [ -f "$include" ]; then
set -x
node bin/run.js test/${1}* --nyc-arg=--include="$include" -Rterse
node bin/run.js test/${1}* --nyc-arg=--include="$include" -Rterse -M coverage-map.js
else
set -x
node bin/run.js test/${1}* --no-cov -Rterse
Expand Down
51 changes: 50 additions & 1 deletion tap-snapshots/test-run-coverage.js-TAP.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,31 @@
* Make sure to inspect the output below. Do not ignore changes!
*/
'use strict'
exports[`test/run/coverage.js TAP generate some coverage > 100 pass 1`] = `
exports[`test/run/coverage.js TAP borked coverage map means no includes > output 1`] = `
TAP version 13
ok 1 - 1.test.js # {time} {
ok 1 - should be equal
1..1
# {time}
}

ok 2 - 2.test.js # {time} {
ok 1 - should be equal
1..1
# {time}
}

1..2
# {time}
-|-|-|-|-|-|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Lines |
-|-|-|-|-|-|
All files | 0 | 0 | 0 | 0 | |
-|-|-|-|-|-|

`

exports[`test/run/coverage.js TAP generate some coverage > output 1`] = `
TAP version 13
ok 1 - 1.test.js # {time} {
ok 1 - should be equal
Expand Down Expand Up @@ -156,3 +180,28 @@ BRH:3
end_of_record

`

exports[`test/run/coverage.js TAP use a coverage map > output 1`] = `
TAP version 13
ok 1 - 1.test.js # {time} {
ok 1 - should be equal
1..1
# {time}
}

ok 2 - 2.test.js # {time} {
ok 1 - should be equal
1..1
# {time}
}

1..2
# {time}
-|-|-|-|-|-|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Lines |
-|-|-|-|-|-|
All files | 75 | 75 | 100 | 75 | |
ok.js | 75 | 75 | 100 | 75 | 6 |
-|-|-|-|-|-|

`
8 changes: 8 additions & 0 deletions tap-snapshots/test-run-dump-config.js-TAP.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ check-coverage: true
color: true
comments: false
coverage: false
coverage-map: null
coverage-report: null
debug: false
esm: false
Expand Down Expand Up @@ -55,6 +56,7 @@ check-coverage: true
color: false
comments: false
coverage: false
coverage-map: null
coverage-report: null
debug: false
esm: false
Expand Down Expand Up @@ -97,6 +99,7 @@ check-coverage: false
color: false
comments: false
coverage: false
coverage-map: null
coverage-report: null
debug: false
esm: false
Expand Down Expand Up @@ -139,6 +142,7 @@ check-coverage: false
color: false
comments: false
coverage: false
coverage-map: null
coverage-report: null
debug: false
esm: false
Expand Down Expand Up @@ -181,6 +185,7 @@ check-coverage: false
color: false
comments: false
coverage: false
coverage-map: null
coverage-report: null
debug: false
esm: false
Expand Down Expand Up @@ -223,6 +228,7 @@ check-coverage: true
color: false
comments: false
coverage: false
coverage-map: null
coverage-report: null
debug: false
esm: false
Expand Down Expand Up @@ -265,6 +271,7 @@ check-coverage: true
color: false
comments: true
coverage: true
coverage-map: null
coverage-report: html
debug: true
esm: false
Expand Down Expand Up @@ -318,6 +325,7 @@ check-coverage: true
color: true
comments: false
coverage: false
coverage-map: null
coverage-report: null
debug: false
esm: false
Expand Down
10 changes: 10 additions & 0 deletions test/coverage-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const t = require('../')
const coverageMap = require('../coverage-map.js')
t.strictSame(coverageMap('test/coverage-map.js'), ['coverage-map.js'])
t.strictSame(coverageMap('test/run/xyz.js'), [
'bin/jack.js',
'bin/jsx.js',
'bin/run.js'
])
t.strictSame(coverageMap('test/glorp.js'), null)
t.strictSame(coverageMap('test/test.js'), ['lib/test.js'])