Skip to content

Commit bbadc1f

Browse files
AmShaegar13bcoe
authored andcommitted
feat: add support for per file coverage checking (#591)
1 parent e9fad9f commit bbadc1f

File tree

5 files changed

+61
-8
lines changed

5 files changed

+61
-8
lines changed

README.md

+7
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ nyc --check-coverage --lines 100 npm test
153153

154154
The above check fails if coverage falls below 100%.
155155

156+
To check thresholds on a per-file basis run:
157+
158+
```shell
159+
nyc check-coverage --lines 95 --per-file
160+
```
161+
156162
## Running reports
157163

158164
Once you've run your tests with nyc, simply run:
@@ -240,6 +246,7 @@ Any configuration options that can be set via the command line can also be speci
240246
"description": "These are just examples for demonstration, nothing prescriptive",
241247
"nyc": {
242248
"check-coverage": true,
249+
"per-file": true,
243250
"lines": 99,
244251
"statements": 99,
245252
"functions": 99,

bin/nyc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,5 @@ function checkCoverage (argv, cb) {
9797
functions: argv.functions,
9898
branches: argv.branches,
9999
statements: argv.statements
100-
})
100+
}, argv['per-file'])
101101
}

index.js

+22-7
Original file line numberDiff line numberDiff line change
@@ -441,21 +441,36 @@ NYC.prototype.showProcessTree = function () {
441441
console.log(processTree.render(this))
442442
}
443443

444-
NYC.prototype.checkCoverage = function (thresholds) {
444+
NYC.prototype.checkCoverage = function (thresholds, perFile) {
445445
var map = this._getCoverageMapFromAllCoverageFiles()
446-
var summary = map.getCoverageSummary()
446+
var nyc = this
447447

448-
// ERROR: Coverage for lines (90.12%) does not meet global threshold (120%)
448+
if (perFile) {
449+
map.files().forEach(function (file) {
450+
// ERROR: Coverage for lines (90.12%) does not meet threshold (120%) for index.js
451+
nyc._checkCoverage(map.fileCoverageFor(file).toSummary(), thresholds, file)
452+
})
453+
} else {
454+
// ERROR: Coverage for lines (90.12%) does not meet global threshold (120%)
455+
nyc._checkCoverage(map.getCoverageSummary(), thresholds)
456+
}
457+
458+
// process.exitCode was not implemented until v0.11.8.
459+
if (/^v0\.(1[0-1]\.|[0-9]\.)/.test(process.version) && process.exitCode !== 0) process.exit(process.exitCode)
460+
}
461+
462+
NYC.prototype._checkCoverage = function (summary, thresholds, file) {
449463
Object.keys(thresholds).forEach(function (key) {
450464
var coverage = summary[key].pct
451465
if (coverage < thresholds[key]) {
452466
process.exitCode = 1
453-
console.error('ERROR: Coverage for ' + key + ' (' + coverage + '%) does not meet global threshold (' + thresholds[key] + '%)')
467+
if (file) {
468+
console.error('ERROR: Coverage for ' + key + ' (' + coverage + '%) does not meet threshold (' + thresholds[key] + '%) for ' + file)
469+
} else {
470+
console.error('ERROR: Coverage for ' + key + ' (' + coverage + '%) does not meet global threshold (' + thresholds[key] + '%)')
471+
}
454472
}
455473
})
456-
457-
// process.exitCode was not implemented until v0.11.8.
458-
if (/^v0\.(1[0-1]\.|[0-9]\.)/.test(process.version) && process.exitCode !== 0) process.exit(process.exitCode)
459474
}
460475

461476
NYC.prototype._loadProcessInfos = function () {

lib/config-util.js

+10
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ Config.buildYargs = function (cwd) {
9393
default: 0,
9494
description: 'what % of statements must be covered?'
9595
})
96+
.option('per-file', {
97+
default: false,
98+
description: 'check thresholds per file'
99+
})
96100
.example('$0 check-coverage --lines 95', "check whether the JSON in nyc's output folder meets the thresholds provided")
97101
})
98102
.option('reporter', {
@@ -195,6 +199,12 @@ Config.buildYargs = function (cwd) {
195199
description: 'should nyc detect and handle source maps?',
196200
global: false
197201
})
202+
.option('per-file', {
203+
default: false,
204+
type: 'boolean',
205+
description: 'check thresholds per file',
206+
global: false
207+
})
198208
.option('produce-source-map', {
199209
default: false,
200210
type: 'boolean',

test/nyc-bin.js

+21
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,27 @@ describe('the nyc cli', function () {
141141
done()
142142
})
143143
})
144+
145+
it('fails when the expected file coverage is below a threshold', function (done) {
146+
var args = [bin, '--check-coverage', '--lines', '51', '--per-file', process.execPath, './half-covered.js']
147+
var matcher = RegExp('ERROR: Coverage for lines \\(50%\\) does not meet threshold \\(51%\\) for .+/half-covered.js')
148+
149+
var proc = spawn(process.execPath, args, {
150+
cwd: fixturesCLI,
151+
env: env
152+
})
153+
154+
var stderr = ''
155+
proc.stderr.on('data', function (chunk) {
156+
stderr += chunk
157+
})
158+
159+
proc.on('close', function (code) {
160+
code.should.not.equal(0)
161+
stderr.trim().should.match(matcher)
162+
done()
163+
})
164+
})
144165
})
145166

146167
// https://github.com/bcoe/nyc/issues/190

0 commit comments

Comments
 (0)