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

feat: add long test time threshold option #9366

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

### Features

- `[jest-config, jest-reporter, jest-runner]` Add `slowTestThreshold` configuration option ([#9366](https://github.com/facebook/jest/pull/9366))
- `[jest-worker]` Added support for workers to send custom messages to parent in jest-worker ([#10293](https://github.com/facebook/jest/pull/10293))
- `[pretty-format]` Added support for serializing custom elements (web components) ([#10217](https://github.com/facebook/jest/pull/10237))

Expand Down
1 change: 1 addition & 0 deletions TestUtils.ts
Expand Up @@ -102,6 +102,7 @@ const DEFAULT_PROJECT_CONFIG: Config.ProjectConfig = {
setupFilesAfterEnv: [],
skipFilter: false,
skipNodeResolution: false,
slowTestThreshold: 5,
snapshotResolver: undefined,
snapshotSerializers: [],
testEnvironment: 'node',
Expand Down
6 changes: 6 additions & 0 deletions docs/Configuration.md
Expand Up @@ -800,6 +800,12 @@ Example `jest.setup.js` file
jest.setTimeout(10000); // in milliseconds
```

### `slowTestThreshold` [number]

Default: `5`

The number of seconds after which a test is considered as slow and reported as such in the results.

### `snapshotResolver` [string]

Default: `undefined`
Expand Down
1 change: 1 addition & 0 deletions e2e/__tests__/__snapshots__/showConfig.test.ts.snap
Expand Up @@ -48,6 +48,7 @@ exports[`--showConfig outputs config info and exits 1`] = `
"setupFiles": [],
"setupFilesAfterEnv": [],
"skipFilter": false,
"slowTestThreshold": 5,
"snapshotSerializers": [],
"testEnvironment": "<<REPLACED_JEST_PACKAGES_DIR>>/jest-environment-jsdom/build/index.js",
"testEnvironmentOptions": {},
Expand Down
Expand Up @@ -176,6 +176,9 @@ module.exports = {
// A list of paths to modules that run some code to configure or set up the testing framework before each test
// setupFilesAfterEnv: [],

// A number of seconds after which a test is considered as slow and reported as such in the results.
Draco-Umbratilis marked this conversation as resolved.
Show resolved Hide resolved
// slowTestThreshold: 5,

// A list of paths to snapshot serializer modules Jest should use for snapshot testing
// snapshotSerializers: [],

Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/Defaults.ts
Expand Up @@ -50,6 +50,7 @@ const defaultOptions: Config.DefaultOptions = {
setupFiles: [],
setupFilesAfterEnv: [],
skipFilter: false,
slowTestThreshold: 5,
snapshotSerializers: [],
testEnvironment: 'jest-environment-jsdom',
testEnvironmentOptions: {},
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-config/src/Descriptions.ts
Expand Up @@ -67,6 +67,8 @@ const descriptions: {[key in keyof Config.InitialOptions]: string} = {
'The paths to modules that run some code to configure or set up the testing environment before each test',
setupFilesAfterEnv:
'A list of paths to modules that run some code to configure or set up the testing framework before each test',
slowTestThreshold:
'A number of seconds after which a test is considered as slow and reported as such in the results.',
Draco-Umbratilis marked this conversation as resolved.
Show resolved Hide resolved
snapshotSerializers:
'A list of paths to snapshot serializer modules Jest should use for snapshot testing',
testEnvironment: 'The test environment that will be used for testing',
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/ValidConfig.ts
Expand Up @@ -97,6 +97,7 @@ const initialOptions: Config.InitialOptions = {
silent: true,
skipFilter: false,
skipNodeResolution: false,
slowTestThreshold: 5,
snapshotResolver: '<rootDir>/snapshotResolver.js',
snapshotSerializers: ['my-serializer-module'],
testEnvironment: 'jest-environment-jsdom',
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/index.ts
Expand Up @@ -205,6 +205,7 @@ const groupOptions = (
setupFilesAfterEnv: options.setupFilesAfterEnv,
skipFilter: options.skipFilter,
skipNodeResolution: options.skipNodeResolution,
slowTestThreshold: options.slowTestThreshold,
snapshotResolver: options.snapshotResolver,
snapshotSerializers: options.snapshotSerializers,
testEnvironment: options.testEnvironment,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/normalize.ts
Expand Up @@ -907,6 +907,7 @@ export default function normalize(
case 'silent':
case 'skipFilter':
case 'skipNodeResolution':
case 'slowTestThreshold':
case 'testEnvironment':
case 'testEnvironmentOptions':
case 'testFailureExitCode':
Expand Down
Expand Up @@ -38,6 +38,7 @@ exports[`prints the config object 1`] = `
"setupFilesAfterEnv": [],
"skipFilter": false,
"skipNodeResolution": false,
"slowTestThreshold": 5,
"snapshotSerializers": [],
"testEnvironment": "node",
"testEnvironmentOptions": {},
Expand Down
31 changes: 31 additions & 0 deletions packages/jest-reporters/src/__tests__/get_result_header.test.js
Expand Up @@ -11,9 +11,28 @@ const terminalLink = require('terminal-link');

jest.mock('terminal-link', () => jest.fn(() => 'wannabehyperlink'));

const endTime = 1577717671160;
const testTime = 5500;

const testResult = {
testFilePath: '/foo',
};
const testResultSlow = {
perfStats: {
end: endTime,
slow: true,
start: endTime - testTime,
},
testFilePath: '/foo',
};
const testResultFast = {
perfStats: {
end: endTime,
slow: false,
start: endTime - testTime,
},
testFilePath: '/foo',
};

const globalConfig = makeGlobalConfig();

Expand All @@ -36,3 +55,15 @@ test('should render the terminal link', () => {

expect(result).toContain('wannabehyperlink');
});

test('should display test time for slow test', () => {
const result = getResultHeader(testResultSlow, globalConfig);

expect(result).toContain(`${testTime / 1000} s`);
});

test('should not display test time for fast test ', () => {
const result = getResultHeader(testResultFast, globalConfig);

expect(result).not.toContain(`${testTime / 1000} s`);
});
9 changes: 4 additions & 5 deletions packages/jest-reporters/src/get_result_header.ts
Expand Up @@ -42,12 +42,11 @@ export default (
const status =
result.numFailingTests > 0 || result.testExecError ? FAIL : PASS;

const runTime = result.perfStats
? (result.perfStats.end - result.perfStats.start) / 1000
: null;

const testDetail = [];
if (runTime !== null && runTime > 5) {

if (result.perfStats?.slow) {
const runTime = (result.perfStats.end - result.perfStats.start) / 1000;

testDetail.push(LONG_TEST_COLOR(formatTime(runTime, 0)));
}

Expand Down
7 changes: 6 additions & 1 deletion packages/jest-runner/src/runTest.ts
Expand Up @@ -266,7 +266,12 @@ async function runTestInternal(
result.numPendingTests +
result.numTodoTests;

result.perfStats = {end: Date.now(), start};
const end = Date.now();
result.perfStats = {
Copy link
Member

Choose a reason for hiding this comment

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

should we stick runtime or something on here as well so we don't have to do end-start in multiple places?

Copy link
Member

Choose a reason for hiding this comment

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

@Draco-Umbratilis just this comment and we should be good to go

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I found one occurrence in jest-test-sequencer and made the change also there. Reflected in tests and changelog, I hope it is ok.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I like it!

end,
slow: (end - start) / 1000 > config.slowTestThreshold,
start,
};
result.testFilePath = path;
result.console = testConsole.getBuffer();
result.skipped = testCount === result.numPendingTests;
Expand Down
Expand Up @@ -19,7 +19,7 @@ describe('formatTestResults', () => {
testResults: [
{
numFailingTests: 0,
perfStats: {end: 2, start: 1},
perfStats: {end: 2, slow: false, start: 1},
// @ts-expect-error
testResults: [assertion],
},
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-test-result/src/helpers.ts
Expand Up @@ -58,6 +58,7 @@ export const buildFailureTestResult = (
openHandles: [],
perfStats: {
end: 0,
slow: false,
start: 0,
},
skipped: false,
Expand Down Expand Up @@ -155,6 +156,7 @@ export const createEmptyTestResult = (): TestResult => ({
openHandles: [],
perfStats: {
end: 0,
slow: false,
start: 0,
},
skipped: false,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-test-result/src/types.ts
Expand Up @@ -92,6 +92,7 @@ export type TestResult = {
openHandles: Array<Error>;
perfStats: {
end: Milliseconds;
slow: boolean;
start: Milliseconds;
};
skipped: boolean;
Expand Down
Expand Up @@ -41,6 +41,7 @@ Object {
"setupFilesAfterEnv": Array [],
"skipFilter": false,
"skipNodeResolution": false,
"slowTestThreshold": 5,
"snapshotResolver": undefined,
"snapshotSerializers": Array [],
"testEnvironment": "node",
Expand Down Expand Up @@ -229,7 +230,7 @@ exports[`ScriptTransformer uses multiple preprocessors 1`] = `
const TRANSFORMED = {
filename: '/fruits/banana.js',
script: 'module.exports = "banana";',
config: '{"automock":false,"cache":true,"cacheDirectory":"/cache/","clearMocks":false,"coveragePathIgnorePatterns":[],"cwd":"/test_root_dir/","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"forceCoverageMatch":[],"globals":{},"haste":{},"moduleDirectories":[],"moduleFileExtensions":["js"],"moduleLoader":"/test_module_loader_path","moduleNameMapper":[],"modulePathIgnorePatterns":[],"modulePaths":[],"name":"test","prettierPath":"prettier","resetMocks":false,"resetModules":false,"restoreMocks":false,"rootDir":"/","roots":[],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"skipNodeResolution":false,"snapshotSerializers":[],"testEnvironment":"node","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":[],"testPathIgnorePatterns":[],"testRegex":["\\\\.test\\\\.js$"],"testRunner":"jest-jasmine2","testURL":"http://localhost","timers":"real","transform":[["^.+\\\\.js$","test_preprocessor"],["^.+\\\\.css$","css-preprocessor"]],"transformIgnorePatterns":["/node_modules/"],"watchPathIgnorePatterns":[]}',
config: '{"automock":false,"cache":true,"cacheDirectory":"/cache/","clearMocks":false,"coveragePathIgnorePatterns":[],"cwd":"/test_root_dir/","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"forceCoverageMatch":[],"globals":{},"haste":{},"moduleDirectories":[],"moduleFileExtensions":["js"],"moduleLoader":"/test_module_loader_path","moduleNameMapper":[],"modulePathIgnorePatterns":[],"modulePaths":[],"name":"test","prettierPath":"prettier","resetMocks":false,"resetModules":false,"restoreMocks":false,"rootDir":"/","roots":[],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"skipNodeResolution":false,"slowTestThreshold":5,"snapshotSerializers":[],"testEnvironment":"node","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":[],"testPathIgnorePatterns":[],"testRegex":["\\\\.test\\\\.js$"],"testRunner":"jest-jasmine2","testURL":"http://localhost","timers":"real","transform":[["^.+\\\\.js$","test_preprocessor"],["^.+\\\\.css$","css-preprocessor"]],"transformIgnorePatterns":["/node_modules/"],"watchPathIgnorePatterns":[]}',
};
`;

Expand All @@ -246,7 +247,7 @@ exports[`ScriptTransformer uses the supplied preprocessor 1`] = `
const TRANSFORMED = {
filename: '/fruits/banana.js',
script: 'module.exports = "banana";',
config: '{"automock":false,"cache":true,"cacheDirectory":"/cache/","clearMocks":false,"coveragePathIgnorePatterns":[],"cwd":"/test_root_dir/","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"forceCoverageMatch":[],"globals":{},"haste":{},"moduleDirectories":[],"moduleFileExtensions":["js"],"moduleLoader":"/test_module_loader_path","moduleNameMapper":[],"modulePathIgnorePatterns":[],"modulePaths":[],"name":"test","prettierPath":"prettier","resetMocks":false,"resetModules":false,"restoreMocks":false,"rootDir":"/","roots":[],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"skipNodeResolution":false,"snapshotSerializers":[],"testEnvironment":"node","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":[],"testPathIgnorePatterns":[],"testRegex":["\\\\.test\\\\.js$"],"testRunner":"jest-jasmine2","testURL":"http://localhost","timers":"real","transform":[["^.+\\\\.js$","test_preprocessor"]],"transformIgnorePatterns":["/node_modules/"],"watchPathIgnorePatterns":[]}',
config: '{"automock":false,"cache":true,"cacheDirectory":"/cache/","clearMocks":false,"coveragePathIgnorePatterns":[],"cwd":"/test_root_dir/","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"extraGlobals":[],"forceCoverageMatch":[],"globals":{},"haste":{},"moduleDirectories":[],"moduleFileExtensions":["js"],"moduleLoader":"/test_module_loader_path","moduleNameMapper":[],"modulePathIgnorePatterns":[],"modulePaths":[],"name":"test","prettierPath":"prettier","resetMocks":false,"resetModules":false,"restoreMocks":false,"rootDir":"/","roots":[],"runner":"jest-runner","setupFiles":[],"setupFilesAfterEnv":[],"skipFilter":false,"skipNodeResolution":false,"slowTestThreshold":5,"snapshotSerializers":[],"testEnvironment":"node","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":[],"testPathIgnorePatterns":[],"testRegex":["\\\\.test\\\\.js$"],"testRunner":"jest-jasmine2","testURL":"http://localhost","timers":"real","transform":[["^.+\\\\.js$","test_preprocessor"]],"transformIgnorePatterns":["/node_modules/"],"watchPathIgnorePatterns":[]}',
};
`;

Expand Down
3 changes: 3 additions & 0 deletions packages/jest-types/src/Config.ts
Expand Up @@ -65,6 +65,7 @@ export type DefaultOptions = {
setupFiles: Array<Path>;
setupFilesAfterEnv: Array<Path>;
skipFilter: boolean;
slowTestThreshold: number;
snapshotSerializers: Array<Path>;
testEnvironment: string;
testEnvironmentOptions: Record<string, any>;
Expand Down Expand Up @@ -171,6 +172,7 @@ export type InitialOptions = Partial<{
silent: boolean;
skipFilter: boolean;
skipNodeResolution: boolean;
slowTestThreshold: number;
snapshotResolver: Path;
snapshotSerializers: Array<Path>;
errorOnDeprecated: boolean;
Expand Down Expand Up @@ -332,6 +334,7 @@ export type ProjectConfig = {
setupFilesAfterEnv: Array<Path>;
skipFilter: boolean;
skipNodeResolution?: boolean;
slowTestThreshold: number;
snapshotResolver?: Path;
snapshotSerializers: Array<Path>;
testEnvironment: string;
Expand Down