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

Allow the cli to use a string for --maxWorkers #8565

Merged
merged 6 commits into from
Jun 24, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Maxworkers is now also working in the jest.config.js
  • Loading branch information
Philipp Beau committed Jun 23, 2019
commit 52c8608641b40e0330955aabbb12b293b181be40
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- `[jest-cli]` Improve chai support (with detailed output, to match jest exceptions) ([#8454](https://github.com/facebook/jest/pull/8454))
- `[*]` Manage the global timeout with `--testTimeout` command line argument. ([#8456](https://github.com/facebook/jest/pull/8456))
- `[pretty-format]` Render custom displayName of memoized components
- `[jest-validate]` Allow `maxWorkers` as part of the `jest.config.js` ([#8565](https://github.com/facebook/jest/pull/8565))

### Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ module.exports = {
// A set of global variables that need to be available in all test environments
// globals: {},

// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
// maxWorkers: \\"50%\\",

// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
// \\"node_modules\\"
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/Defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const defaultOptions: Config.DefaultOptions = {
providesModuleNodeModules: [],
throwOnModuleCollision: false,
},
maxWorkers: '50%',
maxConcurrency: 5,
moduleDirectories: ['node_modules'],
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-config/src/Descriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const descriptions: {[key in keyof Config.InitialOptions]: string} = {
'A path to a module which exports an async function that is triggered once after all test suites',
globals:
'A set of global variables that need to be available in all test environments',
maxWorkers:
'The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.',
moduleDirectories:
"An array of directory names to be searched recursively up from the requiring module's location",
moduleFileExtensions: 'An array of file extensions your modules use',
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/ValidConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const initialOptions: Config.InitialOptions = {
lastCommit: false,
logHeapUsage: true,
maxConcurrency: 5,
maxWorkers: '50%',
moduleDirectories: ['node_modules'],
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
moduleLoader: '<rootDir>',
Expand Down
37 changes: 21 additions & 16 deletions packages/jest-config/src/getMaxWorkers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,34 @@ import {Config} from '@jest/types';

export default function getMaxWorkers(
argv: Partial<Pick<Config.Argv, 'maxWorkers' | 'runInBand' | 'watch'>>,
defaultOptions?: Partial<Pick<Config.Argv, 'maxWorkers'>>,
): number {
if (argv.runInBand) {
return 1;
} else if (argv.maxWorkers) {
// TODO: How to type this properly? Should probably use `coerce` from `yargs`
const maxWorkers = argv.maxWorkers;
const parsed = parseInt(maxWorkers as string, 10);

if (
typeof maxWorkers === 'string' &&
maxWorkers.trim().endsWith('%') &&
parsed > 0 &&
parsed <= 100
) {
const cpus = os.cpus().length;
const workers = Math.floor((parsed / 100) * cpus);
return workers >= 1 ? workers : 1;
}

return parsed > 0 ? parsed : 1;
return parseWorkers(argv.maxWorkers);
} else if (defaultOptions && defaultOptions.maxWorkers) {
return parseWorkers(defaultOptions.maxWorkers);
} else {
// In watch mode, Jest should be unobtrusive and not use all available CPUs.
const cpus = os.cpus() ? os.cpus().length : 1;
return Math.max(argv.watch ? Math.floor(cpus / 2) : cpus - 1, 1);
}
}

const parseWorkers = (maxWorkers: string | number): number => {
const parsed = parseInt(maxWorkers.toString(), 10);

if (
typeof maxWorkers === 'string' &&
maxWorkers.trim().endsWith('%') &&
parsed > 0 &&
parsed <= 100
) {
const cpus = os.cpus().length;
const workers = Math.floor((parsed / 100) * cpus);
return workers >= 1 ? workers : 1;
}

return parsed > 0 ? parsed : 1;
};
2 changes: 1 addition & 1 deletion packages/jest-config/src/normalize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ export default function normalize(
(newOptions.maxConcurrency as unknown) as string,
10,
);
newOptions.maxWorkers = getMaxWorkers(argv);
newOptions.maxWorkers = getMaxWorkers(argv, options);

if (newOptions.testRegex!.length && options.testMatch) {
throw createConfigError(
Expand Down
2 changes: 2 additions & 0 deletions packages/jest-types/src/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export type DefaultOptions = {
globalSetup: string | null | undefined;
globalTeardown: string | null | undefined;
haste: HasteConfig;
maxWorkers: number | string;
maxConcurrency: number;
moduleDirectories: Array<string>;
moduleFileExtensions: Array<string>;
Expand Down Expand Up @@ -156,6 +157,7 @@ export type InitialOptions = {
listTests?: boolean;
mapCoverage?: boolean;
maxConcurrency?: number;
maxWorkers: number | string;
moduleDirectories?: Array<string>;
moduleFileExtensions?: Array<string>;
moduleLoader?: Path;
Expand Down
21 changes: 20 additions & 1 deletion packages/jest-validate/src/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
*/

import {ValidationOptions} from './types';

import defaultConfig from './defaultConfig';
import {ValidationError} from './utils';

let hasDeprecationWarnings = false;

Expand Down Expand Up @@ -46,6 +46,21 @@ const _validate = (
);

hasDeprecationWarnings = hasDeprecationWarnings || isDeprecatedKey;
} else if (allowsMultipleTypes(key)) {
const value = config[key];

if (
typeof options.condition === 'function' &&
typeof options.error === 'function'
) {
if (key === 'maxWorkers' && !isOfTypeStringOrNumber(value)) {
throw new ValidationError(
'Validation Error',
`${key} has to be of type string or number`,
`maxWorkers=50% or\nmaxWorkers=3`,
);
}
}
} else if (Object.hasOwnProperty.call(exampleConfig, key)) {
if (
typeof options.condition === 'function' &&
Expand Down Expand Up @@ -76,6 +91,10 @@ const _validate = (
return {hasDeprecationWarnings};
};

const allowsMultipleTypes = (key: string): boolean => key === 'maxWorkers';
const isOfTypeStringOrNumber = (value: any): boolean =>
typeof value === 'number' || typeof value === 'string';

const validate = (config: Record<string, any>, options: ValidationOptions) => {
hasDeprecationWarnings = false;

Expand Down