Skip to content

Conversation

@igor-shevelenkov
Copy link

Ensure afterEach runs when a test is skipped at runtime (t.skip()), while keeping static { skip: true } behavior unchanged.

Runtime t.skip() previously set skipped and prevented afterEach, even if beforeEach ran.
This left resources uncleaned and differed from user expectations.

Fixes: #61462

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/test_runner

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. test_runner Issues and PRs related to the test runner subsystem. labels Jan 26, 2026
Copy link

@jsumners-nr jsumners-nr left a comment

Choose a reason for hiding this comment

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

Looks good to me.

igor-shevelenkov and others added 2 commits January 26, 2026 17:46
Increment a beforeEach counter and assert it runs twice when a test
is skipped at runtime.

Signed-off-by: Igor <igorshevelenkov4@gmail.com>
@ljharb
Copy link
Member

ljharb commented Jan 26, 2026

This looks fine, but t.skip() shouldn't be marking the overarching test as skipped at all - its purpose is to generate a string comment that will show up as a skipped assertion.

@igor-shevelenkov
Copy link
Author

Thanks @ljharb. I see from tape-testing/tape#545 that in tape, t.skip() is designed as an assertion-level skip. Not a test-level skip. That aligns with TAP semantics.
However, Node's test runner has established t.skip() as a test-level runtime skip. It marks the whole test as skipped, not just an assertion. If we choose to change that i think it'll be a breaking change.
I think something like a separate t.skipAssertion() method would be better

Comment on lines +32 to +36
process.on('exit', () => {
assert.strictEqual(beforeEachTotal, 2);
assert.strictEqual(afterEachRuntimeSkip, 1);
assert.strictEqual(afterEachTotal, 2);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need the beforeEachTotal or afterEachTotal variables. The common.mustCall()s will enforce those for you.

@ljharb
Copy link
Member

ljharb commented Jan 26, 2026

@igor-shevelenkov deviating from TAP semantics seems like a pretty big design issue, but fair that it'd be a breaking change. I'd still suggest making it (in a different PR ofc)

@codecov
Copy link

codecov bot commented Jan 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.77%. Comparing base (83893bb) to head (3a29ef0).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #61525      +/-   ##
==========================================
- Coverage   89.78%   89.77%   -0.01%     
==========================================
  Files         672      672              
  Lines      203809   203811       +2     
  Branches    39183    39189       +6     
==========================================
- Hits       182980   182963      -17     
- Misses      13166    13177      +11     
- Partials     7663     7671       +8     
Files with missing lines Coverage Δ
lib/internal/test_runner/test.js 97.31% <100.00%> (+<0.01%) ⬆️

... and 31 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

t.skip does not invoke test.afterEach

5 participants