node icon indicating copy to clipboard operation
node copied to clipboard

test_runner: add cwd option to run

Open pmarchini opened this issue 1 year ago • 12 comments

I'm opening this PR as a draft to have a place where we can discuss this implementation.

Some background context:

During #54225, we discussed the possibility of adding a new option to run.
This new option would be cwd.

This change could impact many other parts of the code, such as: https://github.com/nodejs/node/pull/54225#issuecomment-2308943539

I just pushed a new commit.

Nice. I realized that this new cwd option may introduce new bugs in at least three places:

For this reason, we decided to work on this in a separate PR (https://github.com/nodejs/node/pull/54225#issuecomment-2308944216).

pmarchini avatar Sep 01 '24 19:09 pmarchini

Review requested:

  • [ ] @nodejs/test_runner

nodejs-github-bot avatar Sep 01 '24 19:09 nodejs-github-bot

We need to turn the cwd option into a URL and get the href.

If we make the cwd a part of the globalOptions object, the coverage code will have access to it.

Same thing. The test object there will have a reference to the cwd.

cjihrig avatar Sep 03 '24 18:09 cjihrig

@cjihrig thanks for the support, I'm gonna take a look ASAP!

pmarchini avatar Sep 03 '24 19:09 pmarchini

Codecov Report

Attention: Patch coverage is 83.33333% with 3 lines in your changes missing coverage. Please review.

Project coverage is 88.42%. Comparing base (89a2f56) to head (a162f2d). Report is 31 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/test_runner/runner.js 78.57% 2 Missing and 1 partial :warning:
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #54705      +/-   ##
==========================================
+ Coverage   88.39%   88.42%   +0.02%     
==========================================
  Files         652      652              
  Lines      186565   186576      +11     
  Branches    36046    36050       +4     
==========================================
+ Hits       164916   164981      +65     
+ Misses      14908    14866      -42     
+ Partials     6741     6729      -12     
Files with missing lines Coverage Δ
lib/internal/test_runner/coverage.js 64.69% <100.00%> (-0.06%) :arrow_down:
lib/internal/test_runner/harness.js 92.67% <100.00%> (+0.02%) :arrow_up:
lib/internal/test_runner/runner.js 89.42% <78.57%> (+2.38%) :arrow_up:

... and 45 files with indirect coverage changes

codecov[bot] avatar Sep 16 '24 14:09 codecov[bot]

CI: https://ci.nodejs.org/job/node-test-pull-request/62684/

nodejs-github-bot avatar Sep 23 '24 08:09 nodejs-github-bot

CI: https://ci.nodejs.org/job/node-test-pull-request/62731/

nodejs-github-bot avatar Sep 24 '24 13:09 nodejs-github-bot

It looks like there may be relevant failures in the latest CI run.

cjihrig avatar Sep 24 '24 17:09 cjihrig

It looks like there may be relevant failures in the latest CI run.

Hey @cjihrig, yes I've seen, I'm preparing my Windows build!

pmarchini avatar Sep 24 '24 17:09 pmarchini

@cjihrig after some attempts I was able to reproduce the same errors on my Windows 10 machine. I'll take a look ASAP, it's definitely flaky

pmarchini avatar Sep 25 '24 08:09 pmarchini

@cjihrig, I'm still looking into this. I've been able to replicate it 3 times in 12 hours, after thousands of retries

pmarchini avatar Sep 25 '24 22:09 pmarchini

Hey @cjihrig, I have just pushed a debug-only commit, I will revert it later.

In my local Windows environment, something very strange is happening:

The error, like the one we see in the pipeline, occurs only when running the test on a machine that has just been restarted from sleep.
It makes me think there might be some correlation with my very slow disk and the recovery from sleep mode.

~What surprises me is that, looking at the stack trace, it seems that the origin of the error is the same abort triggered in the unit test after the test:watch:drained~ (EDIT: this is expected).

While I keep testing, I will need another pipeline run. (I don't like trying to debug using the CI, but I'm not finding another way)

WDYT?

pmarchini avatar Sep 26 '24 07:09 pmarchini

WDYT?

I don't have a great answer. This is why I try to avoid working on watch mode.

cjihrig avatar Sep 28 '24 15:09 cjihrig

CI: https://ci.nodejs.org/job/node-test-pull-request/62899/

nodejs-github-bot avatar Oct 02 '24 18:10 nodejs-github-bot

CI: https://ci.nodejs.org/job/node-test-pull-request/62903/

nodejs-github-bot avatar Oct 03 '24 13:10 nodejs-github-bot

CI: https://ci.nodejs.org/job/node-test-pull-request/62905/

nodejs-github-bot avatar Oct 03 '24 15:10 nodejs-github-bot

Landed in 1c7795e52e6218d92bd498e377faecab7e17af5e

nodejs-github-bot avatar Oct 03 '24 15:10 nodejs-github-bot

The commit lands cleanly on v22.x-staging but test fails:

./node test/parallel/test-runner-no-isolation-different-cwd.mjs
before one: <root>
suite one
before two: <root>
suite two
beforeEach one: suite one - test
beforeEach two: suite one - test
suite one - test
afterEach one: suite one - test
afterEach two: suite one - test
beforeEach one: test one
beforeEach two: test one
test one
afterEach one: test one
afterEach two: test one
before suite two: suite two
beforeEach one: suite two - test
beforeEach two: suite two - test
suite two - test
afterEach one: suite two - test
afterEach two: suite two - test
after one: <root>
after two: <root>
node:internal/modules/run_main:122
    triggerUncaughtException(
    ^

AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
+ actual - expected ... Lines skipped

  [
    'before one: <root>',
...
    'afterEach one: suite one - test',
    'afterEach two: suite one - test',
+   'beforeEach one: test one',
+   'beforeEach two: test one',
+   'test one',
+   'afterEach one: test one',
+   'afterEach two: test one',
    'before suite two: suite two',
...
    'after one: <root>',
    'after two: <root>'
  ]
    at file:///Users/mzasso/git/nodejs/v22.x/test/parallel/test-runner-no-isolation-different-cwd.mjs:16:1
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5) {

targos avatar Oct 05 '24 10:10 targos

My guess is that the problem is the fixture's only test which requires --test-only on v22, but does not on main.

cjihrig avatar Oct 05 '24 14:10 cjihrig

I'll take a look ASAP

pmarchini avatar Oct 05 '24 16:10 pmarchini

Hey @cjihrig, I just took a quick look and the fixtures are not using only.

Given one.test.js:

suite('suite one', function() {
  record(this.name);

  test('suite one - test', { only: true }, function() {
    record(this.name);
  });
});

test('test one', function() {
  record(this.name);
});

and checking the output it seems that the failing output on the v22.x-staging is indeed correct. Idk why but it seems that in main, atm, given those test files, we're only executing the tests contained inside the suite and not the standalone test ('test one').

The behaviour I would expect is the one in v22.x-staging, do we agree on this?

Note:

I just tried to execute
./node --test --experimental-test-isolation=none test/fixtures/test-runner/no-isolation/one.test.js and
./node --test --experimental-test-isolation=process test/fixtures/test-runner/no-isolation/one.test.js.

The output is different, when isolation == none we're skipping

test('test one', function() {
  record(this.name);
});

(I just tested this in main)

pmarchini avatar Oct 08 '24 08:10 pmarchini

I just took a quick look and the fixtures are not using only.

I believe it is:

test('suite one - test', { only: true }, function() {

cjihrig avatar Oct 08 '24 11:10 cjihrig

I just took a quick look and the fixtures are not using only.

I believe it is:

test('suite one - test', { only: true }, function() {

Sorry, I completely missed it, even though I had just recopied it 😬

pmarchini avatar Oct 08 '24 12:10 pmarchini

@cjihrig, but still, do you think it makes sense to have two different behaviors based on the isolation?
Honestly, I wasn't expecting this.

Note:

> ./node --test --experimental-test-isolation=none  test/fixtures/test-runner/no-isolation/one.test.js
▶ suite one
  ✔ suite one - test (0.510791ms)
✔ suite one (0.929208ms)
ℹ tests 1
ℹ suites 1
ℹ pass 1
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 14.173333

and

> ./node --test --experimental-test-isolation=process  test/fixtures/test-runner/no-isolation/one.test.js
▶ suite one
  ✔ suite one - test (0.441834ms)
  ℹ 'only' and 'runOnly' require the --test-only command-line option.
✔ suite one (0.865417ms)
✔ test one (0.209416ms)
ℹ tests 2
ℹ suites 1
ℹ pass 2
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 94.562917

pmarchini avatar Oct 08 '24 12:10 pmarchini

do you think it makes sense to have two different behaviors based on the isolation?

For the only flag, I do. When running multiple test processes in parallel, some things are inherently different. For example, look at mocha, which calls out "some important implications of the behavior" including not supporting only at all.

cjihrig avatar Oct 08 '24 13:10 cjihrig

do you think it makes sense to have two different behaviors based on the isolation?

For the only flag, I do. When running multiple test processes in parallel, some things are inherently different. For example, look at mocha, which calls out "some important implications of the behavior" including not supporting only at all.

I agree, but I think I might be missing something here.

Why is test-only the default when isolation == none? As a user, I would expect to have to set --test-only even when isolation == none (or perhaps the reverse should be true).

What I mean is, I would expect the same default behavior regardless of the isolation mode.

This is an honest question. Considering that 22.x is still following this logic, I suppose it's something that was considered and decided recently. I'm not strongly opinionated on this, just curious.

EDIT: As always, thanks for your time and support! 🚀

pmarchini avatar Oct 08 '24 14:10 pmarchini

The idea is that no one ever wants to type --test-only because only tests can be automatically detected and handled appropriately. only is uniquely annoying because the test runner has to discover all of the tests that it will run, determine if any only tests were found, and if so, then apply filtering.

When using process isolation the annoyance factor is 100x worse because that logic needs to be coordinated across multiple child processes. It is technically possible to support, but the complexity and performance overhead are not worth it IMO. Prior to isolation=none existing, process isolation was the only mode of execution, so we needed a way to handle only tests. That's how --test-only came to be (the idea was copied from node-tap).

cjihrig avatar Oct 08 '24 15:10 cjihrig

@cjihrig, thank you for the explanation, it makes perfect sense 😁 I suppose this problem will be fixed as soon as https://github.com/nodejs/node/pull/54832 is backported to 22.x, right?

pmarchini avatar Oct 08 '24 16:10 pmarchini

I believe so.

cjihrig avatar Oct 08 '24 16:10 cjihrig

I suppose this problem will be fixed as soon as #54832 is backported to 22.x, right?

AFAICT that PR is already on v22.x, but trying to cherry-pick the commit from this PR still have a failing test.

aduh95 avatar Oct 09 '24 21:10 aduh95

Hey @aduh95, I just tested locally, and I think we're missing this PR: https://github.com/nodejs/node/pull/54881 (landed in commit https://github.com/nodejs/node/commit/dbaef339aad329aaf7e1b23072da7462ed9543e1) I tried cherry-picking that specific commit into 22.x-staging, and it fixes this test.

I suppose it can't be backported, as it's a semver-major.

Note: forgive me if what I've said doesn't make sense; I'm not super confident about backporting and release management 😬

pmarchini avatar Oct 10 '24 11:10 pmarchini