Skip to content

Commit

Permalink
test_runner: add suite()
Browse files Browse the repository at this point in the history
This commit adds a suite() function to the test runner and makes
describe() an alias for it. This matches the it() alias for
test().

Fixes: #51430
PR-URL: #52127
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
  • Loading branch information
cjihrig authored and marco-ippolito committed May 3, 2024
1 parent bda3cde commit 41646d9
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 42 deletions.
106 changes: 69 additions & 37 deletions doc/api/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ test('top level test', async (t) => {
> between each subtest execution.
In this example, `await` is used to ensure that both subtests have completed.
This is necessary because parent tests do not wait for their subtests to
complete, unlike tests created with the `describe` and `it` syntax.
This is necessary because tests do not wait for their subtests to
complete, unlike tests created within suites.
Any subtests that are still outstanding when their parent finishes
are cancelled and treated as failures. Any subtest failures cause the parent
test to fail.
Expand Down Expand Up @@ -162,12 +162,11 @@ test('skip() method with message', (t) => {
});
```

## `describe`/`it` syntax
## `describe()` and `it()` aliases

Running tests can also be done using `describe` to declare a suite
and `it` to declare a test.
A suite is used to organize and group related tests together.
`it` is a shorthand for [`test()`][].
Suites and tests can also be written using the `describe()` and `it()`
functions. [`describe()`][] is an alias for [`suite()`][], and [`it()`][] is an
alias for [`test()`][].

```js
describe('A thing', () => {
Expand All @@ -187,7 +186,7 @@ describe('A thing', () => {
});
```

`describe` and `it` are imported from the `node:test` module.
`describe()` and `it()` are imported from the `node:test` module.

```mjs
import { describe, it } from 'node:test';
Expand Down Expand Up @@ -1200,6 +1199,51 @@ run({ files: [path.resolve('./tests/test.js')] })
.pipe(process.stdout);
```

## `suite([name][, options][, fn])`

<!-- YAML
added: REPLACEME
-->

* `name` {string} The name of the suite, which is displayed when reporting test
results. **Default:** The `name` property of `fn`, or `'<anonymous>'` if `fn`
does not have a name.
* `options` {Object} Optional configuration options for the suite.
This supports the same options as `test([name][, options][, fn])`.
* `fn` {Function|AsyncFunction} The suite function declaring nested tests and
suites. The first argument to this function is a [`SuiteContext`][] object.
**Default:** A no-op function.
* Returns: {Promise} Immediately fulfilled with `undefined`.

The `suite()` function is imported from the `node:test` module.

## `suite.skip([name][, options][, fn])`

<!-- YAML
added: REPLACEME
-->

Shorthand for skipping a suite. This is the same as
[`suite([name], { skip: true }[, fn])`][suite options].

## `suite.todo([name][, options][, fn])`

<!-- YAML
added: REPLACEME
-->

Shorthand for marking a suite as `TODO`. This is the same as
[`suite([name], { todo: true }[, fn])`][suite options].

## `suite.only([name][, options][, fn])`

<!-- YAML
added: REPLACEME
-->

Shorthand for marking a suite as `only`. This is the same as
[`suite([name], { only: true }[, fn])`][suite options].

## `test([name][, options][, fn])`

<!-- YAML
Expand Down Expand Up @@ -1251,7 +1295,7 @@ changes:
the callback function is passed as the second argument. **Default:** A no-op
function.
* Returns: {Promise} Fulfilled with `undefined` once
the test completes, or immediately if the test runs within [`describe()`][].
the test completes, or immediately if the test runs within a suite.

The `test()` function is the value imported from the `test` module. Each
invocation of this function results in reporting the test to the {TestsStream}.
Expand All @@ -1261,7 +1305,7 @@ actions related to the current test. Examples include skipping the test, adding
additional diagnostic information, or creating subtests.

`test()` returns a `Promise` that fulfills once the test completes.
if `test()` is called within a `describe()` block, it fulfills immediately.
if `test()` is called within a suite, it fulfills immediately.
The return value can usually be discarded for top level tests.
However, the return value from subtests should be used to prevent the parent
test from finishing first and cancelling the subtest
Expand Down Expand Up @@ -1302,29 +1346,18 @@ same as [`test([name], { only: true }[, fn])`][it options].

## `describe([name][, options][, fn])`

* `name` {string} The name of the suite, which is displayed when reporting test
results. **Default:** The `name` property of `fn`, or `'<anonymous>'` if `fn`
does not have a name.
* `options` {Object} Configuration options for the suite.
supports the same options as `test([name][, options][, fn])`.
* `fn` {Function|AsyncFunction} The function under suite
declaring all subtests and subsuites.
The first argument to this function is a [`SuiteContext`][] object.
**Default:** A no-op function.
* Returns: {Promise} Immediately fulfilled with `undefined`.
Alias for [`suite()`][].

The `describe()` function imported from the `node:test` module. Each
invocation of this function results in the creation of a Subtest.
After invocation of top level `describe` functions,
all top level tests and suites will execute.
The `describe()` function is imported from the `node:test` module.

## `describe.skip([name][, options][, fn])`

Shorthand for skipping a suite, same as [`describe([name], { skip: true }[, fn])`][describe options].
Shorthand for skipping a suite. This is the same as
[`describe([name], { skip: true }[, fn])`][describe options].

## `describe.todo([name][, options][, fn])`

Shorthand for marking a suite as `TODO`, same as
Shorthand for marking a suite as `TODO`. This is the same as
[`describe([name], { todo: true }[, fn])`][describe options].

## `describe.only([name][, options][, fn])`
Expand All @@ -1335,7 +1368,7 @@ added:
- v18.15.0
-->

Shorthand for marking a suite as `only`, same as
Shorthand for marking a suite as `only`. This is the same as
[`describe([name], { only: true }[, fn])`][describe options].

## `it([name][, options][, fn])`
Expand All @@ -1350,7 +1383,7 @@ changes:
description: Calling `it()` is now equivalent to calling `test()`.
-->

Shorthand for [`test()`][].
Alias for [`test()`][].

The `it()` function is imported from the `node:test` module.

Expand Down Expand Up @@ -1394,7 +1427,7 @@ added:
If unspecified, subtests inherit this value from their parent.
**Default:** `Infinity`.

This function is used to create a hook running before running a suite.
This function creates a hook that runs before executing a suite.

```js
describe('tests', async () => {
Expand Down Expand Up @@ -1424,7 +1457,7 @@ added:
If unspecified, subtests inherit this value from their parent.
**Default:** `Infinity`.

This function is used to create a hook running after running a suite.
This function creates a hook that runs after executing a suite.

```js
describe('tests', async () => {
Expand Down Expand Up @@ -1457,8 +1490,7 @@ added:
If unspecified, subtests inherit this value from their parent.
**Default:** `Infinity`.

This function is used to create a hook running
before each subtest of the current suite.
This function creates a hook that runs before each test in the current suite.

```js
describe('tests', async () => {
Expand Down Expand Up @@ -1488,11 +1520,8 @@ added:
If unspecified, subtests inherit this value from their parent.
**Default:** `Infinity`.

This function is used to create a hook running
after each subtest of the current test.

**Note:** The `afterEach` hook is guaranteed to run after every test,
even if any of the tests fail.
This function creates a hook that runs after each test in the current suite.
The `afterEach()` hook is run even if the test fails.

```js
describe('tests', async () => {
Expand Down Expand Up @@ -3054,10 +3083,13 @@ Can be used to abort test subtasks when the test has been aborted.
[`context.skip`]: #contextskipmessage
[`context.todo`]: #contexttodomessage
[`describe()`]: #describename-options-fn
[`it()`]: #itname-options-fn
[`run()`]: #runoptions
[`suite()`]: #suitename-options-fn
[`test()`]: #testname-options-fn
[describe options]: #describename-options-fn
[it options]: #testname-options-fn
[stream.compose]: stream.md#streamcomposestreams
[suite options]: #suitename-options-fn
[test reporters]: #test-reporters
[test runner execution model]: #test-runner-execution-model
3 changes: 1 addition & 2 deletions lib/internal/test_runner/harness.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,7 @@ function hook(hook) {
module.exports = {
createTestTree,
test: runInParentContext(Test),
describe: runInParentContext(Suite),
it: runInParentContext(Test),
suite: runInParentContext(Suite),
before: hook('before'),
after: hook('after'),
beforeEach: hook('beforeEach'),
Expand Down
7 changes: 4 additions & 3 deletions lib/test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';
const { ObjectAssign, ObjectDefineProperty } = primordials;
const { test, describe, it, before, after, beforeEach, afterEach } = require('internal/test_runner/harness');
const { test, suite, before, after, beforeEach, afterEach } = require('internal/test_runner/harness');
const { run } = require('internal/test_runner/runner');

module.exports = test;
Expand All @@ -9,9 +9,10 @@ ObjectAssign(module.exports, {
afterEach,
before,
beforeEach,
describe,
it,
describe: suite,
it: test,
run,
suite,
test,
});

Expand Down
8 changes: 8 additions & 0 deletions test/parallel/test-runner-aliases.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';
require('../common');
const { strictEqual } = require('node:assert');
const test = require('node:test');

strictEqual(test.test, test);
strictEqual(test.it, test);
strictEqual(test.describe, test.suite);

0 comments on commit 41646d9

Please sign in to comment.