Skip to content

Commit 178d93d

Browse files
authored
feat(testing): add disableJestRuntime option to @nx/jest/plugin to speed up target inference (#28522)
This PR adds a new `disableJestRuntime` option to `@nx/jest/plugin`. By setting this to `true`, the inference plugin will not use `jest-config` and `jest-runtime` to retrieve `outputs`, nor matching spec files when `ciTargetName` is used. Instead, we'll use our own config loader and glob/matcher to get both values for the inferred targets. This speeds up computation quite a bit. With a large monorepo (800 projects, 75K files), the computation goes from 2m 41s to 35s, or ~78% time reduction. NOTE: This has no effect on existing projects and needs to be opted into. <!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
1 parent 4014662 commit 178d93d

File tree

5 files changed

+662
-103
lines changed

5 files changed

+662
-103
lines changed

docs/generated/packages/jest/documents/overview.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,16 @@ within the same workspace. In this case, you can configure the `@nx/jest/plugin`
6060
"include": ["e2e/**/*"],
6161
"options": {
6262
"targetName": "e2e-local",
63-
"ciTargetName": "e2e-ci"
63+
"ciTargetName": "e2e-ci",
64+
"disableJestRuntime": false
6465
}
6566
}
6667
]
6768
}
6869
```
6970

71+
If you experience slowness from `@nx/jest/plugin`, then set `disableJestRuntime` to `true` to skip creating the Jest runtime. By disabling the Jest runtime, Nx will use its own utilities to find `inputs`, `outputs`, and test files for [Atomized targets](/ci/features/split-e2e-tasks). This can reduce computation time by as much as 80%.
72+
7073
### Splitting E2E Tests
7174

7275
If Jest is used to run E2E tests, you can enable [splitting the tasks](/ci/features/split-e2e-tasks) by file to get

docs/shared/packages/jest/jest-plugin.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,16 @@ within the same workspace. In this case, you can configure the `@nx/jest/plugin`
6060
"include": ["e2e/**/*"],
6161
"options": {
6262
"targetName": "e2e-local",
63-
"ciTargetName": "e2e-ci"
63+
"ciTargetName": "e2e-ci",
64+
"disableJestRuntime": false
6465
}
6566
}
6667
]
6768
}
6869
```
6970

71+
If you experience slowness from `@nx/jest/plugin`, then set `disableJestRuntime` to `true` to skip creating the Jest runtime. By disabling the Jest runtime, Nx will use its own utilities to find `inputs`, `outputs`, and test files for [Atomized targets](/ci/features/split-e2e-tasks). This can reduce computation time by as much as 80%.
72+
7073
### Splitting E2E Tests
7174

7275
If Jest is used to run E2E tests, you can enable [splitting the tasks](/ci/features/split-e2e-tasks) by file to get

packages/jest/.eslintrc.json

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"prettier",
4040
"jest",
4141
"@jest/types",
42+
"jest-runtime",
4243
// require.resolve is used for these packages
4344
"identity-obj-proxy"
4445
]

packages/jest/src/plugins/plugin.spec.ts

+328
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,334 @@ describe('@nx/jest/plugin', () => {
347347
expect(results).toMatchSnapshot();
348348
}
349349
);
350+
351+
describe('disableJestRuntime', () => {
352+
it('should create test and test-ci targets based on jest.config.ts', async () => {
353+
mockJestConfig(
354+
{
355+
coverageDirectory: '../coverage',
356+
testMatch: ['**/*.spec.ts'],
357+
testPathIgnorePatterns: ['ignore.spec.ts'],
358+
},
359+
context
360+
);
361+
const results = await createNodesFunction(
362+
['proj/jest.config.js'],
363+
{
364+
targetName: 'test',
365+
ciTargetName: 'test-ci',
366+
disableJestRuntime: true,
367+
},
368+
context
369+
);
370+
371+
expect(results).toMatchInlineSnapshot(`
372+
[
373+
[
374+
"proj/jest.config.js",
375+
{
376+
"projects": {
377+
"proj": {
378+
"metadata": {
379+
"targetGroups": {
380+
"E2E (CI)": [
381+
"test-ci",
382+
"test-ci--src/unit.spec.ts",
383+
],
384+
},
385+
},
386+
"root": "proj",
387+
"targets": {
388+
"test": {
389+
"cache": true,
390+
"command": "jest",
391+
"inputs": [
392+
"default",
393+
"^production",
394+
{
395+
"externalDependencies": [
396+
"jest",
397+
],
398+
},
399+
],
400+
"metadata": {
401+
"description": "Run Jest Tests",
402+
"help": {
403+
"command": "npx jest --help",
404+
"example": {
405+
"options": {
406+
"coverage": true,
407+
},
408+
},
409+
},
410+
"technologies": [
411+
"jest",
412+
],
413+
},
414+
"options": {
415+
"cwd": "proj",
416+
},
417+
"outputs": [
418+
"{workspaceRoot}/coverage",
419+
],
420+
},
421+
"test-ci": {
422+
"cache": true,
423+
"dependsOn": [
424+
"test-ci--src/unit.spec.ts",
425+
],
426+
"executor": "nx:noop",
427+
"inputs": [
428+
"default",
429+
"^production",
430+
{
431+
"externalDependencies": [
432+
"jest",
433+
],
434+
},
435+
],
436+
"metadata": {
437+
"description": "Run Jest Tests in CI",
438+
"help": {
439+
"command": "npx jest --help",
440+
"example": {
441+
"options": {
442+
"coverage": true,
443+
},
444+
},
445+
},
446+
"nonAtomizedTarget": "test",
447+
"technologies": [
448+
"jest",
449+
],
450+
},
451+
"outputs": [
452+
"{workspaceRoot}/coverage",
453+
],
454+
},
455+
"test-ci--src/unit.spec.ts": {
456+
"cache": true,
457+
"command": "jest src/unit.spec.ts",
458+
"inputs": [
459+
"default",
460+
"^production",
461+
{
462+
"externalDependencies": [
463+
"jest",
464+
],
465+
},
466+
],
467+
"metadata": {
468+
"description": "Run Jest Tests in src/unit.spec.ts",
469+
"help": {
470+
"command": "npx jest --help",
471+
"example": {
472+
"options": {
473+
"coverage": true,
474+
},
475+
},
476+
},
477+
"technologies": [
478+
"jest",
479+
],
480+
},
481+
"options": {
482+
"cwd": "proj",
483+
},
484+
"outputs": [
485+
"{workspaceRoot}/coverage",
486+
],
487+
},
488+
},
489+
},
490+
},
491+
},
492+
],
493+
]
494+
`);
495+
});
496+
497+
it.each`
498+
preset | expectedInput
499+
${'<rootDir>/jest.preset.js'} | ${'{projectRoot}/jest.preset.js'}
500+
${'../jest.preset.js'} | ${'{workspaceRoot}/jest.preset.js'}
501+
`('should correct input from preset', async ({ preset, expectedInput }) => {
502+
mockJestConfig(
503+
{
504+
preset,
505+
coverageDirectory: '../coverage',
506+
testMatch: ['**/*.spec.ts'],
507+
testPathIgnorePatterns: ['ignore.spec.ts'],
508+
},
509+
context
510+
);
511+
const results = await createNodesFunction(
512+
['proj/jest.config.js'],
513+
{
514+
targetName: 'test',
515+
ciTargetName: 'test-ci',
516+
disableJestRuntime: true,
517+
},
518+
context
519+
);
520+
521+
expect(results[0][1].projects['proj'].targets['test'].inputs).toContain(
522+
expectedInput
523+
);
524+
});
525+
526+
it.each`
527+
testRegex
528+
${'\\.*\\.spec\\.ts'}
529+
${['\\.*\\.spec\\.ts']}
530+
`(
531+
'should create test-ci targets from testRegex config option',
532+
async ({ testRegex }) => {
533+
mockJestConfig(
534+
{
535+
coverageDirectory: '../coverage',
536+
testRegex,
537+
testPathIgnorePatterns: ['ignore.spec.ts'],
538+
},
539+
context
540+
);
541+
const results = await createNodesFunction(
542+
['proj/jest.config.js'],
543+
{
544+
targetName: 'test',
545+
ciTargetName: 'test-ci',
546+
disableJestRuntime: true,
547+
},
548+
context
549+
);
550+
551+
expect(results).toMatchInlineSnapshot(`
552+
[
553+
[
554+
"proj/jest.config.js",
555+
{
556+
"projects": {
557+
"proj": {
558+
"metadata": {
559+
"targetGroups": {
560+
"E2E (CI)": [
561+
"test-ci",
562+
"test-ci--src/unit.spec.ts",
563+
],
564+
},
565+
},
566+
"root": "proj",
567+
"targets": {
568+
"test": {
569+
"cache": true,
570+
"command": "jest",
571+
"inputs": [
572+
"default",
573+
"^production",
574+
{
575+
"externalDependencies": [
576+
"jest",
577+
],
578+
},
579+
],
580+
"metadata": {
581+
"description": "Run Jest Tests",
582+
"help": {
583+
"command": "npx jest --help",
584+
"example": {
585+
"options": {
586+
"coverage": true,
587+
},
588+
},
589+
},
590+
"technologies": [
591+
"jest",
592+
],
593+
},
594+
"options": {
595+
"cwd": "proj",
596+
},
597+
"outputs": [
598+
"{workspaceRoot}/coverage",
599+
],
600+
},
601+
"test-ci": {
602+
"cache": true,
603+
"dependsOn": [
604+
"test-ci--src/unit.spec.ts",
605+
],
606+
"executor": "nx:noop",
607+
"inputs": [
608+
"default",
609+
"^production",
610+
{
611+
"externalDependencies": [
612+
"jest",
613+
],
614+
},
615+
],
616+
"metadata": {
617+
"description": "Run Jest Tests in CI",
618+
"help": {
619+
"command": "npx jest --help",
620+
"example": {
621+
"options": {
622+
"coverage": true,
623+
},
624+
},
625+
},
626+
"nonAtomizedTarget": "test",
627+
"technologies": [
628+
"jest",
629+
],
630+
},
631+
"outputs": [
632+
"{workspaceRoot}/coverage",
633+
],
634+
},
635+
"test-ci--src/unit.spec.ts": {
636+
"cache": true,
637+
"command": "jest src/unit.spec.ts",
638+
"inputs": [
639+
"default",
640+
"^production",
641+
{
642+
"externalDependencies": [
643+
"jest",
644+
],
645+
},
646+
],
647+
"metadata": {
648+
"description": "Run Jest Tests in src/unit.spec.ts",
649+
"help": {
650+
"command": "npx jest --help",
651+
"example": {
652+
"options": {
653+
"coverage": true,
654+
},
655+
},
656+
},
657+
"technologies": [
658+
"jest",
659+
],
660+
},
661+
"options": {
662+
"cwd": "proj",
663+
},
664+
"outputs": [
665+
"{workspaceRoot}/coverage",
666+
],
667+
},
668+
},
669+
},
670+
},
671+
},
672+
],
673+
]
674+
`);
675+
}
676+
);
677+
});
350678
});
351679

352680
function mockJestConfig(config: any, context: CreateNodesContext) {

0 commit comments

Comments
 (0)