-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
Incorrect empty file coverage #7388
Changes from all commits
d854088
1608330
91fe2ee
8dc0887
7bef9f4
d550165
22093dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,8 +8,11 @@ | |
*/ | ||
'use strict'; | ||
|
||
import istanbulCoverage from 'istanbul-lib-coverage'; | ||
import libSourceMaps from 'istanbul-lib-source-maps'; | ||
import generateEmptyCoverage from '../generateEmptyCoverage'; | ||
|
||
const path = require('path'); | ||
const os = require('os'); | ||
const {makeGlobalConfig, makeProjectConfig} = require('../../../../TestUtils'); | ||
|
||
|
@@ -35,14 +38,32 @@ module.exports = { | |
};`; | ||
|
||
it('generates an empty coverage object for a file without running it', () => { | ||
const coverageMap = istanbulCoverage.createCoverageMap({}); | ||
const sourceMapStore = libSourceMaps.createSourceMapStore(); | ||
const rootDir = '/tmp'; | ||
const filepath = path.join(rootDir, './sum.js'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
const emptyCoverage = generateEmptyCoverage( | ||
src, | ||
'/sum.js', | ||
filepath, | ||
makeGlobalConfig(), | ||
makeProjectConfig({ | ||
cacheDirectory: os.tmpdir(), | ||
rootDir: os.tmpdir(), | ||
rootDir, | ||
transform: [['^.+\\.js$', require.resolve('babel-jest')]], | ||
}), | ||
); | ||
expect(emptyCoverage && emptyCoverage.coverage).toMatchSnapshot(); | ||
|
||
expect(typeof emptyCoverage).toBe('object'); | ||
|
||
let coverage = emptyCoverage && emptyCoverage.coverage; | ||
|
||
if (emptyCoverage && emptyCoverage.sourceMapPath) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The result from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The actually coverage for this piece of code after source map transformation is in this commit and looks like this
|
||
coverageMap.addFileCoverage(emptyCoverage.coverage); | ||
sourceMapStore.registerURL(filepath, emptyCoverage.sourceMapPath); | ||
|
||
coverage = sourceMapStore.transformCoverage(coverageMap).map; | ||
} | ||
|
||
expect(coverage).toMatchSnapshot(); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,14 +9,17 @@ | |
|
||
import type {GlobalConfig, ProjectConfig, Path} from 'types/Config'; | ||
|
||
import {createInstrumenter} from 'istanbul-lib-instrument'; | ||
import {readInitialCoverage} from 'istanbul-lib-instrument'; | ||
import {classes} from 'istanbul-lib-coverage'; | ||
import Runtime from 'jest-runtime'; | ||
|
||
export type CoverageWorkerResult = {| | ||
coverage: any, | ||
sourceMapPath: ?string, | ||
|}; | ||
|
||
const {FileCoverage} = classes; | ||
|
||
export default function( | ||
source: string, | ||
filename: Path, | ||
|
@@ -29,16 +32,15 @@ export default function( | |
collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, | ||
}; | ||
if (Runtime.shouldInstrument(filename, coverageOptions, config)) { | ||
// Transform file without instrumentation first, to make sure produced | ||
// source code is ES6 (no flowtypes etc.) and can be instrumented | ||
const transformResult = new Runtime.ScriptTransformer( | ||
// Transform file with instrumentation to make sure initial coverage data is well mapped to original code. | ||
const {code, mapCoverage, sourceMapPath} = new Runtime.ScriptTransformer( | ||
config, | ||
).transformSource(filename, source, false); | ||
const instrumenter = createInstrumenter(); | ||
instrumenter.instrumentSync(transformResult.code, filename); | ||
).transformSource(filename, source, true); | ||
const extracted = readInitialCoverage(code); | ||
|
||
return { | ||
coverage: instrumenter.fileCoverage, | ||
sourceMapPath: transformResult.sourceMapPath, | ||
coverage: new FileCoverage(extracted.coverageData), | ||
sourceMapPath: mapCoverage ? sourceMapPath : null, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jwbay I think |
||
}; | ||
} else { | ||
return null; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the only change? Not sure how that shows the bug being fixed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original unit test does not transpile the code. It does not pass any transformer.
src code
-->jest.Runtime.ScriptTransformer
without any transformer -->code
without any change -->instrumenter
-->coverageData
That's why the coverage data in the snapshot is CORRECT because it just instruments the src code.
So the original snapchat is CORRECT!
But in real life, we always use some transformer to process code like jsx, TS.So what we want is:
src code
-->jest.Runtime.ScriptTransformer
with some transformer -->code
transpiled -->instrumenter
-->coverageData
However, the
coverageData
is for transpiled code, so we have to source map it to the original code.Since we use babel, we should use
babel-plugin-istanbul
to instrument the code in order to instrument the ES6 code correctly. And when we usebabel-plugin-istanbul
, the coverageData is already for source map.src code
-->jest.Runtime.ScriptTransformer
with some transformer andbabel-plugin-istanbul
-->code
transpiled &coverageData
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason why I change the
path
which is the file path, is that babel requires the file path be inside the rootDir. I set the rootDir to/tmp
and thus the path should be/tmp/sum.js