I have a Typescript-based React project in which I am running jest tests (also in TS). I can run tests fine but am trying to profile the performance of some which take quite a long time to run. I have tried using Chrome Devtools to attach to the tests, which it does, however it fails due to it being TS and not plain Js. Is there any way I can profile my tests individually to see where the performance issue is occurring? Using VS Code.
Instead of a React project, it was just a regular TypeScript library for me, but I bet this also works for your use-case. I am leaving this here, in case it's usable, or for future me.
The ONLY solution I found that worked was manually setting up the profiler v8-profiler-next.
import * as fs from 'fs';
import * as v8Profiler from 'v8-profiler-next';
v8Profiler.setGenerateType(1);
const title = 'good-name';
describe('Should be able to generate with inputs', () => {
v8Profiler.startProfiling(title, true);
afterAll(() => {
const profile = v8Profiler.stopProfiling(title);
profile.export(function (error, result: any) {
// if it doesn't have the extension .cpuprofile then
// chrome's profiler tool won't like it.
// examine the profile:
// Navigate to chrome://inspect
// Click Open dedicated DevTools for Node
// Select the profiler tab
// Load your file
fs.writeFileSync(`${title}.cpuprofile`, result);
profile.delete();
});
});
test('....', async () => {
// Add test
});
});
This then gives you the CPU profile as such, which works fine with TypeScript.
TL;DR
Search for your functional, daily test script and create your new profiler script just adding the --inspect
or --inspect-brk
to the node call. If your test script calls jest directly, make the new test:inspect script verbose, calling node on jest.
Detailed
I just had the same problem, and in my case the problem is that my jest config file is in a custom folder. It is pretty easy to discover if this is your case also.
First, go to the scripts entry in your package.json and find the script you usually run in your daily tests (the one that already works). In my case I had kind of a chain (an unnecessary and poorly designed chain, in my opinion, but I will add it here because it might help if you have the same case): the npm run test
calls the test:unit
without adding anything; the test:unit
removes any flags passed, calling test:base
with coverage and max-workers flags; finally, the test:base
was the one that calls jest:
"test": "npm run test:unit",
"test:base": "cross-env NODE_ENV=test node --expose-gc --no-compilation-cache ./node_modules/jest/bin/jest.js --logHeapUsage --config ./config/jest.config.js --colors --rootDir . --passWithNoTests",
"test:unit": "npm run test:base -- --maxWorkers=4 --coverage",
As you can see, the final script run is test:base
, which has many flags, including the --config
, which points to the jest.config file--which is the one that instructs jest to use TsJest for typescript.
So, in the end I just created my test:debug
(or test:profile
, or whatever name you want to give it) adding the same script with the --inspect
(or --inspect-brk
, because it is easier to run the profiler when you break at the start):
"test:profiler": "cross-env NODE_ENV=test node --inspect-brk --expose-gc --no-compilation-cache ./node_modules/jest/bin/jest.js --logHeapUsage --config ./config/jest.config.js --colors --rootDir . --passWithNoTests",
As you can see, I just added the --inspect-brk
to my already functional test script.
If your test script calls jest directly (something simple like "test": "jest"
, change it to the verbose call ("test:profiler": "node ./node_modules/jest/bin/jest.js"
), or whatever you path to jest is inside "node_modules" (the path should not be different, but shit happens).
After this, I could open chrome devtools for node and inspect through the profiler (in my older version, the Performance tab).
© 2022 - 2024 — McMap. All rights reserved.
import v8Profiler from 'v8-profiler-next';
toimport * as v8Profiler from 'v8-profiler-next';
– Item