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

added --all flag for indicating that all files should have coverage applied #44

Merged
merged 6 commits into from
Sep 9, 2015
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ adding the following configuration:
}}
```

## Include Reports For Files That Are Not Required

By default nyc does not collect coverage for files that have not
been required, run nyc with the flag `--all` to enable this.

## Configuring Istanbul

Behind the scenes nyc uses [istanbul](https://www.npmjs.com/package/istanbul). You
Expand Down
8 changes: 8 additions & 0 deletions bin/nyc.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ if (process.env.NYC_CWD) {
type: 'boolean',
describe: "don't output a report after tests finish running"
})
.option('a', {
alias: 'all',
default: false,
type: 'boolean',
describe: 'whether or not to instrument all files of the project (not just the ones touched by your test suite)'
})
.help('h')
.alias('h', 'help')
.version(require('../package.json').version)
Expand Down Expand Up @@ -97,6 +103,8 @@ if (process.env.NYC_CWD) {
var nyc = (new NYC())
nyc.cleanup()

if (argv.all) nyc.addAllFiles()

sw([__filename], {
NYC_CWD: process.cwd()
})
Expand Down
100 changes: 65 additions & 35 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* global __coverage__ */
var _ = require('lodash')
var fs = require('fs')
var glob = require('glob')
var mkdirp = require('mkdirp')
var path = require('path')
var rimraf = require('rimraf')
Expand Down Expand Up @@ -31,8 +32,7 @@ function NYC (opts) {
})

this.instrumenter = this._createInstrumenter()

mkdirp.sync(this.tmpDirectory())
this._createOutputDirectory()
}

NYC.prototype._createInstrumenter = function () {
Expand All @@ -50,56 +50,74 @@ NYC.prototype._createInstrumenter = function () {
})
}

NYC.prototype.cleanup = function () {
if (!process.env.NYC_CWD) rimraf.sync(this.tmpDirectory())
NYC.prototype.addFile = function (filename) {
var instrument = true
var relFile = path.relative(this.cwd, filename)

// only instrument a file if it's not on the exclude list.
for (var i = 0, exclude; (exclude = this.exclude[i]) !== undefined; i++) {
if (exclude.test(relFile)) {
instrument = false
break
}
}

var content = stripBom(fs.readFileSync(filename, 'utf8'))

if (instrument) {
content = this.instrumenter.instrumentSync(content, './' + relFile)
}

return {
instrument: instrument,
content: content,
relFile: relFile
}
}

NYC.prototype._wrapRequire = function () {
NYC.prototype.addAllFiles = function () {
var _this = this

// any JS you require should get coverage added.
require.extensions['.js'] = function (module, filename) {
var instrument = true
var content = fs.readFileSync(filename, 'utf8')

// only instrument a file if it's not on the exclude list.
var relFile = path.relative(_this.cwd, filename)
for (var i = 0, exclude; (exclude = _this.exclude[i]) !== undefined; i++) {
if (exclude.test(relFile)) {
instrument = false
break
}
}
this._createOutputDirectory()

if (instrument) {
content = _this.instrumenter.instrumentSync(
content,
'./' + relFile
glob.sync('**/*.js').forEach(function (filename) {
var obj = _this.addFile(filename)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are now reading full file contents of files that should be excluded. Potentially quite a painful performance hit.

if (obj.instrument) {
module._compile(
_this.instrumenter.getPreamble(obj.content, obj.relFile),
filename
)
}
})

module._compile(stripBom(content), filename)
this.writeCoverageFile()
}

NYC.prototype._wrapRequire = function () {
var _this = this

// any JS you require should get coverage added.
require.extensions['.js'] = function (module, filename) {
var obj = _this.addFile(filename)
module._compile(obj.content, filename)
}
}

NYC.prototype.cleanup = function () {
if (!process.env.NYC_CWD) rimraf.sync(this.tmpDirectory())
}

NYC.prototype._createOutputDirectory = function () {
mkdirp.sync(this.tmpDirectory())
}

NYC.prototype._wrapExit = function () {
var _this = this
var outputCoverage = function () {
var coverage = global.__coverage__
if (typeof __coverage__ === 'object') coverage = __coverage__
if (!coverage) return

fs.writeFileSync(
path.resolve(_this.tmpDirectory(), './', process.pid + '.json'),
JSON.stringify(coverage),
'utf-8'
)
}

// we always want to write coverage
// regardless of how the process exits.
onExit(function () {
outputCoverage()
_this.writeCoverageFile()
}, {alwaysLast: true})
}

Expand All @@ -109,6 +127,18 @@ NYC.prototype.wrap = function (bin) {
return this
}

NYC.prototype.writeCoverageFile = function () {
var coverage = global.__coverage__
if (typeof __coverage__ === 'object') coverage = __coverage__
if (!coverage) return

fs.writeFileSync(
path.resolve(this.tmpDirectory(), './', process.pid + '.json'),
JSON.stringify(coverage),
'utf-8'
)
}

NYC.prototype.report = function (cb, _collector, _reporter) {
cb = cb || function () {}

Expand Down
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"config": {
"nyc": {
"exclude": [
"node_modules"
"node_modules",
"bin"
]
}
},
Expand All @@ -37,7 +38,8 @@
"license": "ISC",
"dependencies": {
"foreground-child": "^1.3.0",
"istanbul": "^0.3.16",
"glob": "^5.0.14",
"istanbul": "^0.3.19",
"lodash": "^3.10.0",
"mkdirp": "^0.5.0",
"rimraf": "^2.4.2",
Expand All @@ -49,8 +51,8 @@
"devDependencies": {
"chai": "^3.0.0",
"sinon": "^1.15.3",
"standard": "^4.5.4",
"tap": "^1.3.0"
"standard": "^5.2.1",
"tap": "^1.3.4"
},
"repository": {
"type": "git",
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/not-loaded.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var i = 3 + 5
i++
45 changes: 44 additions & 1 deletion test/nyc-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ describe('nyc', function () {
var fixtures = path.resolve(__dirname, './fixtures')

describe('cwd', function () {

function afterEach () {
delete process.env.NYC_CWD
rimraf.sync(path.resolve(fixtures, './nyc_output'))
Expand Down Expand Up @@ -89,6 +88,14 @@ describe('nyc', function () {
it('writes coverage report when process is killed with SIGINT', function (done) {
testSignal('sigint', done)
})

it('does not output coverage for files that have not been included, by default', function (done) {
var reports = _.filter(nyc._loadReports(), function (report) {
return report['./test/fixtures/not-loaded.js']
})
reports.length.should.equal(0)
return done()
})
})

describe('report', function () {
Expand Down Expand Up @@ -271,4 +278,40 @@ describe('nyc', function () {
munged.should.eql(['node', 'test/nyc-test.js'])
})
})

describe('addAllFiles', function () {
it('outputs an empty coverage report for all files that are not excluded', function (done) {
var nyc = (new NYC())
nyc.addAllFiles()

var reports = _.filter(nyc._loadReports(), function (report) {
return report['./test/fixtures/not-loaded.js']
})
var report = reports[0]['./test/fixtures/not-loaded.js']

reports.length.should.equal(1)
report.s['1'].should.equal(0)
report.s['2'].should.equal(0)
return done()
})

it('tracks coverage appropriately once the file is required', function (done) {
var nyc = (new NYC({
cwd: process.cwd()
})).wrap()
require('./fixtures/not-loaded')
nyc.writeCoverageFile()

var reports = _.filter(nyc._loadReports(), function (report) {
return report['./test/fixtures/not-loaded.js']
})
var report = reports[0]['./test/fixtures/not-loaded.js']

reports.length.should.equal(1)
report.s['1'].should.equal(1)
report.s['2'].should.equal(1)

return done()
})
})
})