Skip to content

test_runner: add skip, todo, only, and expectFailure to subtest context#62156

Open
Felipeness wants to merge 2 commits intonodejs:mainfrom
Felipeness:fix/test-runner-subtest-skip-todo-only
Open

test_runner: add skip, todo, only, and expectFailure to subtest context#62156
Felipeness wants to merge 2 commits intonodejs:mainfrom
Felipeness:fix/test-runner-subtest-skip-todo-only

Conversation

@Felipeness
Copy link

The top-level test() function exposes test.skip(), test.todo(), test.only(), and test.expectFailure() variants, but these were missing from TestContext's test() method. Calling t.test.skip() inside a test callback threw TypeError: t.test.skip is not a function.

The documentation states that t.test() "behaves identically to the top level test()", so this is a bug.

Changes

  • Move test() from the TestContext class prototype to an arrow function in the constructor, allowing variant methods to be attached as properties
  • Extract a shared runSubtest() helper to avoid duplicating plan counting and createSubtest logic
  • Attach .skip, .todo, .only, and .expectFailure — matching the exact same list used in harness.js for the top-level test()

Trade-off

This trades one shared prototype method for 5 closures per TestContext instance (one base + four variants). This is acceptable given V8's closure optimization for same-shape functions, and is the same pattern used by the top-level test() in harness.js.

Test plan

  • Verify all variant functions exist on TestContext (including expectFailure)
  • t.test.skip() prevents callback execution
  • t.test.todo() without callback (marks as todo, skips)
  • t.test.todo() with callback (runs callback, marks as todo)
  • t.plan() counting works with subtest variants
  • Nested subtests also expose all variants

Fixes: #50665

@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 Mar 8, 2026
@Felipeness
Copy link
Author

This is an alternative to #61251, addressing the same issue. Key differences:

  • Includes expectFailure in the variants list (matching the full set from harness.js)
  • Extracts a shared runSubtest() helper to avoid code duplication
  • Additional test coverage: todo with callback, plan counting with variants, expectFailure existence check

The top-level test() function exposes test.skip(), test.todo(),
test.only(), and test.expectFailure() variants, but these were missing
from TestContext's test() method used in subtests, causing TypeError.

Move test() from the class prototype to an arrow function in the
constructor, allowing variants to be attached as properties. Extract
a shared runSubtest() helper to avoid duplicating the plan counting
and createSubtest logic. This trades one shared prototype method for
5 closures per TestContext instance (one base + four variants), which
is acceptable given V8's closure optimization for same-shape functions.

Includes tests for: variant existence, skip preventing callback
execution, todo with and without callback, plan counting with
variants, and nested subtest variant availability.

Fixes: nodejs#50665
@Felipeness Felipeness force-pushed the fix/test-runner-subtest-skip-todo-only branch from d9bb1f7 to 60db1ec Compare March 8, 2026 19:54
Node.js core lint rule (node-core/set-proto-to-null-in-object)
requires every object literal in lib/ to have __proto__: null
to prevent prototype pollution.
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.

test runner (--test, node:test) subtest test context lack .skip, .only and .todo functions

2 participants