Skip to content

Discussion/Tracking: Adding more structure to Node.js' tests #54796

Closed
@jasnell

Description

@jasnell

It's no secret at this point that other runtimes (Deno, Bun, Workers, etc) are seeking to improve compatibility with Node.js. In order to accomplish this, these other runtimes need the ability to run Node.js' tests since those are really the closet thing we have to a conformance test suite. The challenge, however, is that the current corpus of tests are largely unstructured blobs of code that mix tests for public API with tests for internal API using a bespoke test harness that relies on Node.js specific characteristics. This makes it difficult for runtimes to partially/selectively implement Node.js compatibility and generally forces these other runtimes to manually port tests to work in those environments... particularly when the tests depend on specific Node.js internals that are not necessarily part of the public API surface (e.g. any test that relies on --expose-internals)

This issue serves two purposes: 1) as a place where we can discuss and try to come to consensus on a way of improving the structure of our tests, and 2) a tracking issue to track the progress of such activity.

There are four key issues:

  1. Mixing of internal and public APIs in tests without clear delineations between those.
  2. Lack of consistent documentation/comments explaining exactly what is being tested at any given point. This includes lack of documentation around what the expected behaviors being asserted are, etc.
  3. Haphazard organization. Some of the test files haphazardly just kind of sprinkle individual tests throughout the file in an almost organic or ad hoc way.
  4. Use of the bespoke test harness (require('../common') and it's reliance on various internal, undocumented behaviors and features that may be difficult to reconcile to other environments.

To improve overall structure of the tests, I propose:

  1. ... that we begin making use of our own node:test internal module to impose a more logical structure to the tests. I don't think it matters if that is using either the test('...', () => { ... }) or BDD describe('...', () => { ... }) pattern. I've seen both in use in a few tests already and some folks seem to prefer the BDD pattern. I'm good with that.

  2. ... that we reduce dependency on our internal bespoke test harness. For instance, common.mustCall() can be replaced (albeit with a bit more verbosity) with mock.fn() checks. The current ../common.js can be decomposed into individual imports to allow it to be more incrementally applied. The harness can also be made a bit less specific to Node.js and possibly even published as a separate module that can be made to run on multiple runtimes.

  3. ... that we begin asking for tests to include more documentation/comments on what is being tested, what the expected behaviors are, what the edge cases are, etc. With more structure using the BDD model that likely comes more naturally and we might not need more comments in the tests, but there are still nuances that are worthy of improved documentation.

  4. ... that we separate tests verifying internal behaviors from tests verifying external behavior.

Ultimately I'd like us to get to a point where we have a clearly delineated set of public API tests that other runtimes can pick up almost as is and run in their environments... a lot like we can do with the Web Platform Tests. These would be separated from the internal tests that verify specific aspects of Node.js' internals that aren't considered public API and wouldn't really be expected of other runtimes to implement in exactly the same way. To that end, I would propose eventually splitting the current test/parallel directory into two separate folders, test/parallel/public and test/parallel/internal, with the test/parallel/public being the primary set of tests other runtimes should seek to run and align with. Likewise, we'd have test/sequential/public and test/sequential/internal ... or, we can flip it around and have test/public/parallel, test/public/sequential, test/internal/parallel, test/internal/sequential. The key differentiator is that nothing in test/public would be allowed to use things like --expose-internals and would be set up only to set the documented public API surface.

Adding additional structure here obviously increases dev friction a bit, so all this needs to be carefully considered.

This is no small task. There are many thousands of individual test files that would need to be updated. So before jumping into this whole process in earnest, let's chat about it and gets some input from the contributor base.

@nodejs/tsc, @nodejs/collaborators, @nodejs/testing

Metadata

Metadata

Assignees

No one assigned

    Labels

    discussIssues opened for discussions and feedbacks.testIssues and PRs related to the tests.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions