From 0cd9a6de557f44dcfe79a4f287ca04b05d674bdc Mon Sep 17 00:00:00 2001 From: Andrew Clark Date: Fri, 7 Aug 2020 16:32:59 -0400 Subject: [PATCH] Parallelize Jest in CI (#19552) Uses CircleCI's `parallelism` key to split our test jobs across multiple processes, like we do for the build job. --- .circleci/config.yml | 21 ++++++++++++++++++- .../__tests__/ReactClassEquivalence-test.js | 4 ++++ scripts/jest/config.base.js | 2 ++ scripts/jest/jestSequencer.js | 19 +++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 scripts/jest/jestSequencer.js diff --git a/.circleci/config.yml b/.circleci/config.yml index 5804192ca451..9039180938a4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,6 +19,8 @@ aliases: name: Install Packages command: yarn --frozen-lockfile + - &TEST_PARALLELISM 20 + - &attach_workspace at: build @@ -92,6 +94,7 @@ jobs: RELEASE_CHANNEL_stable_yarn_test: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout @@ -102,6 +105,7 @@ jobs: yarn_test: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -111,6 +115,7 @@ jobs: RELEASE_CHANNEL_stable_yarn_test_www: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -120,6 +125,7 @@ jobs: RELEASE_CHANNEL_stable_yarn_test_www_variant: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -129,6 +135,7 @@ jobs: RELEASE_CHANNEL_stable_yarn_test_prod_www: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -138,6 +145,7 @@ jobs: RELEASE_CHANNEL_stable_yarn_test_prod_www_variant: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -147,6 +155,7 @@ jobs: yarn_test_www: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -156,6 +165,7 @@ jobs: yarn_test_www_variant: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -165,6 +175,7 @@ jobs: yarn_test_prod_www: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -174,6 +185,7 @@ jobs: yarn_test_prod_www_variant: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -183,6 +195,7 @@ jobs: RELEASE_CHANNEL_stable_yarn_test_persistent: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout @@ -193,6 +206,7 @@ jobs: RELEASE_CHANNEL_stable_yarn_test_prod: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout @@ -203,6 +217,7 @@ jobs: yarn_test_prod: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -212,7 +227,7 @@ jobs: RELEASE_CHANNEL_stable_yarn_build: docker: *docker environment: *environment - parallelism: 20 + parallelism: *TEST_PARALLELISM steps: - checkout - *restore_yarn_cache @@ -344,6 +359,7 @@ jobs: RELEASE_CHANNEL_stable_yarn_test_build: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - attach_workspace: *attach_workspace @@ -354,6 +370,7 @@ jobs: yarn_test_build: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - attach_workspace: *attach_workspace @@ -404,6 +421,7 @@ jobs: RELEASE_CHANNEL_stable_yarn_test_build_prod: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - attach_workspace: *attach_workspace @@ -414,6 +432,7 @@ jobs: yarn_test_build_prod: docker: *docker environment: *environment + parallelism: *TEST_PARALLELISM steps: - checkout - attach_workspace: *attach_workspace diff --git a/packages/react/src/__tests__/ReactClassEquivalence-test.js b/packages/react/src/__tests__/ReactClassEquivalence-test.js index d4815792add8..a08b67720ac6 100644 --- a/packages/react/src/__tests__/ReactClassEquivalence-test.js +++ b/packages/react/src/__tests__/ReactClassEquivalence-test.js @@ -38,6 +38,10 @@ function runJest(testFile) { cwd, env: Object.assign({}, process.env, { REACT_CLASS_EQUIVALENCE_TEST: 'true', + // Remove these so that the test file is not filtered out by the mechanism + // we use to parallelize tests in CI + CIRCLE_NODE_TOTAL: '', + CIRCLE_NODE_INDEX: '', }), }); diff --git a/scripts/jest/config.base.js b/scripts/jest/config.base.js index 3da2fb6b4148..0e9508221a65 100644 --- a/scripts/jest/config.base.js +++ b/scripts/jest/config.base.js @@ -22,6 +22,8 @@ module.exports = { timers: 'fake', snapshotSerializers: [require.resolve('jest-snapshot-serializer-raw')], + testSequencer: require.resolve('./jestSequencer'), + // TODO: Upgrade to Jest 26 which uses jsdom 16 by default. testEnvironment: require.resolve('jest-environment-jsdom-sixteen'), }; diff --git a/scripts/jest/jestSequencer.js b/scripts/jest/jestSequencer.js new file mode 100644 index 000000000000..b21cbbfc0ccb --- /dev/null +++ b/scripts/jest/jestSequencer.js @@ -0,0 +1,19 @@ +'use strict'; + +const Sequencer = require('@jest/test-sequencer').default; + +class CustomSequencer extends Sequencer { + sort(tests) { + if (process.env.CIRCLE_NODE_TOTAL) { + // In CI, parallelize tests across multiple tasks. + const nodeTotal = parseInt(process.env.CIRCLE_NODE_TOTAL, 10); + const nodeIndex = parseInt(process.env.CIRCLE_NODE_INDEX, 10); + tests = tests + .sort((a, b) => (a.path < b.path ? -1 : 1)) + .filter((_, i) => i % nodeTotal === nodeIndex); + } + return tests; + } +} + +module.exports = CustomSequencer;