Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
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
5 changes: 2 additions & 3 deletions packages/node-integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"fix:prettier": "prettier --write \"{suites,utils}/**/*.ts\"",
"type-check": "tsc",
"pretest": "run-s --silent prisma:init",
"test": "jest --forceExit",
"test": "ts-node ./utils/run-tests.ts",
"test:watch": "yarn test --watch"
},
"dependencies": {
Expand All @@ -34,8 +34,7 @@
"mongodb-memory-server-global": "^7.6.3",
"mysql": "^2.18.1",
"nock": "^13.1.0",
"pg": "^8.7.3",
"portfinder": "^1.0.28"
"pg": "^8.7.3"
},
"config": {
"mongodbMemoryServer": {
Expand Down
10 changes: 4 additions & 6 deletions packages/node-integration-tests/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { logger, parseSemver } from '@sentry/utils';
import axios, { AxiosRequestConfig } from 'axios';
import { Express } from 'express';
import * as http from 'http';
import { AddressInfo } from 'net';
import nock from 'nock';
import * as path from 'path';
import { getPortPromise } from 'portfinder';

export type TestServerConfig = {
url: string;
Expand Down Expand Up @@ -151,11 +151,9 @@ export class TestEnv {
}
});

void getPortPromise().then(port => {
const url = `http://localhost:${port}/test`;
const server = app.listen(port, () => {
resolve([server, url]);
});
const server = app.listen(0, () => {
const url = `http://localhost:${(server.address() as AddressInfo).port}/test`;
resolve([server, url]);
});
});

Expand Down
61 changes: 61 additions & 0 deletions packages/node-integration-tests/utils/run-tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/* eslint-disable no-console */
import childProcess from 'child_process';
import os from 'os';

const testPaths = childProcess.execSync('jest --listTests', { encoding: 'utf8' }).trim().split('\n');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having an explanation here is both helpful in its own right and possibly a way to forestall other folks asking the same question Abhi asked about foreEach.

Suggested change
const testPaths = childProcess.execSync('jest --listTests', { encoding: 'utf8' }).trim().split('\n');
// This will serve as a pool of remaining tests from which the threads spawned below can draw
const testPaths = childProcess.execSync('jest --listTests', { encoding: 'utf8' }).trim().split('\n');

Also:

jest --listTests

TIL! 🙂


let testsSucceeded = true;
const testAmount = testPaths.length;
const fails: string[] = [];

const threads = os.cpus().map(async (_, i) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think this makes it slightly clearer that two things are really happening, thread creation and thread use.

Suggested change
const threads = os.cpus().map(async (_, i) => {
const threads = os.cpus()
threads.map(async (_, i) => {

let testPath = testPaths.pop();
while (testPath !== undefined) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not a .forEach here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If by forEach you mean iterating over the jobs - I didn't do that because a) I don't want to overload the host machine by instantly starting a bazillion of processes, b) I wanted to distribute the jobs among the workers evenly, i.e. by popping another job off the queue when they're done with their current one. I honestly wouldn't know how to do that with forEach.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had in my head to just split the tests by cpus beforehand and then sync iterate, but the producer - consumer pattern you have here is way more effective, I just didn't think it through.

console.log(`(Worker ${i}) Running test "${testPath}"`);
await new Promise(resolve => {
const p = childProcess.spawn('jest', ['--runTestsByPath', testPath as string, '--forceExit']);

let output = '';

p.stdout.on('data', (data: Buffer) => {
output = output + data.toString();
});

p.stderr.on('data', (data: Buffer) => {
output = output + data.toString();
});

p.on('error', error => {
console.log(`(Worker ${i}) Error in test "${testPath}"`, error);
console.log(output);
resolve();
});

p.on('exit', exitcode => {
console.log(`(Worker ${i}) Finished test "${testPath}"`);
console.log(output);
if (exitcode !== 0) {
fails.push(`FAILED: "${testPath}"`);
testsSucceeded = false;
}
resolve();
});
});
testPath = testPaths.pop();
}
});

void Promise.all(threads).then(() => {
console.log('-------------------');
console.log(`Successfully ran ${testAmount} tests.`);
if (!testsSucceeded) {
console.log('Not all tests succeeded:\n');
fails.forEach(fail => {
console.log(`● ${fail}`);
});
process.exit(1);
} else {
console.log('All tests succeeded.');
process.exit(0);
}
});
3 changes: 2 additions & 1 deletion packages/remix/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
},
"devDependencies": {
"@remix-run/node": "^1.4.3",
"@remix-run/react": "^1.4.3"
"@remix-run/react": "^1.4.3",
"portfinder": "^1.0.28"
},
"peerDependencies": {
"@remix-run/node": "1.x",
Expand Down