forked from gotwarlost/istanbul
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add check-coverage command, update tests and set up self coverage check
- Loading branch information
1 parent
2c56237
commit a3bb5f5
Showing
5 changed files
with
192 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
/* | ||
Copyright (c) 2012, Yahoo! Inc. All rights reserved. | ||
Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. | ||
*/ | ||
|
||
var nopt = require('nopt'), | ||
path = require('path'), | ||
fs = require('fs'), | ||
Collector = require('../collector'), | ||
formatOption = require('../util/help-formatter').formatOption, | ||
util = require('util'), | ||
utils = require('../object-utils'), | ||
filesFor = require('../util/file-matcher').filesFor, | ||
Command = require('./index'); | ||
|
||
function CheckCoverageCommand() { | ||
Command.call(this); | ||
} | ||
|
||
CheckCoverageCommand.TYPE = 'check-coverage'; | ||
util.inherits(CheckCoverageCommand, Command); | ||
|
||
Command.mix(CheckCoverageCommand, { | ||
synopsis: function () { | ||
return "checks overall coverage against thresholds from coverage JSON files. Exits 1 if thresholds are not met, 0 otherwise"; | ||
}, | ||
|
||
usage: function () { | ||
console.error('\nUsage: ' + this.toolName() + ' ' + this.type() + ' <options> [<include-pattern>]\n\nOptions are:\n\n' + | ||
[ | ||
formatOption('--statements <threshold>', 'The minimum statement coverage required as a percentage'), | ||
formatOption('--functions <threshold>', 'The minimum statement threshold coverage required as a percentage'), | ||
formatOption('--branches <threshold>', 'The minimum branch coverage required as a percentage'), | ||
formatOption('--lines <threshold>', 'The minimum line coverage required as a percentage') | ||
].join('\n\n') + '\n'); | ||
|
||
console.error('\n'); | ||
|
||
console.error('<include-pattern> is a fileset pattern that can be used to select one or more coverage files ' + | ||
'for merge. This defaults to "**/coverage*.json"'); | ||
|
||
console.error('\n'); | ||
}, | ||
|
||
run: function (args, callback) { | ||
|
||
var config = { | ||
root: path, | ||
dir: path, | ||
statements: Number, | ||
lines: Number, | ||
branches: Number, | ||
functions: Number, | ||
verbose: Boolean | ||
}, | ||
opts = nopt(config, { v : '--verbose' }, args, 0), | ||
includePattern = '**/coverage*.json', | ||
root, | ||
collector = new Collector(), | ||
errors = []; | ||
|
||
if (opts.argv.remain.length > 0) { | ||
includePattern = opts.argv.remain[0]; | ||
} | ||
|
||
root = opts.root || process.cwd(); | ||
filesFor({ | ||
root: root, | ||
includes: [ includePattern ] | ||
}, function (err, files) { | ||
if (err) { throw err; } | ||
files.forEach(function (file) { | ||
var coverageObject = JSON.parse(fs.readFileSync(file, 'utf8')); | ||
collector.add(coverageObject); | ||
}); | ||
var thresholds = { | ||
statements: opts.statements || 0, | ||
branches: opts.branches || 0, | ||
lines: opts.lines || 0, | ||
functions: opts.functions || 0 | ||
}, | ||
actuals = utils.summarizeCoverage(collector.getFinalCoverage()); | ||
|
||
if (opts.verbose) { | ||
console.log('Compare actuals against thresholds'); | ||
console.log(JSON.stringify({ actuals: actuals, thresholds: thresholds }, undefined, 4)); | ||
} | ||
|
||
Object.keys(thresholds).forEach(function (key) { | ||
var actual = actuals[key].pct, | ||
threshold = thresholds[key]; | ||
|
||
if (actual < threshold) { | ||
errors.push('ERROR: Coverage for ' + key + ' (' + actual + '%) does not meet threshold (' + threshold + '%)'); | ||
} | ||
}); | ||
return callback(errors.length === 0 ? null : errors.join("\n")); | ||
}); | ||
} | ||
}); | ||
|
||
module.exports = CheckCoverageCommand; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/*jslint nomen: true */ | ||
var path = require('path'), | ||
fs = require('fs'), | ||
rimraf = require('rimraf'), | ||
mkdirp = require('mkdirp'), | ||
COMMAND = 'check-coverage', | ||
COVER_COMMAND = 'cover', | ||
DIR = path.resolve(__dirname, 'sample-project'), | ||
OUTPUT_DIR = path.resolve(DIR, 'coverage'), | ||
helper = require('../cli-helper'), | ||
existsSync = fs.existsSync || path.existsSync, | ||
run = helper.runCommand.bind(null, COMMAND), | ||
runCover = helper.runCommand.bind(null, COVER_COMMAND); | ||
|
||
module.exports = { | ||
setUp: function (cb) { | ||
rimraf.sync(OUTPUT_DIR); | ||
mkdirp.sync(OUTPUT_DIR); | ||
helper.resetOpts(); | ||
runCover([ 'test/run.js', '--report', 'none' ], function (results) { | ||
cb(); | ||
}); | ||
}, | ||
tearDown: function (cb) { | ||
rimraf.sync(OUTPUT_DIR); | ||
cb(); | ||
}, | ||
"should fail on inadequate statement coverage": function (test) { | ||
test.ok(existsSync(path.resolve(OUTPUT_DIR, 'coverage.json'))); | ||
run([ '--statements', '72' ], function (results) { | ||
test.ok(!results.succeeded()); | ||
test.ok(results.grepError(/Coverage for statements/)); | ||
test.done(); | ||
}); | ||
}, | ||
"should fail on inadequate branch coverage": function (test) { | ||
test.ok(existsSync(path.resolve(OUTPUT_DIR, 'coverage.json'))); | ||
run([ '--branches', '72' ], function (results) { | ||
test.ok(!results.succeeded()); | ||
test.ok(results.grepError(/Coverage for branches/)); | ||
test.done(); | ||
}); | ||
}, | ||
"should fail on inadequate function coverage": function (test) { | ||
test.ok(existsSync(path.resolve(OUTPUT_DIR, 'coverage.json'))); | ||
run([ '--functions', '72' ], function (results) { | ||
test.ok(!results.succeeded()); | ||
test.ok(results.grepError(/Coverage for functions/)); | ||
test.done(); | ||
}); | ||
}, | ||
"should fail on inadequate line coverage": function (test) { | ||
test.ok(existsSync(path.resolve(OUTPUT_DIR, 'coverage.json'))); | ||
run([ '--lines', '72' ], function (results) { | ||
test.ok(!results.succeeded()); | ||
test.ok(results.grepError(/Coverage for lines/)); | ||
test.done(); | ||
}); | ||
}, | ||
"should fail with multiple reasons when multiple thresholds violated": function (test) { | ||
test.ok(existsSync(path.resolve(OUTPUT_DIR, 'coverage.json'))); | ||
run([ '--statements=72','--functions=50','--branches=72','--lines=72', '-v' ], function (results) { | ||
test.ok(!results.succeeded()); | ||
test.ok(results.grepError(/Coverage for lines/)); | ||
test.ok(results.grepError(/Coverage for statements/)); | ||
test.ok(results.grepError(/Coverage for branches/)); | ||
test.ok(!results.grepError(/Coverage for functions/)); | ||
test.ok(!results.grepOutput(/\\"actuals\\"/), "Verbose message not printed as expected"); | ||
test.done(); | ||
}); | ||
}, | ||
"should succeed with any threshold when no coverage found": function (test) { | ||
test.ok(existsSync(path.resolve(OUTPUT_DIR, 'coverage.json'))); | ||
run([ '--statements', '72', '**/foobar.json' ], function (results) { | ||
test.ok(results.succeeded()); | ||
test.done(); | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters