Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Run node integration tests in isolation #5721

Merged
merged 8 commits into from
Sep 13, 2022

Conversation

lforst
Copy link
Member

@lforst lforst commented Sep 12, 2022

Since even after merging #5715 I have trouble with the global context being shared across tests we should definitely isolate the individual node integration tests before something slips though because of it.

This PR adds a quick and dirty script that runs all the test files with an individual jest command. It doesn't do anything fancy except for creating a worker sharing work for each CPU core available.

Also removes the portfinder package from the integration tests as it was a bit inconsistent - we now let the OS choose a port on its own.

This PR admittedly doesn't contain a lot of effort but was done to unblock #5710

@lforst lforst force-pushed the lforst-isolated-node-integration-tests branch from c90e3bd to dd5fe3f Compare September 12, 2022 12:57

const threads = os.cpus().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
Member 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.

@lforst lforst enabled auto-merge (squash) September 12, 2022 13:29
Copy link
Member

@lobsterkatie lobsterkatie left a comment

Choose a reason for hiding this comment

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

This is nicely done!

Perhaps at some point we can apply the same logic to places where we run jest with --runInBand.

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! 🙂

const numTests = 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) => {

Comment on lines +18 to +26
let output = '';

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

jestProcess.stderr.on('data', (data: Buffer) => {
output = output + data.toString();
});
Copy link
Member

Choose a reason for hiding this comment

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

Are you doing it this way (rather than just setting stdio to inherit in your spawn options) so that the output from each test is printed in a single block, rather than being interleaved with output from the other running tests? If so, a) good thinking!, and b) I think a comment saying so would be helpful.

@lforst lforst enabled auto-merge (squash) September 13, 2022 07:52
@lforst lforst merged commit 8f19db5 into master Sep 13, 2022
@lforst lforst deleted the lforst-isolated-node-integration-tests branch September 13, 2022 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants