From 9e8d3fbd5aa68d83c28a5df5e8dc5549cdd4cf02 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Sun, 17 Mar 2024 11:26:26 -0400 Subject: [PATCH] test_runner: add suite() 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: https://github.com/nodejs/node/issues/51430 --- doc/api/test.md | 106 +++++++++++++++++---------- lib/internal/test_runner/harness.js | 3 +- lib/test.js | 7 +- test/parallel/test-runner-aliases.js | 8 ++ 4 files changed, 82 insertions(+), 42 deletions(-) create mode 100644 test/parallel/test-runner-aliases.js diff --git a/doc/api/test.md b/doc/api/test.md index 661e357c1da528..cb386825048362 100644 --- a/doc/api/test.md +++ b/doc/api/test.md @@ -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. @@ -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', () => { @@ -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'; @@ -1204,6 +1203,51 @@ run({ files: [path.resolve('./tests/test.js')] }) .pipe(process.stdout); ``` +## `suite([name][, options][, fn])` + + + +* `name` {string} The name of the suite, which is displayed when reporting test + results. **Default:** The `name` property of `fn`, or `''` 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])` + + + +Shorthand for skipping a suite. This is the same as +[`suite([name], { skip: true }[, fn])`][suite options]. + +## `suite.todo([name][, options][, fn])` + + + +Shorthand for marking a suite as `TODO`. This is the same as +[`suite([name], { todo: true }[, fn])`][suite options]. + +## `suite.only([name][, options][, fn])` + + + +Shorthand for marking a suite as `only`. This is the same as +[`suite([name], { only: true }[, fn])`][suite options]. + ## `test([name][, options][, fn])` -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])` @@ -1358,7 +1391,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. @@ -1402,7 +1435,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 () => { @@ -1432,7 +1465,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 () => { @@ -1465,8 +1498,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 () => { @@ -1496,11 +1528,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 () => { @@ -3075,10 +3104,13 @@ Can be used to abort test subtasks when the test has been aborted. [`context.todo`]: #contexttodomessage [`describe()`]: #describename-options-fn [`glob(7)`]: https://man7.org/linux/man-pages/man7/glob.7.html +[`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 diff --git a/lib/internal/test_runner/harness.js b/lib/internal/test_runner/harness.js index 504cc1e93acd7a..d715fa7879eb16 100644 --- a/lib/internal/test_runner/harness.js +++ b/lib/internal/test_runner/harness.js @@ -282,8 +282,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'), diff --git a/lib/test.js b/lib/test.js index d096cae23d5357..1907eb7639b832 100644 --- a/lib/test.js +++ b/lib/test.js @@ -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; @@ -9,9 +9,10 @@ ObjectAssign(module.exports, { afterEach, before, beforeEach, - describe, - it, + describe: suite, + it: test, run, + suite, test, }); diff --git a/test/parallel/test-runner-aliases.js b/test/parallel/test-runner-aliases.js new file mode 100644 index 00000000000000..1a61da896e9e38 --- /dev/null +++ b/test/parallel/test-runner-aliases.js @@ -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);