Repository navigation
t.skip does not invoke test.afterEach #61462
Description
Activity
@jsumners-nr I’m seeing the same behaviour. Looking at the test runner,
test.afterEachis only invoked whenthis.skippedis false.@cjihrig and @MoLow — is this the intended behaviour? I see you’ve both worked on the test runner.
If this is expected, it may be worth clarifying the docs. They currently state that
afterEach()runs even if a test fails, but don’t mention that it does not run when a test is skipped.Alternatively, should
afterEachrun whenskip()is called from within the test body, and only be skipped whenskipis provided as a test option?Happy to work on this once the intended behaviour is clear.
Reacted by James SumnersAlternatively, should
afterEachrun whenskip()is called from within the test body, and only be skipped whenskipis provided as a test option?That would make more sense to me given:
'use strict' const test = require('node:test') test.beforeEach((t) => { process._rawDebug('!!! beforeEach:', t.name) }) test.afterEach(() => { process._rawDebug('!!! afterEach') }) test('one', (t) => { t.assert.ok('one is good') }) test('two', (t) => { if (process.env.TEST_SKIP === 'false') { t.assert.ok('two is good') } else { t.skip('two gets skipped after some logic') } }) test('three', { skip: true }, () => {}) // ❯ node index.js // !!! beforeEach: one // !!! afterEach // !!! beforeEach: two // ✔ one (1.0415ms) // ﹣ two (0.132708ms) # two gets skipped after some logic // ﹣ three (0.045167ms) # SKIP // ℹ tests 3 // ℹ suites 0 // ℹ pass 1 // ℹ fail 0 // ℹ cancelled 0 // ℹ skipped 2 // ℹ todo 0 // ℹ duration_ms 4.874333
Since
{ skip: true }means that thetest.beforeEachis not invoked, it is most likely that no clean up needs to happen intest.afterEach. But witht.skip, thetest.beforeEachis invoked and therefore has a high likelihood of setting up stuff that needs to be cleaned up after the test. In my opinion, this is a bug.Reacted by mattskel and RenéRegardless,
t.skipshouldn't be skipping the containing test - it's just a skip comment for an assertion. The only way to skip a test in my experience is usually to invoke it with.skip()orskip: truein the first place.Reacted by Pietro Marchini and Moshe AtlowRegardless,
t.skipshouldn't be skipping the containing test - it's just a skip comment for an assertion. The only way to skip a test in my experience is usually to invoke it with.skip()orskip: truein the first place.Correct: https://nodejs.org/docs/latest/api/test.html#contextskipmessage
This issue is:
- the test is being invoked
- the test issues
context.skipto show the test has been skipped internally - the
test.afterEachis not invoked becausecontext.skipwas invoked
I assert that this is wrong because once the test function has been invoked any
beforeEachsetup should have its associatedafterEachinvoked.Reacted by Jordan HarbandThis is 100% true; if a before callback ran, the after callback MUST be run to clean things up.
- added a commit that references this issue
on Feb 26, 2026 - added a commit that references this issue
on Feb 28, 2026 Thank you for resolving this @igor-shevelenkov.
Reacted by Igor Shevelenkov- added 6 commits that reference this issue
on Apr 4, 2026 - added a commit that references this issue
on Jul 29, 2026
I expect that
!!! afterEachwill be printed twice when this test suite is run. However, on Node.js 20.20.0 and 24.13.0, that is not the case. Instead, the result is:This is a problem when the test being skipped depends upon logic internal to the test. As an example, we may have a test setup like: