From ad2c61a7d5dcc266f075daa33604559a77ace994 Mon Sep 17 00:00:00 2001 From: Mario Nebl Date: Wed, 19 Oct 2022 22:03:09 +1100 Subject: [PATCH 1/4] fix: distribute rest files over shards #13027 --- .../src/__tests__/test_sequencer.test.ts | 19 ++++++++++++- packages/jest-test-sequencer/src/index.ts | 27 ++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.ts b/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.ts index 88b5bb4b9c17..87a6b8157f91 100644 --- a/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.ts +++ b/packages/jest-test-sequencer/src/__tests__/test_sequencer.test.ts @@ -368,6 +368,23 @@ test('returns expected 100/8 shards', async () => { ); expect(shards.map(shard => shard.length)).toEqual([ - 13, 13, 13, 13, 13, 13, 13, 9, + 13, 13, 13, 13, 12, 12, 12, 12, + ]); +}); + +test('returns expected 55/12 shards', async () => { + const allTests = toTests(new Array(55).fill(true).map((_, i) => `/${i}.js`)); + + const shards = await Promise.all( + new Array(12).fill(true).map((_, i) => + sequencer.shard(allTests, { + shardCount: 12, + shardIndex: i + 1, + }), + ), + ); + + expect(shards.map(shard => shard.length)).toEqual([ + 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, ]); }); diff --git a/packages/jest-test-sequencer/src/index.ts b/packages/jest-test-sequencer/src/index.ts index f55b5ea4c1f2..a0c6161d5666 100644 --- a/packages/jest-test-sequencer/src/index.ts +++ b/packages/jest-test-sequencer/src/index.ts @@ -72,6 +72,19 @@ export default class TestSequencer { return cache; } + _shardPosition(options: ShardOptions & {suiteLength: number}): number { + const shardRest = options.suiteLength % options.shardCount; + const ratio = options.suiteLength / options.shardCount; + + return new Array(options.shardIndex) + .fill(true) + .reduce((acc, _, shardIndex) => { + const dangles = shardIndex < shardRest; + const shardSize = dangles ? Math.ceil(ratio) : Math.floor(ratio); + return acc + shardSize; + }, 0); + } + /** * Select tests for shard requested via --shard=shardIndex/shardCount * Sharding is applied before sorting @@ -97,9 +110,17 @@ export default class TestSequencer { tests: Array, options: ShardOptions, ): Array | Promise> { - const shardSize = Math.ceil(tests.length / options.shardCount); - const shardStart = shardSize * (options.shardIndex - 1); - const shardEnd = shardSize * options.shardIndex; + const shardStart = this._shardPosition({ + shardCount: options.shardCount, + shardIndex: options.shardIndex - 1, + suiteLength: tests.length, + }); + + const shardEnd = this._shardPosition({ + shardCount: options.shardCount, + shardIndex: options.shardIndex, + suiteLength: tests.length, + }); return tests .map(test => { From bcf22397e0cdfa621eb4c16f312a901fdb28cd37 Mon Sep 17 00:00:00 2001 From: Mario Nebl Date: Thu, 20 Oct 2022 10:14:18 +1100 Subject: [PATCH 2/4] fix: mark _shardPosition as private Co-authored-by: Simen Bekkhus --- packages/jest-test-sequencer/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-test-sequencer/src/index.ts b/packages/jest-test-sequencer/src/index.ts index a0c6161d5666..e9b3f547f043 100644 --- a/packages/jest-test-sequencer/src/index.ts +++ b/packages/jest-test-sequencer/src/index.ts @@ -72,7 +72,7 @@ export default class TestSequencer { return cache; } - _shardPosition(options: ShardOptions & {suiteLength: number}): number { + private _shardPosition(options: ShardOptions & {suiteLength: number}): number { const shardRest = options.suiteLength % options.shardCount; const ratio = options.suiteLength / options.shardCount; From debc5efcfd15330b0ec3a4501d53c1774b59dbcb Mon Sep 17 00:00:00 2001 From: Mario Nebl Date: Thu, 20 Oct 2022 10:32:58 +1100 Subject: [PATCH 3/4] fix: type reduce explicitly --- packages/jest-test-sequencer/src/index.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/jest-test-sequencer/src/index.ts b/packages/jest-test-sequencer/src/index.ts index e9b3f547f043..7369397a8b80 100644 --- a/packages/jest-test-sequencer/src/index.ts +++ b/packages/jest-test-sequencer/src/index.ts @@ -24,6 +24,10 @@ export type ShardOptions = { shardCount: number; }; +type ShardPositionOptions = ShardOptions & { + suiteLength: number; +}; + /** * The TestSequencer will ultimately decide which tests should run first. * It is responsible for storing and reading from a local cache @@ -72,13 +76,13 @@ export default class TestSequencer { return cache; } - private _shardPosition(options: ShardOptions & {suiteLength: number}): number { + private _shardPosition(options: ShardPositionOptions): number { const shardRest = options.suiteLength % options.shardCount; const ratio = options.suiteLength / options.shardCount; return new Array(options.shardIndex) .fill(true) - .reduce((acc, _, shardIndex) => { + .reduce((acc, _, shardIndex) => { const dangles = shardIndex < shardRest; const shardSize = dangles ? Math.ceil(ratio) : Math.floor(ratio); return acc + shardSize; From 0e021c82ce75abe66d1b073e9783931b1f73ab3d Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Thu, 20 Oct 2022 13:04:47 +0200 Subject: [PATCH 4/4] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d08af002275..906e1998ec31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Fixes +- `[@jest/test-sequencer]` Make sure sharding does not produce empty groups ([#13476](https://github.com/facebook/jest/pull/13476)) + ### Chore & Maintenance ### Performance