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

Allow to run tests in the main process #51548

Closed
ematipico opened this issue Jan 23, 2024 · 11 comments
Closed

Allow to run tests in the main process #51548

ematipico opened this issue Jan 23, 2024 · 11 comments
Labels
feature request Issues that request new features to be added to Node.js. test_runner Issues and PRs related to the test runner subsystem.

Comments

@ematipico
Copy link

ematipico commented Jan 23, 2024

What is the problem this feature will solve?

At the moment, transitioning to node:test from mocha isn't always possible because of perf regressions in the execution of the test suite. This feature will allow us to break these perf executions.

Here are some perf times that I run in our Astro repository: withastro/astro#9758 (comment)

What is the feature you are proposing to solve the problem?

I would propose to accept an option to change the default behaviour. I don't want to bikeshed the name of the option, I leave to people that are better than me.

What alternatives have you considered?

Unfortunately, there isn't an alternative. We really want to transition to node:test, although at Astro we have a lot of tests, and we want to make sure that our CI doesn't become way slower than it already is.

@ematipico ematipico added the feature request Issues that request new features to be added to Node.js. label Jan 23, 2024
@MoLow MoLow added the test_runner Issues and PRs related to the test runner subsystem. label Jan 23, 2024
@MoLow
Copy link
Member

MoLow commented Jan 23, 2024

sounds like a legit feature. @nodejs/test_runner WDYT?

@aduh95
Copy link
Contributor

aduh95 commented Jan 23, 2024

Did you try to implement that in userland to validate the perf difference with Mocha is gone?

@bluwy
Copy link

bluwy commented Jan 24, 2024

@matthewp suggested a workaround to use a file that imports all the test files so to node it looks like a single test file. It seems to work fine and I had implemented that in this branch, which is based on withastro/astro#9758

Here's the result between node:test and mocha, running time pnpm test in the repo's /packages/integrations/node directory:

# node:test
pnpm test  10.24s user 1.24s system 115% cpu 9.914 total

# mocha
pnpm test  8.74s user 1.07s system 158% cpu 6.198 total

Mocha is perhaps slightly faster because it didn't have to spin up a child process at all. NOTE: in the branch linked above, I made a 2nd commit to fix some flaky tests. I also copied that to the Mocha tests so it's fairly compared.

@aduh95
Copy link
Contributor

aduh95 commented Jan 24, 2024

The tradeoff of launching all the test from the same process is that if one test mutates a global, all tests are affected, so it certainly makes sense to not provide that option by default. It should not be too complicated to offer it as an option for the run() function.

Mocha is perhaps slightly faster because it didn't have to spin up a child process at all.

It would be interesting to test that, either by spawning a child process to start mocha, or by not spawning a child process to start node:test implementation.

Another thing that would be interesting to test is to use Worker threads, not sure this has been experimented with yet.

@MoLow
Copy link
Member

MoLow commented Jan 24, 2024

It would be interesting to test that, either by spawning a child process to start mocha, or by not spawning a child process to start node:test implementation.

that can be done by omitting the --test flag

Another thing that would be interesting to test is to use Worker threads, not sure this has been experimented with yet.

I plan on experimenting with both worker threads and simply importing test files later today

@bluwy
Copy link

bluwy commented Jan 24, 2024

By skipping node:test's run() and importing the test files directly, I was able to test skipping the child process (can confirm that mutated globals are shared). Here's the result for time pnpm test like above:

pnpm test  10.53s user 1.37s system 115% cpu 10.294 total

Interestingly it's similar to using run() (that has isolation). So maybe starting one child process is fine, but too many it might take a toll on some projects. I've not looked into what else could have Mocha running faster though. NOTE: we have a custom astro-scripts test CLI to execute node:test, but compared to Mocha's, ours should be lighter-weight.

@matthewp
Copy link

@aduh95

The tradeoff of launching all the test from the same process is that if one test mutates a global, all tests are affected, so it certainly makes sense to not provide that option by default.

I don't know how much code on npm is depending on globals, I assume the majority of it is simple utility input/output functions that don't need such a feature.

I also think file-based isolation is a weird choice in that it creates a refactor hazard. You decide that test1.js and test2.js are very similar so you combine them into 1 file and now the tests fail. That seems like a failure in your code you should be fixing.

Given that people use files for code organization it seems like a strange choice to me to make it also be about test isolation.

@aduh95
Copy link
Contributor

aduh95 commented Jan 24, 2024

I also think file-based isolation is a weird choice in that it creates a refactor hazard.

It hardly matters what we think about that choice, changing it would be a breaking change, so probably not worth it.

@benjamingr
Copy link
Member

Sounds like a legitimate feature to me

@rluvaton
Copy link
Member

rluvaton commented Feb 5, 2024

Isn't it duplicate of #48871 ?

@ematipico ematipico closed this as not planned Won't fix, can't repro, duplicate, stale May 25, 2024
@cjihrig cjihrig reopened this May 25, 2024
@cjihrig
Copy link
Contributor

cjihrig commented Jul 18, 2024

Implementation work on this has moved to #53927

@RedYetiDev RedYetiDev moved this from Awaiting Triage to Triaged in Node.js feature requests Jul 18, 2024
@RedYetiDev RedYetiDev moved this from Triaged to In Progress in Node.js feature requests Jul 18, 2024
nodejs-github-bot pushed a commit that referenced this issue Aug 21, 2024
This commit introduces a new --experimental-test-isolation flag
that, when set to 'none', causes the test runner to execute all
tests in the same process. By default, this is the main test
runner process, but if watch mode is enabled, it spawns a separate
process that runs all of the tests.

The default value of the new flag is 'process', which uses the
existing behavior of running each test file in its own child
process.

It is worth noting that when the isolation mode is 'none', globals
and all other top level logic (such as top level before() and after()
hooks) is shared among all files.

Co-authored-by: Moshe Atlow <moshe@atlow.co.il>
PR-URL: #53927
Fixes: #51548
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
RafaelGSS pushed a commit that referenced this issue Aug 25, 2024
This commit updates the way the test runner computes inherited
hooks. Instead of computing them when the Test/Suite is
constructed, they are now computed just prior to running the
Test/Suite. The reason is because when multiple test files are
run in the same process, it is possible for the inherited hooks
to change as more files are loaded.

PR-URL: #53927
Fixes: #51548
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
RafaelGSS pushed a commit that referenced this issue Aug 25, 2024
This commit introduces a new --experimental-test-isolation flag
that, when set to 'none', causes the test runner to execute all
tests in the same process. By default, this is the main test
runner process, but if watch mode is enabled, it spawns a separate
process that runs all of the tests.

The default value of the new flag is 'process', which uses the
existing behavior of running each test file in its own child
process.

It is worth noting that when the isolation mode is 'none', globals
and all other top level logic (such as top level before() and after()
hooks) is shared among all files.

Co-authored-by: Moshe Atlow <moshe@atlow.co.il>
PR-URL: #53927
Fixes: #51548
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
@RedYetiDev RedYetiDev moved this from In Progress to Done in Node.js feature requests Aug 26, 2024
RafaelGSS pushed a commit that referenced this issue Aug 30, 2024
This commit introduces a new --experimental-test-isolation flag
that, when set to 'none', causes the test runner to execute all
tests in the same process. By default, this is the main test
runner process, but if watch mode is enabled, it spawns a separate
process that runs all of the tests.

The default value of the new flag is 'process', which uses the
existing behavior of running each test file in its own child
process.

It is worth noting that when the isolation mode is 'none', globals
and all other top level logic (such as top level before() and after()
hooks) is shared among all files.

Co-authored-by: Moshe Atlow <moshe@atlow.co.il>
PR-URL: #53927
Fixes: #51548
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Issues that request new features to be added to Node.js. test_runner Issues and PRs related to the test runner subsystem.
Projects
None yet
8 participants