From e97e796d14bca6016e81a4a1fd7f7cb40ada1241 Mon Sep 17 00:00:00 2001 From: Moshe Atlow Date: Fri, 17 Feb 2023 15:42:01 +0200 Subject: [PATCH] test_runner: allow nesting test within describe PR-URL: https://github.com/nodejs/node/pull/46544 Fixes: https://github.com/nodejs/node/issues/46478 Reviewed-By: Antoine du Hamel Reviewed-By: Colin Ihrig Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell --- lib/internal/test_runner/harness.js | 3 +- test/message/test_runner_describe_it.js | 17 ++-- test/message/test_runner_describe_it.out | 116 ++++++++++++----------- test/message/test_runner_output.js | 2 +- 4 files changed, 76 insertions(+), 62 deletions(-) diff --git a/lib/internal/test_runner/harness.js b/lib/internal/test_runner/harness.js index d379089e64fd92..3dec42d0c4aa9e 100644 --- a/lib/internal/test_runner/harness.js +++ b/lib/internal/test_runner/harness.js @@ -167,7 +167,8 @@ function getGlobalRoot() { } function test(name, options, fn) { - const subtest = getGlobalRoot().createSubtest(Test, name, options, fn); + const parent = testResources.get(executionAsyncId()) || getGlobalRoot(); + const subtest = parent.createSubtest(Test, name, options, fn); return subtest.start(); } diff --git a/test/message/test_runner_describe_it.js b/test/message/test_runner_describe_it.js index 510eacff9add28..7962f80fdd0c89 100644 --- a/test/message/test_runner_describe_it.js +++ b/test/message/test_runner_describe_it.js @@ -2,7 +2,7 @@ 'use strict'; require('../common'); const assert = require('node:assert'); -const { describe, it } = require('node:test'); +const { describe, it, test } = require('node:test'); const util = require('util'); @@ -41,6 +41,8 @@ it('async pass', async () => { }); +test('mixing describe/it and test should work', () => {}); + it('async throw fail', async () => { throw new Error('thrown from async throw fail'); }); @@ -95,6 +97,7 @@ describe('subtest sync throw fail', () => { it('+sync throw fail', () => { throw new Error('thrown from subtest sync throw fail'); }); + test('mixing describe/it and test should work', () => {}); }); it('sync throw non-error fail', async () => { @@ -106,7 +109,7 @@ describe('level 0a', { concurrency: 4 }, () => { const p1a = new Promise((resolve) => { setTimeout(() => { resolve(); - }, 1000); + }, 100); }); return p1a; @@ -124,7 +127,7 @@ describe('level 0a', { concurrency: 4 }, () => { const p1c = new Promise((resolve) => { setTimeout(() => { resolve(); - }, 2000); + }, 200); }); return p1c; @@ -134,7 +137,7 @@ describe('level 0a', { concurrency: 4 }, () => { const p1c = new Promise((resolve) => { setTimeout(() => { resolve(); - }, 1500); + }, 150); }); return p1c; @@ -143,7 +146,7 @@ describe('level 0a', { concurrency: 4 }, () => { const p0a = new Promise((resolve) => { setTimeout(() => { resolve(); - }, 3000); + }, 300); }); return p0a; @@ -309,12 +312,12 @@ describe('describe async throw fails', async () => { describe('timeouts', () => { it('timed out async test', { timeout: 5 }, async () => { return new Promise((resolve) => { - setTimeout(resolve, 1000); + setTimeout(resolve, 100); }); }); it('timed out callback test', { timeout: 5 }, (done) => { - setTimeout(done, 1000); + setTimeout(done, 100); }); diff --git a/test/message/test_runner_describe_it.out b/test/message/test_runner_describe_it.out index 87207aca71fafa..2de7664bd24d1a 100644 --- a/test/message/test_runner_describe_it.out +++ b/test/message/test_runner_describe_it.out @@ -82,8 +82,13 @@ ok 10 - async pass --- duration_ms: * ... +# Subtest: mixing describe/it and test should work +ok 11 - mixing describe/it and test should work + --- + duration_ms: * + ... # Subtest: async throw fail -not ok 11 - async throw fail +not ok 12 - async throw fail --- duration_ms: * failureType: 'testCodeFailure' @@ -99,7 +104,7 @@ not ok 11 - async throw fail * ... # Subtest: async skip fail -not ok 12 - async skip fail +not ok 13 - async skip fail --- duration_ms: * failureType: 'callbackAndPromisePresent' @@ -107,7 +112,7 @@ not ok 12 - async skip fail code: 'ERR_TEST_FAILURE' ... # Subtest: async assertion fail -not ok 13 - async assertion fail +not ok 14 - async assertion fail --- duration_ms: * failureType: 'testCodeFailure' @@ -130,12 +135,12 @@ not ok 13 - async assertion fail * ... # Subtest: resolve pass -ok 14 - resolve pass +ok 15 - resolve pass --- duration_ms: * ... # Subtest: reject fail -not ok 15 - reject fail +not ok 16 - reject fail --- duration_ms: * failureType: 'testCodeFailure' @@ -151,27 +156,27 @@ not ok 15 - reject fail * ... # Subtest: unhandled rejection - passes but warns -ok 16 - unhandled rejection - passes but warns +ok 17 - unhandled rejection - passes but warns --- duration_ms: * ... # Subtest: async unhandled rejection - passes but warns -ok 17 - async unhandled rejection - passes but warns +ok 18 - async unhandled rejection - passes but warns --- duration_ms: * ... # Subtest: immediate throw - passes but warns -ok 18 - immediate throw - passes but warns +ok 19 - immediate throw - passes but warns --- duration_ms: * ... # Subtest: immediate reject - passes but warns -ok 19 - immediate reject - passes but warns +ok 20 - immediate reject - passes but warns --- duration_ms: * ... # Subtest: immediate resolve pass -ok 20 - immediate resolve pass +ok 21 - immediate resolve pass --- duration_ms: * ... @@ -195,8 +200,13 @@ ok 20 - immediate resolve pass * * ... - 1..1 -not ok 21 - subtest sync throw fail + # Subtest: mixing describe/it and test should work + ok 2 - mixing describe/it and test should work + --- + duration_ms: * + ... + 1..2 +not ok 22 - subtest sync throw fail --- duration_ms: * failureType: 'subtestsFailed' @@ -204,7 +214,7 @@ not ok 21 - subtest sync throw fail code: 'ERR_TEST_FAILURE' ... # Subtest: sync throw non-error fail -not ok 22 - sync throw non-error fail +not ok 23 - sync throw non-error fail --- duration_ms: * failureType: 'testCodeFailure' @@ -233,27 +243,27 @@ not ok 22 - sync throw non-error fail duration_ms: * ... 1..4 -ok 23 - level 0a +ok 24 - level 0a --- duration_ms: * ... # Subtest: invalid subtest - pass but subtest fails -ok 24 - invalid subtest - pass but subtest fails +ok 25 - invalid subtest - pass but subtest fails --- duration_ms: * ... # Subtest: sync skip option -ok 25 - sync skip option # SKIP +ok 26 - sync skip option # SKIP --- duration_ms: * ... # Subtest: sync skip option with message -ok 26 - sync skip option with message # SKIP this is skipped +ok 27 - sync skip option with message # SKIP this is skipped --- duration_ms: * ... # Subtest: sync skip option is false fail -not ok 27 - sync skip option is false fail +not ok 28 - sync skip option is false fail --- duration_ms: * failureType: 'testCodeFailure' @@ -269,67 +279,67 @@ not ok 27 - sync skip option is false fail * ... # Subtest: -ok 28 - +ok 29 - --- duration_ms: * ... # Subtest: functionOnly -ok 29 - functionOnly +ok 30 - functionOnly --- duration_ms: * ... # Subtest: -ok 30 - +ok 31 - --- duration_ms: * ... # Subtest: test with only a name provided -ok 31 - test with only a name provided +ok 32 - test with only a name provided --- duration_ms: * ... # Subtest: -ok 32 - +ok 33 - --- duration_ms: * ... # Subtest: -ok 33 - # SKIP +ok 34 - # SKIP --- duration_ms: * ... # Subtest: test with a name and options provided -ok 34 - test with a name and options provided # SKIP +ok 35 - test with a name and options provided # SKIP --- duration_ms: * ... # Subtest: functionAndOptions -ok 35 - functionAndOptions # SKIP +ok 36 - functionAndOptions # SKIP --- duration_ms: * ... # Subtest: escaped description \\ \# \\\#\\ -ok 36 - escaped description \\ \# \\\#\\ +ok 37 - escaped description \\ \# \\\#\\ --- duration_ms: * ... # Subtest: escaped skip message -ok 37 - escaped skip message # SKIP \#skip +ok 38 - escaped skip message # SKIP \#skip --- duration_ms: * ... # Subtest: escaped todo message -ok 38 - escaped todo message # TODO \#todo +ok 39 - escaped todo message # TODO \#todo --- duration_ms: * ... # Subtest: callback pass -ok 39 - callback pass +ok 40 - callback pass --- duration_ms: * ... # Subtest: callback fail -not ok 40 - callback fail +not ok 41 - callback fail --- duration_ms: * failureType: 'testCodeFailure' @@ -340,22 +350,22 @@ not ok 40 - callback fail * ... # Subtest: sync t is this in test -ok 41 - sync t is this in test +ok 42 - sync t is this in test --- duration_ms: * ... # Subtest: async t is this in test -ok 42 - async t is this in test +ok 43 - async t is this in test --- duration_ms: * ... # Subtest: callback t is this in test -ok 43 - callback t is this in test +ok 44 - callback t is this in test --- duration_ms: * ... # Subtest: callback also returns a Promise -not ok 44 - callback also returns a Promise +not ok 45 - callback also returns a Promise --- duration_ms: * failureType: 'callbackAndPromisePresent' @@ -363,7 +373,7 @@ not ok 44 - callback also returns a Promise code: 'ERR_TEST_FAILURE' ... # Subtest: callback throw -not ok 45 - callback throw +not ok 46 - callback throw --- duration_ms: * failureType: 'testCodeFailure' @@ -379,7 +389,7 @@ not ok 45 - callback throw * ... # Subtest: callback called twice -not ok 46 - callback called twice +not ok 47 - callback called twice --- duration_ms: * failureType: 'multipleCallbackInvocations' @@ -390,12 +400,12 @@ not ok 46 - callback called twice * ... # Subtest: callback called twice in different ticks -ok 47 - callback called twice in different ticks +ok 48 - callback called twice in different ticks --- duration_ms: * ... # Subtest: callback called twice in future tick -not ok 48 - callback called twice in future tick +not ok 49 - callback called twice in future tick --- duration_ms: * failureType: 'uncaughtException' @@ -405,7 +415,7 @@ not ok 48 - callback called twice in future tick * ... # Subtest: callback async throw -not ok 49 - callback async throw +not ok 50 - callback async throw --- duration_ms: * failureType: 'uncaughtException' @@ -416,12 +426,12 @@ not ok 49 - callback async throw * ... # Subtest: callback async throw after done -ok 50 - callback async throw after done +ok 51 - callback async throw after done --- duration_ms: * ... # Subtest: custom inspect symbol fail -not ok 51 - custom inspect symbol fail +not ok 52 - custom inspect symbol fail --- duration_ms: * failureType: 'testCodeFailure' @@ -429,7 +439,7 @@ not ok 51 - custom inspect symbol fail code: 'ERR_TEST_FAILURE' ... # Subtest: custom inspect symbol that throws fail -not ok 52 - custom inspect symbol that throws fail +not ok 53 - custom inspect symbol that throws fail --- duration_ms: * failureType: 'testCodeFailure' @@ -480,7 +490,7 @@ not ok 52 - custom inspect symbol that throws fail * ... 1..2 -not ok 53 - subtest sync throw fails +not ok 54 - subtest sync throw fails --- duration_ms: * failureType: 'subtestsFailed' @@ -497,7 +507,7 @@ not ok 53 - subtest sync throw fails code: 'ERR_TEST_FAILURE' ... 1..1 -not ok 54 - describe sync throw fails +not ok 55 - describe sync throw fails --- duration_ms: * failureType: 'testCodeFailure' @@ -525,7 +535,7 @@ not ok 54 - describe sync throw fails code: 'ERR_TEST_FAILURE' ... 1..1 -not ok 55 - describe async throw fails +not ok 56 - describe async throw fails --- duration_ms: * failureType: 'testCodeFailure' @@ -573,7 +583,7 @@ not ok 55 - describe async throw fails duration_ms: * ... 1..4 -not ok 56 - timeouts +not ok 57 - timeouts --- duration_ms: * failureType: 'subtestsFailed' @@ -598,7 +608,7 @@ not ok 56 - timeouts * ... 1..2 -not ok 57 - successful thenable +not ok 58 - successful thenable --- duration_ms: * failureType: 'subtestsFailed' @@ -606,7 +616,7 @@ not ok 57 - successful thenable code: 'ERR_TEST_FAILURE' ... # Subtest: rejected thenable -not ok 58 - rejected thenable +not ok 59 - rejected thenable --- duration_ms: * failureType: 'testCodeFailure' @@ -616,7 +626,7 @@ not ok 58 - rejected thenable * ... # Subtest: invalid subtest fail -not ok 59 - invalid subtest fail +not ok 60 - invalid subtest fail --- duration_ms: * failureType: 'parentAlreadyFinished' @@ -625,15 +635,15 @@ not ok 59 - invalid subtest fail stack: |- * ... -1..59 +1..60 # Warning: Test "unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event. # Warning: Test "async unhandled rejection - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from async unhandled rejection fail" and would have caused the test to fail, but instead triggered an unhandledRejection event. # Warning: Test "immediate throw - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from immediate throw fail" and would have caused the test to fail, but instead triggered an uncaughtException event. # Warning: Test "immediate reject - passes but warns" generated asynchronous activity after the test ended. This activity created the error "Error: rejected from immediate reject fail" and would have caused the test to fail, but instead triggered an unhandledRejection event. # Warning: Test "callback called twice in different ticks" generated asynchronous activity after the test ended. This activity created the error "Error [ERR_TEST_FAILURE]: callback invoked multiple times" and would have caused the test to fail, but instead triggered an uncaughtException event. # Warning: Test "callback async throw after done" generated asynchronous activity after the test ended. This activity created the error "Error: thrown from callback async throw after done" and would have caused the test to fail, but instead triggered an uncaughtException event. -# tests 59 -# pass 22 +# tests 60 +# pass 23 # fail 23 # cancelled 0 # skipped 9 diff --git a/test/message/test_runner_output.js b/test/message/test_runner_output.js index 91caca3038e7b8..593f069d8f4606 100644 --- a/test/message/test_runner_output.js +++ b/test/message/test_runner_output.js @@ -119,7 +119,7 @@ test('level 0a', { concurrency: 4 }, async (t) => { return p1a; }); - t.test('level 1b', async (t) => { + test('level 1b', async (t) => { const p1b = new Promise((resolve) => { resolve(); });