From a5ebc896f1aec3a8852e1fc3c348c8e5488d2246 Mon Sep 17 00:00:00 2001 From: Steve Herzog Date: Tue, 14 Mar 2023 11:59:35 -0500 Subject: [PATCH] test_runner: support defining test reporter in NODE_OPTIONS Adds --test-reporter and --test-reporter-destination as allowable options in NODE_OPTIONS. Also adds the CLI flag --test-child-process to allow forcing the default test-reporter for inter-process communication. Fixes: https://github.com/nodejs/node/issues/46484 PR-URL: https://github.com/nodejs/node/pull/46688 Reviewed-By: Moshe Atlow Reviewed-By: Colin Ihrig Reviewed-By: Benjamin Gruenbaum --- doc/api/cli.md | 7 ++++++ lib/internal/test_runner/runner.js | 3 ++- lib/internal/test_runner/utils.js | 37 +++++++++++++++++++----------- src/node_options.cc | 6 +++-- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/doc/api/cli.md b/doc/api/cli.md index 8588363de7cbd7..31309254c5e3dc 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -1941,6 +1941,8 @@ Node.js options that are allowed are: * `--secure-heap` * `--snapshot-blob` * `--test-only` +* `--test-reporter-destination` +* `--test-reporter` * `--throw-deprecation` * `--title` * `--tls-cipher-list` @@ -2082,6 +2084,11 @@ If `value` equals `'1'`, the check for a supported platform is skipped during Node.js startup. Node.js might not execute correctly. Any issues encountered on unsupported platforms will not be fixed. +### `NODE_TEST_CONTEXT=value` + +If `value` equals `'child'`, test reporter options will be overridden and test +output will be sent to stdout in the TAP format. + ### `NODE_TLS_REJECT_UNAUTHORIZED=value` If `value` equals `'0'`, certificate validation is disabled for TLS connections. diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index 5b772251be981e..8b54d53a2d5a8f 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -145,6 +145,7 @@ function getRunArgs({ path, inspectPort }) { ArrayPrototypePush(argv, `--inspect-port=${getInspectPort(inspectPort)}`); } ArrayPrototypePush(argv, path); + return argv; } @@ -260,7 +261,7 @@ function runTestFile(path, root, inspectPort, filesWatcher) { const subtest = root.createSubtest(FileTest, path, async (t) => { const args = getRunArgs({ path, inspectPort }); const stdio = ['pipe', 'pipe', 'pipe']; - const env = { ...process.env }; + const env = { ...process.env, NODE_TEST_CONTEXT: 'child' }; if (filesWatcher) { stdio.push('ipc'); env.WATCH_REPORT_DEPENDENCIES = '1'; diff --git a/lib/internal/test_runner/utils.js b/lib/internal/test_runner/utils.js index 388aa6c075efd7..a5068dbf589e63 100644 --- a/lib/internal/test_runner/utils.js +++ b/lib/internal/test_runner/utils.js @@ -8,6 +8,7 @@ const { RegExpPrototypeExec, SafeMap, } = primordials; + const { basename } = require('path'); const { createWriteStream } = require('fs'); const { pathToFileURL } = require('internal/url'); @@ -166,25 +167,33 @@ function parseCommandLine() { const isTestRunner = getOptionValue('--test'); const coverage = getOptionValue('--experimental-test-coverage'); - const destinations = getOptionValue('--test-reporter-destination'); - const reporters = getOptionValue('--test-reporter'); + const isChildProcess = process.env.NODE_TEST_CONTEXT === 'child'; + let destinations; + let reporters; let testNamePatterns; let testOnlyFlag; - if (reporters.length === 0 && destinations.length === 0) { - ArrayPrototypePush(reporters, kDefaultReporter); - } + if (isChildProcess) { + reporters = [kDefaultReporter]; + destinations = [kDefaultDestination]; + } else { + destinations = getOptionValue('--test-reporter-destination'); + reporters = getOptionValue('--test-reporter'); + if (reporters.length === 0 && destinations.length === 0) { + ArrayPrototypePush(reporters, kDefaultReporter); + } - if (reporters.length === 1 && destinations.length === 0) { - ArrayPrototypePush(destinations, kDefaultDestination); - } + if (reporters.length === 1 && destinations.length === 0) { + ArrayPrototypePush(destinations, kDefaultDestination); + } - if (destinations.length !== reporters.length) { - throw new ERR_INVALID_ARG_VALUE( - '--test-reporter', - reporters, - 'must match the number of specified \'--test-reporter-destination\'', - ); + if (destinations.length !== reporters.length) { + throw new ERR_INVALID_ARG_VALUE( + '--test-reporter', + reporters, + 'must match the number of specified \'--test-reporter-destination\'', + ); + } } if (isTestRunner) { diff --git a/src/node_options.cc b/src/node_options.cc index e7b0ba1073fbb4..b8685530965c2e 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -569,10 +569,12 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { &EnvironmentOptions::test_name_pattern); AddOption("--test-reporter", "report test output using the given reporter", - &EnvironmentOptions::test_reporter); + &EnvironmentOptions::test_reporter, + kAllowedInEnvvar); AddOption("--test-reporter-destination", "report given reporter to the given destination", - &EnvironmentOptions::test_reporter_destination); + &EnvironmentOptions::test_reporter_destination, + kAllowedInEnvvar); AddOption("--test-only", "run tests with 'only' option set", &EnvironmentOptions::test_only,