I've noticed a significant slow down when testing a project which is using source-map-support/register but its only apparent when throwing custom errors, its unnoticeable in other tests.
I have left a test case below showing 4327ms vs 10ms (which is worse at 4317% slower)
jest.config.js
module.exports = {
transform: {
'^.+\\.ts$': 'ts-jest'
},
testRegex: '(/test/.*/.*\\.ts)$',
moduleFileExtensions: [
'ts',
'tsx',
'js',
'jsx',
'json',
'node'
]
}
test/generic/options.test.ts
import 'source-map-support/register'
class UnexpectedError extends Error {
static EXPECTED_HTML = {
message: 'Wrong content type header - "text/html" or "application/xhtml+xml" was expected',
name: 'WRONG_CONTENT_TYPE'
}
static BAD_OPTIONS = {
message: 'Bad options (see Opts), options must be an Object',
name: 'BAD_OPTIONS'
}
constructor (errorType: { message: string, name: string }) {
super(errorType.message)
this.name = errorType.name
this.stack = new Error().stack
}
}
test('should throw bad options error', async () => {
try {
throw new UnexpectedError(UnexpectedError.BAD_OPTIONS)
} catch (err) {
expect(err.message).toEqual(UnexpectedError.BAD_OPTIONS.message)
}
})
An example run:
With import 'source-map-support/register':
⬢ ~/dev/unfurl wip ⦿ ./node_modules/jest/bin/jest.js test/generic/options.test.ts
PASS test/generic/options.test.ts
✓ should throw bad options error (4327ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.532s
Ran all test suites matching /test\/generic\/options.test.ts/i.
Without import 'source-map-support/register':
⬢ ~/dev/unfurl wip ⦿ ./node_modules/jest/bin/jest.js test/generic/options.test.ts
PASS test/generic/options.test.ts
✓ should throw bad options error (10ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.273s, estimated 5s
Ran all test suites matching /test\/generic\/options.test.ts/i.
@jacktuck thanks for reporting this issue. What version of jest do you have? If it's 23.1.4, can you try using the latest beta following #697 instructions (it's about to be released tho).
Source maps support is already coming out of the box with jest and ts-jest so you don't need to use source-map-support.
UPDATE: IF the require('source-maps-support/require') is within you source files, maybe you should wrap it within a if (process.env.NODE_ENV !== 'test') block (Jest defines this env var if it is not set so you don't have to worry about it being defined or not when running tests).
If the require('source-maps-support/require') is within your tests, it should be safe to remove it
@huafu downgrading ts-jest seemed to fix it, i think.
⬢ ~/dev/unfurl wip ⦿ npm list jest ts-jest
[email protected] /Users/jt/dev/unfurl
├── [email protected]
└── [email protected]
⬢ ~/dev/unfurl wip ⦿ ./node_modules/jest/bin/jest.js test/generic/options.test.ts
PASS test/generic/options.test.ts
✓ should throw bad options error (2520ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 3.578s, estimated 4s
Ran all test suites matching /test\/generic\/options.test.ts/i.
⬢ ~/dev/unfurl wip ⦿ npm i ts-jest@22
npm WARN [email protected] requires a peer of [email protected] but none is installed. You must install peer dependencies yourself.
+ [email protected]
added 66 packages, removed 1 package and updated 2 packages in 6.388s
⬢ ~/dev/unfurl wip ⦿ ./node_modules/jest/bin/jest.js test/generic/options.test.ts
PASS test/generic/options.test.ts
✓ should throw bad options error (10ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.813s, estimated 4s
Ran all test suites matching /test\/generic\/options.test.ts/i.
⬢ ~/dev/unfurl wip ⦿ npm list jest ts-jest
[email protected] /Users/jt/dev/unfurl
├── [email protected]
└── [email protected]
[email protected] (~3000ms) -> [email protected](~10ms)
UPDATE: IF the require('source-maps-support/require') is within you source files
Yeah that is the case. I kept the source inline for the test so it's easier to see what's going on.
maybe you should wrap it within a if (!process.env.TEST) block
That would work but it feels it bit janky, plus reading ENV is slow if i remember correctly
@jacktuck try beta (see #697), and run tests once to get all in the cache (might be slow), then run once again to see the real speed once all is in the cache.
Anyway, since it's in your source files, you should also wrap the require('source-maps-support/require') within a if ( process.env.NODE_ENV !== 'test' ). Jest automatically adds source mapping. Doing this require will be like processing source files twice thru source mapping tools.
If you are still stuck with this, feel free to join us on Slack for further help.
// Remove this
// import 'source-map-support/register'
// And replace with:
if (process.env.NODE_ENV !== 'test') {
// tslint:disable-next-line:no-var-requires
require('source-map-support/register')
}
@jacktuck be careful, I've fixed the code related to the env var as it was wrong.
Anyway, the clean way to go:
setupFiles section, or prepend a file to it if the section exists:js
"setupFiles": ["tests/mock-source-maps-support.ts"]
tests/mock-source-maps-support.ts, add this:js
jest.mock('source-map-support/register')
then you don't have to change your source files, and the import of source-map-support/register will have no effect
Thanks.
Mocking didn't work, not sure why, it was still just as slow.
I'm just doing this for now, which works, but i don't love.
if (!process.env.disable_source_map) {
require('source-map-support').install()
}
"scripts": {
"test": "disable_source_map=true jest --verbose --runInBand --coverage --coveragePathIgnorePatterns '/test/'",
"travis": "disable_source_map=true jest --verbose --runInBand --coverage --coverageReporters=text-lcov --coveragePathIgnorePatterns '/test/' | coveralls",
"start": "node dist/index.js",
"watch": "tsc -w --outDir dist",
"build": "tsc --outDir dist"
}
@jacktuck I think it does not work if you have resetModules or so enabled.
If you have automocking, you could also try having a __mocks__/source-map-support/register.ts with nothing inside. I say could because I am unsure how jest handles sub-folders for mocks.
Instead of using your disable_source_map you should rely on the NODE_ENV being test or not, since it's common to have it set to test for tests, and jest is also setting it to test in case it wasn't set before.
if there is still the issue, feel free to open another one.
Most helpful comment
@jacktuck be careful, I've fixed the code related to the env var as it was wrong.
Anyway, the clean way to go:
setupFilessection, or prepend a file to it if the section exists:js "setupFiles": ["tests/mock-source-maps-support.ts"]tests/mock-source-maps-support.ts, add this:js jest.mock('source-map-support/register')then you don't have to change your source files, and the import of
source-map-support/registerwill have no effect