Skip to content

Commit 4fedfbd

Browse files
authored
feat(jest-core): Add perfStats to surface test setup overhead (#14622)
1 parent d89bdaf commit 4fedfbd

File tree

11 files changed

+66
-4
lines changed

11 files changed

+66
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- `[jest-config]` [**BREAKING**] Add `mts` and `cts` to default `moduleFileExtensions` config ([#14369](https://github.com/facebook/jest/pull/14369))
66
- `[jest-config]` [**BREAKING**] Update `testMatch` and `testRegex` default option for supporting `mjs`, `cjs`, `mts`, and `cts` ([#14584](https://github.com/jestjs/jest/pull/14584))
77
- `[@jest/core]` [**BREAKING**] Group together open handles with the same stack trace ([#13417](https://github.com/jestjs/jest/pull/13417), & [#14543](https://github.com/jestjs/jest/pull/14543))
8+
- `[@jest/core]` Add `perfStats` to surface test setup overhead ([#14622](https://github.com/jestjs/jest/pull/14622))
89
- `[@jest/core, @jest/test-sequencer]` [**BREAKING**] Exposes `globalConfig` & `contexts` to `TestSequencer` ([#14535](https://github.com/jestjs/jest/pull/14535), & [#14543](https://github.com/jestjs/jest/pull/14543))
910
- `[jest-environment-jsdom]` [**BREAKING**] Upgrade JSDOM to v22 ([#13825](https://github.com/jestjs/jest/pull/13825))
1011
- `[@jest/fake-timers]` [**BREAKING**] Upgrade `@sinonjs/fake-timers` to v11 ([#14544](https://github.com/jestjs/jest/pull/14544))

docs/Configuration.md

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2080,13 +2080,22 @@ This option allows the use of a custom results processor. This processor must be
20802080
"column": number,
20812081
"line": number
20822082
},
2083-
"duration": number | null
2083+
"duration": number | null,
2084+
"startAt": epoch | null
20842085
},
20852086
...
20862087
],
20872088
"perfStats": {
2088-
"start": epoch,
2089-
"end": epoch
2089+
"end": epoch,
2090+
"loadTestEnvironmentEnd": epoch,
2091+
"loadTestEnvironmentStart": epoch,
2092+
"runtime": number,
2093+
"setupAfterEnvEnd": epoch,
2094+
"setupAfterEnvStart": epoch,
2095+
"setupFilesEnd": epoch,
2096+
"setupFilesStart": epoch,
2097+
"slow": boolean,
2098+
"start": epoch
20902099
},
20912100
"testFilePath": absolute path to test file,
20922101
"coverage": {}

packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapter.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ const jestAdapter = async (
7474
}
7575
});
7676

77+
const setupAfterEnvStart = Date.now();
7778
for (const path of config.setupFilesAfterEnv) {
7879
const esm = runtime.unstable_shouldLoadAsEsm(path);
7980

@@ -83,6 +84,7 @@ const jestAdapter = async (
8384
runtime.requireModule(path);
8485
}
8586
}
87+
const setupAfterEnvEnd = Date.now();
8688
const esm = runtime.unstable_shouldLoadAsEsm(testPath);
8789

8890
if (esm) {
@@ -91,9 +93,15 @@ const jestAdapter = async (
9193
runtime.requireModule(testPath);
9294
}
9395

96+
const setupAfterEnvPerfStats = {
97+
setupAfterEnvEnd,
98+
setupAfterEnvStart,
99+
};
100+
94101
const results = await runAndTransformResultsToJestFormat({
95102
config,
96103
globalConfig,
104+
setupAfterEnvPerfStats,
97105
testPath,
98106
});
99107

packages/jest-circus/src/legacy-code-todo-rewrite/jestAdapterInit.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,13 @@ export const initialize = async ({
141141
export const runAndTransformResultsToJestFormat = async ({
142142
config,
143143
globalConfig,
144+
setupAfterEnvPerfStats,
144145
testPath,
145146
}: {
146147
config: Config.ProjectConfig;
147148
globalConfig: Config.GlobalConfig;
148149
testPath: string;
150+
setupAfterEnvPerfStats: Config.SetupAfterEnvPerfStats;
149151
}): Promise<TestResult> => {
150152
const runResult: Circus.RunResult = await run();
151153

@@ -189,6 +191,7 @@ export const runAndTransformResultsToJestFormat = async ({
189191
location: testResult.location,
190192
numPassingAsserts: testResult.numPassingAsserts,
191193
retryReasons: testResult.retryReasons,
194+
startAt: testResult.startedAt,
192195
status,
193196
title: testResult.testPath[testResult.testPath.length - 1],
194197
};
@@ -215,15 +218,21 @@ export const runAndTransformResultsToJestFormat = async ({
215218

216219
await dispatch({name: 'teardown'});
217220

221+
const emptyTestResult = createEmptyTestResult();
222+
218223
return {
219-
...createEmptyTestResult(),
224+
...emptyTestResult,
220225
console: undefined,
221226
displayName: config.displayName,
222227
failureMessage,
223228
numFailingTests,
224229
numPassingTests,
225230
numPendingTests,
226231
numTodoTests,
232+
perfStats: {
233+
...emptyTestResult.perfStats,
234+
...setupAfterEnvPerfStats,
235+
},
227236
testExecError,
228237
testFilePath: testPath,
229238
testResults: assertionResults,

packages/jest-circus/src/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ export const makeSingleTestResult = (
382382
location,
383383
numPassingAsserts: test.numPassingAsserts,
384384
retryReasons: test.retryReasons.map(_getError).map(getErrorStack),
385+
startedAt: test.startedAt,
385386
status,
386387
testPath: Array.from(testPath),
387388
};

packages/jest-runner/src/runTest.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ async function runTestInternal(
8787
const docblockPragmas = docblock.parse(docblock.extract(testSource));
8888
const customEnvironment = docblockPragmas['jest-environment'];
8989

90+
const loadTestEnvironmentStart = Date.now();
9091
let testEnvironment = projectConfig.testEnvironment;
9192

9293
if (customEnvironment) {
@@ -169,6 +170,7 @@ async function runTestInternal(
169170
testPath: path,
170171
},
171172
);
173+
const loadTestEnvironmentEnd = Date.now();
172174

173175
if (typeof environment.getVmContext !== 'function') {
174176
console.error(
@@ -213,6 +215,7 @@ async function runTestInternal(
213215

214216
const start = Date.now();
215217

218+
const setupFilesStart = Date.now();
216219
for (const path of projectConfig.setupFiles) {
217220
const esm = runtime.unstable_shouldLoadAsEsm(path);
218221

@@ -225,6 +228,7 @@ async function runTestInternal(
225228
}
226229
}
227230
}
231+
const setupFilesEnd = Date.now();
228232

229233
const sourcemapOptions: sourcemapSupport.Options = {
230234
environment: 'node',
@@ -329,8 +333,13 @@ async function runTestInternal(
329333
const end = Date.now();
330334
const testRuntime = end - start;
331335
result.perfStats = {
336+
...result.perfStats,
332337
end,
338+
loadTestEnvironmentEnd,
339+
loadTestEnvironmentStart,
333340
runtime: testRuntime,
341+
setupFilesEnd,
342+
setupFilesStart,
334343
slow: testRuntime / 1000 > projectConfig.slowTestThreshold,
335344
start,
336345
};

packages/jest-test-result/src/helpers.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,13 @@ export const buildFailureTestResult = (
5757
openHandles: [],
5858
perfStats: {
5959
end: 0,
60+
loadTestEnvironmentEnd: 0,
61+
loadTestEnvironmentStart: 0,
6062
runtime: 0,
63+
setupAfterEnvEnd: 0,
64+
setupAfterEnvStart: 0,
65+
setupFilesEnd: 0,
66+
setupFilesStart: 0,
6167
slow: false,
6268
start: 0,
6369
},
@@ -155,7 +161,13 @@ export const createEmptyTestResult = (): TestResult => ({
155161
openHandles: [],
156162
perfStats: {
157163
end: 0,
164+
loadTestEnvironmentEnd: 0,
165+
loadTestEnvironmentStart: 0,
158166
runtime: 0,
167+
setupAfterEnvEnd: 0,
168+
setupAfterEnvStart: 0,
169+
setupFilesEnd: 0,
170+
setupFilesStart: 0,
159171
slow: false,
160172
start: 0,
161173
},

packages/jest-test-result/src/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,13 @@ export type TestResult = {
106106
openHandles: Array<Error>;
107107
perfStats: {
108108
end: number;
109+
loadTestEnvironmentEnd: number;
110+
loadTestEnvironmentStart: number;
109111
runtime: number;
112+
setupAfterEnvEnd: number;
113+
setupAfterEnvStart: number;
114+
setupFilesEnd: number;
115+
setupFilesStart: number;
110116
slow: boolean;
111117
start: number;
112118
};

packages/jest-types/src/Circus.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ export type TestResult = {
209209
*/
210210
failing?: boolean;
211211
invocations: number;
212+
startedAt?: number | null;
212213
status: TestStatus;
213214
location?: {column: number; line: number} | null;
214215
numPassingAsserts: number;

packages/jest-types/src/Config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,11 @@ export type ProjectConfig = {
494494
workerIdleMemoryLimit?: number;
495495
};
496496

497+
export type SetupAfterEnvPerfStats = {
498+
setupAfterEnvStart: number;
499+
setupAfterEnvEnd: number;
500+
};
501+
497502
export type Argv = Arguments<
498503
Partial<{
499504
all: boolean;

packages/jest-types/src/TestResult.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type Callsite = {
2323
export type AssertionResult = {
2424
ancestorTitles: Array<string>;
2525
duration?: number | null;
26+
startAt?: number | null;
2627
/**
2728
* Whether [`test.failing()`](https://jestjs.io/docs/api#testfailingname-fn-timeout)
2829
* was used.

0 commit comments

Comments
 (0)