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_runner,cli: --test-timeout should be used with --test #53773

Closed
wants to merge 1 commit into from

Conversation

jakecastelli
Copy link
Member

When --test-timeout used without --test it does not behave what the user would expect.

Refs: #50431 (comment)

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/test_runner

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. labels Jul 9, 2024
@atlowChemi atlowChemi added request-ci Add this label to start a Jenkins CI on a PR. test_runner Issues and PRs related to the test runner subsystem. labels Jul 10, 2024
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Jul 10, 2024
@nodejs-github-bot
Copy link
Collaborator

@rluvaton
Copy link
Member

Isn't it breaking change? (nobody should use test timeout without test but it would break now)

@jakecastelli
Copy link
Member Author

Hi @rluvaton, yes it would break, on the other hand this feels more like a bug or at least false positive to me. As without --test then --test-timeout does not behave like what it is supposed to be.

@cjihrig
Copy link
Contributor

cjihrig commented Jul 12, 2024

I don't think this is the correct fix. The problem is that --test-timeout as implemented simply does not work properly (IMO). The flag itself should be supported with or without the --test flag.

@jakecastelli
Copy link
Member Author

Hi @cjihrig thanks for your input, I thought the origin implementation meant to be used with --test.

The flag itself should be supported with or without the --test flag

Now I see your point, in that case we will need to grab the --test-timeout flag around here to ensure this.timeout is not null.

Let me know your thoughts, cheers.

@jakecastelli
Copy link
Member Author

I have another question which is when timeout is passed in as an option along with --test-timeout cli flag, which one should take priority?

consider the following code snippet:

import { test } from "node:test";

test("test timeout", { timeout: 100 }, (t, done) => {
  setTimeout(done, 3000);
});
node --test-timeout=2000

Should 100 be applied or 2000?

@rluvaton
Copy link
Member

rluvaton commented Jul 12, 2024

I tend to lean to

Test timeout > cli flag > run config

@cjihrig
Copy link
Contributor

cjihrig commented Jul 12, 2024

Test timeout > cli flag > run config

I think local config should take precedence over more global config. In other words test timeout > run() config > CLI flag

@nodejs-github-bot
Copy link
Collaborator

Copy link
Contributor

@cjihrig cjihrig left a comment

Choose a reason for hiding this comment

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

Explicitly requesting changes. This is technically a breaking change. If we are going to introduce a breaking change on this flag, we should do so in a way that actually makes it better.

@jakecastelli
Copy link
Member Author

If we are going to introduce a breaking change on this flag, we should do so in a way that actually makes it better.

Could you explain in which area we could make it better?

My understanding is that:

  • This PR should make it slightly better I think as it prevents the false positive result but it will be a breaking change as --test-timeout could only be used with --test through test_runner in the future.
  • We want to support --test-timeout even without --test. as per comment.

Anything else I could've missed?

@cjihrig
Copy link
Contributor

cjihrig commented Jul 15, 2024

Let me try to explain with an example. Consider the following file named test.js:

'use strict';
const { test } = require('node:test');

test('delay', () => {
  return new Promise((resolve) => {
    setTimeout(resolve, 10_000);
  });
});

test('pass');

Someone could run this in a few ways relevant to this PR:

  • node test.js - Everything passes after ~10 seconds. This is correct behavior.
  • node --test test.js - Everything passes after ~10 seconds. This is correct behavior.
  • node --test-timeout=500 test.js - This currently passes after ~10 seconds. The entire file should timeout after 500ms if we consider the current behavior of --test-timeout correct (I do not consider it correct).
  • node --test --test-timeout=500 test.js - This currently times out after 500ms. The test results show a single cancelled test corresponding to the entire test.js file.

I am proposing that the behavior of the first two cases stay the same, while the final two cases should both run to completion (the setTimeout() will keep the process alive for longer, but the tests should run) after ~500ms and the results should show one timed out test followed by one passing test.

@jakecastelli
Copy link
Member Author

jakecastelli commented Jul 15, 2024

Oh I see what you mean!! Thanks for explaining it in great details.

I agree, the current implementation of --test-timeout is not correct, it does not make too much sense to apply timeout on the entire file. Therefore my fix is not actually an improvement (consider we want to support the 3rd case).

@jakecastelli
Copy link
Member Author

jakecastelli commented Jul 16, 2024

Let me try to explain with an example. Consider the following file named test.js:

'use strict';
const { test } = require('node:test');

test('delay', () => {
  return new Promise((resolve) => {
    setTimeout(resolve, 10_000);
  });
});

test('pass');

Someone could run this in a few ways relevant to this PR:

  • node test.js - Everything passes after ~10 seconds. This is correct behavior.
  • node --test test.js - Everything passes after ~10 seconds. This is correct behavior.
  • node --test-timeout=500 test.js - This currently passes after ~10 seconds. The entire file should timeout after 500ms if we consider the current behavior of --test-timeout correct (I do not consider it correct).
  • node --test --test-timeout=500 test.js - This currently times out after 500ms. The test results show a single cancelled test corresponding to the entire test.js file.

I am proposing that the behavior of the first two cases stay the same, while the final two cases should both run to completion (the setTimeout() will keep the process alive for longer, but the tests should run) after ~500ms and the results should show one timed out test followed by one passing test.

Hi Colin, I think there is a 5th case: UPDATE: This is the same as the 4th case.

  • node --test --test-timeout=500 This currently cancels the rest of the tests when any of the test timeout. Is it the behaviour we wanted? UPDATE: This is the same as the 4th case.

Consider the following example:

// test-1.mjs
import { test } from "node:test";

test("test timeout", () => {
  return new Promise((resolve) => {
    setTimeout(resolve, 5_000);
  });
});
// test-2.mjs
"use strict";
import { test } from "node:test";

test("delay 10s", () => {
  return new Promise((resolve) => {
    setTimeout(resolve, 10_000);
  });
});

test("delay 1s", () => {
  return new Promise((resolve) => {
    setTimeout(resolve, 1_000);
  });
});

test("pass");

when we run node --test --test-timeout=2000 it will say:

✖ test-2.mjs (2002.938084ms)
  'test timed out after 2000ms'

✖ test.mjs (2002.376083ms)
  'test timed out after 2000ms'

ℹ tests 2
ℹ suites 0
ℹ pass 0
ℹ fail 0
ℹ cancelled 2
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 2011.548291

As you can see, test cases delay 1s and pass didn't get a chance to run and on a side note the summary seems not that helpful as it lacks the test case names.

@cjihrig
Copy link
Contributor

cjihrig commented Jul 16, 2024

@jakecastelli yes, that is the same as the fourth case I mentioned above. If you're interested in working on this, I would suggest starting with the third case above and then working backward from there to the CLI parts (which will be significantly simpler to fix).

@jakecastelli
Copy link
Member Author

Thanks Colin, yes I am interested in working on this and I think I may close to get a draft PR up for feedback soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants