Skip to content

Commit

Permalink
[tests] Run unit tests concurrently in chunks (#9615)
Browse files Browse the repository at this point in the history
We can separate each package `test-unit` into a separate job. This will help isolate problems and we can re-run CI for a specific package.
  • Loading branch information
styfle committed Mar 7, 2023
1 parent f207563 commit c062099
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 25 deletions.
4 changes: 2 additions & 2 deletions packages/node/test/integration-setup.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const fs = require('fs');
const path = require('path');
const { intoChunks, NUMBER_OF_CHUNKS } = require('../../../utils/chunk-tests');
const { intoChunks } = require('../../../utils/chunk-tests');

const {
testDeployment,
Expand All @@ -20,7 +20,7 @@ module.exports = function setupTests(groupIndex) {
let fixtures = fs.readdirSync(fixturesPath);

if (typeof groupIndex !== 'undefined') {
fixtures = intoChunks(NUMBER_OF_CHUNKS, fixtures)[groupIndex - 1];
fixtures = intoChunks(1, 5, fixtures)[groupIndex - 1];

console.log('testing group', groupIndex, fixtures);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/static-build/test/integration-setup.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const fs = require('fs');
const path = require('path');
const { intoChunks, NUMBER_OF_CHUNKS } = require('../../../utils/chunk-tests');
const { intoChunks } = require('../../../utils/chunk-tests');

const {
testDeployment,
Expand Down Expand Up @@ -33,7 +33,7 @@ module.exports = function setupTests(groupIndex) {
let fixtures = fs.readdirSync(fixturesPath);

if (typeof groupIndex !== 'undefined') {
fixtures = intoChunks(NUMBER_OF_CHUNKS, fixtures)[groupIndex - 1];
fixtures = intoChunks(1, 5, fixtures)[groupIndex - 1];

console.log('testing group', groupIndex, fixtures);
}
Expand Down
43 changes: 25 additions & 18 deletions utils/chunk-tests.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
// @ts-check
const child_process = require('child_process');
const path = require('path');

const NUMBER_OF_CHUNKS = 5;
const MINIMUM_PER_CHUNK = 1;
const runnersMap = new Map([
['test-e2e', ['ubuntu-latest']],
['test-next-local', ['ubuntu-latest']],
['test-dev', ['ubuntu-latest', 'macos-latest']],
[
'test-unit',
{
min: 1,
max: 1,
runners: ['ubuntu-latest', 'macos-latest', 'windows-latest'],
},
],
['test-e2e', { min: 1, max: 5, runners: ['ubuntu-latest'] }],
['test-next-local', { min: 1, max: 5, runners: ['ubuntu-latest'] }],
['test-dev', { min: 1, max: 5, runners: ['ubuntu-latest', 'macos-latest'] }],
]);

async function getChunkedTests() {
Expand Down Expand Up @@ -60,11 +67,14 @@ async function getChunkedTests() {
([packagePathAndName, scriptNames]) => {
const [packagePath, packageName] = packagePathAndName.split(',');
return Object.entries(scriptNames).flatMap(([scriptName, testPaths]) => {
const {
runners = ['ubuntu-latest'],
min = 1,
max = 1,
} = runnersMap.get(scriptName) || {};
const sortedTestPaths = testPaths.sort((a, b) => a.localeCompare(b));
return intoChunks(NUMBER_OF_CHUNKS, sortedTestPaths).flatMap(
return intoChunks(min, max, sortedTestPaths).flatMap(
(chunk, chunkNumber, allChunks) => {
const runners = runnersMap.get(scriptName) || ['ubuntu-latest'];

return runners.map(runner => {
return {
runner,
Expand Down Expand Up @@ -115,7 +125,7 @@ async function turbo(args) {
if (code !== 0) {
reject(new Error(`Turbo exited with code ${code}`));
} else {
resolve();
resolve(code);
}
});
});
Expand All @@ -128,17 +138,15 @@ async function turbo(args) {

/**
* @template T
* @param {number} totalChunks maximum number of chunks
* @param {T[]} values
* @param {number} minChunks minimum number of chunks
* @param {number} maxChunks maximum number of chunks
* @param {T[]} arr
* @returns {T[][]}
*/
function intoChunks(totalChunks, arr) {
const chunkSize = Math.max(
MINIMUM_PER_CHUNK,
Math.ceil(arr.length / totalChunks)
);
function intoChunks(minChunks, maxChunks, arr) {
const chunkSize = Math.max(minChunks, Math.ceil(arr.length / maxChunks));
const chunks = [];
for (let i = 0; i < totalChunks; i++) {
for (let i = 0; i < maxChunks; i++) {
chunks.push(arr.slice(i * chunkSize, (i + 1) * chunkSize));
}
return chunks.filter(x => x.length > 0);
Expand All @@ -161,5 +169,4 @@ if (module === require.main || !module.parent) {

module.exports = {
intoChunks,
NUMBER_OF_CHUNKS,
};
17 changes: 14 additions & 3 deletions utils/chunk-tests.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,27 @@ const { intoChunks } = require('./chunk-tests');
describe('it should create chunks correctly', () => {
it('should split chunks correctly less chunks than items', () => {
const files = ['/first', '/second', '/third'];
expect(intoChunks(2, files)).toEqual([['/first', '/second'], ['/third']]);
expect(intoChunks(1, 2, files)).toEqual([
['/first', '/second'],
['/third'],
]);
});

it('should split chunks correctly more chunks than items', () => {
const files = ['/first', '/second', '/third'];
expect(intoChunks(5, files)).toEqual([['/first'], ['/second'], ['/third']]);
expect(intoChunks(1, 5, files)).toEqual([
['/first'],
['/second'],
['/third'],
]);
});

it('should split chunks correctly equal chunks with items', () => {
const files = ['/first', '/second', '/third'];
expect(intoChunks(3, files)).toEqual([['/first'], ['/second'], ['/third']]);
expect(intoChunks(1, 3, files)).toEqual([
['/first'],
['/second'],
['/third'],
]);
});
});

0 comments on commit c062099

Please sign in to comment.