From c2fde1903c4a53a2259358ba557f70807e79e493 Mon Sep 17 00:00:00 2001 From: greenhead Date: Wed, 26 Aug 2026 00:33:22 +0900 Subject: [PATCH 1/2] test: use common spawnSync helpers in more tests The helpers report the command, both streams, and the exit condition on failure, so mismatches are diagnosed consistently across tests. Signed-off-by: greenhead --- test/message/node_run_list.js | 7 ++- test/parallel/test-common-wpt-backends.js | 4 +- test/parallel/test-fs-glob.mjs | 5 +- .../test-module-unreadable-package-json.js | 10 ++-- test/parallel/test-runner-cli.js | 19 ++++---- ...test-runner-coverage-default-exclusion.mjs | 48 ++++++++++--------- .../test-runner-coverage-thresholds.js | 26 +++++----- test/pseudo-tty/test-set-raw-mode-modes.js | 5 +- 8 files changed, 63 insertions(+), 61 deletions(-) diff --git a/test/message/node_run_list.js b/test/message/node_run_list.js index aef49734615d..24cb5656e285 100644 --- a/test/message/node_run_list.js +++ b/test/message/node_run_list.js @@ -1,14 +1,13 @@ 'use strict'; require('../common'); -const assert = require('node:assert/strict'); -const childProcess = require('node:child_process'); +const { spawnSyncAndExit } = require('../common/child_process'); const fixtures = require('../common/fixtures'); -const child = childProcess.spawnSync( +const { child } = spawnSyncAndExit( process.execPath, [ '--no-warnings', '--run'], { cwd: fixtures.path('run-script'), encoding: 'utf8' }, + { status: 9, signal: null }, ); -assert.strictEqual(child.status, 9); console.log(child.stderr); diff --git a/test/parallel/test-common-wpt-backends.js b/test/parallel/test-common-wpt-backends.js index 10aa619bc8d5..7808615ef15e 100644 --- a/test/parallel/test-common-wpt-backends.js +++ b/test/parallel/test-common-wpt-backends.js @@ -10,6 +10,7 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); const { spawnSync } = require('child_process'); +const { spawnSyncAndExitWithoutError } = require('../common/child_process'); const { backends, WPTRunner } = require('../common/wpt'); const queueProbe = process.env.NODE_TEST_WPT_QUEUE_PROBE === '1'; @@ -105,12 +106,11 @@ async function compare(throws) { // End to end: the runner's own reporting has to match too. The webidl spec // reports an uncaught error whose name the status file matches on. function runDriver(driver, spec, backend) { - const { status, stdout, stderr } = spawnSync( + const { child: { stdout } } = spawnSyncAndExitWithoutError( process.execPath, [path.join(__dirname, '../wpt', driver), spec], { env: { ...process.env, WPT_BACKEND: backend }, encoding: 'utf8' }, ); - assert.strictEqual(status, 0, `${spec} failed on the ${backend} backend:\n${stdout}${stderr}`); // Specs run concurrently, so the lines arrive in an arbitrary order. return stdout.split('\n').filter((line) => line.startsWith('[')).sort(); } diff --git a/test/parallel/test-fs-glob.mjs b/test/parallel/test-fs-glob.mjs index 9226e491358d..39d1cd07576d 100644 --- a/test/parallel/test-fs-glob.mjs +++ b/test/parallel/test-fs-glob.mjs @@ -1,6 +1,6 @@ import * as common from '../common/index.mjs'; import tmpdir from '../common/tmpdir.js'; -import { spawnSync } from 'node:child_process'; +import { spawnSyncAndExitWithoutError } from '../common/child_process.js'; import { resolve, dirname, sep, relative, join, isAbsolute } from 'node:path'; import { mkdir, writeFile, symlink, glob as asyncGlob } from 'node:fs/promises'; import { glob, globSync, Dirent, chmodSync, writeFileSync, rmSync } from 'node:fs'; @@ -737,11 +737,10 @@ describe('glob - seen cache', function() { `; const seenDir = tmpdir.resolve('glob-seen'); - const child = spawnSync( + spawnSyncAndExitWithoutError( process.execPath, ['--expose-internals', '-e', script, seenDir], { encoding: 'utf8' }, ); - assert.strictEqual(child.status, 0, child.stderr || child.stdout); }); }); diff --git a/test/parallel/test-module-unreadable-package-json.js b/test/parallel/test-module-unreadable-package-json.js index 4261dad85580..7de221612d9d 100644 --- a/test/parallel/test-module-unreadable-package-json.js +++ b/test/parallel/test-module-unreadable-package-json.js @@ -18,6 +18,7 @@ const assert = require('assert'); const fs = require('fs'); const path = require('path'); const { spawnSync } = require('child_process'); +const { spawnSyncAndAssert } = require('../common/child_process'); const tmpdir = require('../common/tmpdir'); tmpdir.refresh(); @@ -38,11 +39,10 @@ const entry = tmpdir.resolve('main.mjs'); fs.writeFileSync(entry, 'import { which } from "dep"; console.log(which);'); // Sanity check: the export resolves while the package config is readable. -{ - const child = spawnSync(process.execPath, [entry], { encoding: 'utf8' }); - assert.strictEqual(child.stdout.trim(), 'real'); - assert.strictEqual(child.status, 0, child.stderr); -} +spawnSyncAndAssert(process.execPath, [entry], { encoding: 'utf8' }, { + stdout: 'real', + trim: true, +}); fs.chmodSync(depPackageJson, 0o000); diff --git a/test/parallel/test-runner-cli.js b/test/parallel/test-runner-cli.js index 0702c5c1500c..5a5e6b9bdf11 100644 --- a/test/parallel/test-runner-cli.js +++ b/test/parallel/test-runner-cli.js @@ -3,6 +3,7 @@ require('../common'); const assert = require('assert'); const { spawnSync } = require('child_process'); +const { spawnSyncAndAssert } = require('../common/child_process'); const { join } = require('path'); const fixtures = require('../common/fixtures'); const testFixtures = fixtures.path('test-runner'); @@ -70,16 +71,14 @@ for (const isolation of ['none', 'process']) { const args = ['--test', '--test-reporter=tap', '--no-experimental-strip-types', `--test-isolation=${isolation}`, dir]; - const child = spawnSync(process.execPath, args, { cwd: testFixtures }); - - assert.strictEqual(child.status, 0); - assert.strictEqual(child.signal, null); - assert.strictEqual(child.stderr.toString(), ''); - const stdout = child.stdout.toString(); - - assert.match(stdout, /ok 1 - this should pass/); - assert.match(stdout, /ok 2 - this should pass/); - assert.match(stdout, /ok 3 - this should pass/); + spawnSyncAndAssert(process.execPath, args, { cwd: testFixtures }, { + stderr: '', + stdout(output) { + assert.match(output, /ok 1 - this should pass/); + assert.match(output, /ok 2 - this should pass/); + assert.match(output, /ok 3 - this should pass/); + }, + }); } } diff --git a/test/parallel/test-runner-coverage-default-exclusion.mjs b/test/parallel/test-runner-coverage-default-exclusion.mjs index f6080612a37c..8ce72ecbe6ad 100644 --- a/test/parallel/test-runner-coverage-default-exclusion.mjs +++ b/test/parallel/test-runner-coverage-default-exclusion.mjs @@ -1,10 +1,10 @@ import '../common/index.mjs'; import { before, describe, it } from 'node:test'; import assert from 'node:assert'; -import { spawnSync } from 'node:child_process'; import { cp } from 'node:fs/promises'; import tmpdir from '../common/tmpdir.js'; import fixtures from '../common/fixtures.js'; +import { spawnSyncAndAssert } from '../common/child_process.js'; const skipIfNoInspector = { skip: !process.features.inspector ? 'inspector disabled' : false }; @@ -57,14 +57,15 @@ describe('test runner coverage default exclusion', skipIfNoInspector, () => { '--test-reporter=tap', '--no-experimental-strip-types', ]; - const result = spawnSync(process.execPath, args, { + spawnSyncAndAssert(process.execPath, args, { env: { ...process.env, NODE_TEST_TMPDIR: tmpdir.path }, cwd: tmpdir.path + }, { + stderr: '', + stdout(output) { + assert(output.includes(report)); + }, }); - - assert.strictEqual(result.stderr.toString(), ''); - assert(result.stdout.toString().includes(report)); - assert.strictEqual(result.status, 0); }); it('should exclude test files from coverage by default', async () => { @@ -74,14 +75,15 @@ describe('test runner coverage default exclusion', skipIfNoInspector, () => { '--experimental-test-coverage', '--test-reporter=tap', ]; - const result = spawnSync(process.execPath, args, { + spawnSyncAndAssert(process.execPath, args, { env: { ...process.env, NODE_TEST_TMPDIR: tmpdir.path }, cwd: tmpdir.path + }, { + stderr: '', + stdout(output) { + assertDefaultExclusions(output); + }, }); - - assert.strictEqual(result.stderr.toString(), ''); - assertDefaultExclusions(result.stdout.toString()); - assert.strictEqual(result.status, 0); }); it('should exclude ts test files', async () => { @@ -91,14 +93,15 @@ describe('test runner coverage default exclusion', skipIfNoInspector, () => { '--disable-warning=ExperimentalWarning', '--test-reporter=tap', ]; - const result = spawnSync(process.execPath, args, { + spawnSyncAndAssert(process.execPath, args, { env: { ...process.env, NODE_TEST_TMPDIR: tmpdir.path }, cwd: tmpdir.path + }, { + stderr: '', + stdout(output) { + assertDefaultExclusions(output); + }, }); - - assert.strictEqual(result.stderr.toString(), ''); - assertDefaultExclusions(result.stdout.toString()); - assert.strictEqual(result.status, 0); }); it('should exclude dotfile test files from coverage by default', async () => { @@ -109,14 +112,15 @@ describe('test runner coverage default exclusion', skipIfNoInspector, () => { '--test-reporter=tap', 'test/.dotfile.cjs', ]; - const result = spawnSync(process.execPath, args, { + spawnSyncAndAssert(process.execPath, args, { env: { ...process.env, NODE_TEST_TMPDIR: tmpdir.path }, cwd: tmpdir.path + }, { + stderr: '', + stdout(output) { + assertDefaultExclusions(output); + assert.doesNotMatch(output, /#\s+\.dotfile\.cjs\s+\|/); + }, }); - - assert.strictEqual(result.stderr.toString(), ''); - assertDefaultExclusions(result.stdout.toString()); - assert.doesNotMatch(result.stdout.toString(), /#\s+\.dotfile\.cjs\s+\|/); - assert.strictEqual(result.status, 0); }); }); diff --git a/test/parallel/test-runner-coverage-thresholds.js b/test/parallel/test-runner-coverage-thresholds.js index 2742464adf64..20738c54386d 100644 --- a/test/parallel/test-runner-coverage-thresholds.js +++ b/test/parallel/test-runner-coverage-thresholds.js @@ -2,6 +2,7 @@ const common = require('../common'); const assert = require('node:assert'); const { spawnSync } = require('node:child_process'); +const { spawnSyncAndExit } = require('../common/child_process'); const { readdirSync } = require('node:fs'); const { test } = require('node:test'); const fixtures = require('../common/fixtures'); @@ -172,23 +173,24 @@ for (const coverage of coverages) { }); test(`test failing ${coverage.flag} with dot reporter`, () => { - const result = spawnSync(process.execPath, [ + const { child } = spawnSyncAndExit(process.execPath, [ '--test', '--experimental-test-coverage', '--test-coverage-exclude=!test/**', `${coverage.flag}=99`, '--test-reporter', 'dot', fixture, - ]); - - const stdout = result.stdout.toString(); - assert.match( - stdout, - RegExp(`Error: ${coverage.actual.toFixed(2)}% ${coverage.name} coverage does not meet threshold of 99%`) - ); - assert.match(stdout, /start of coverage report/); - assert.match(stdout, /end of coverage report/); - assert.strictEqual(result.status, 1); - assert(!findCoverageFileForPid(result.pid)); + ], { + status: 1, + stdout(output) { + assert.match( + output, + RegExp(`Error: ${coverage.actual.toFixed(2)}% ${coverage.name} coverage does not meet threshold of 99%`) + ); + assert.match(output, /start of coverage report/); + assert.match(output, /end of coverage report/); + }, + }); + assert(!findCoverageFileForPid(child.pid)); }); } diff --git a/test/pseudo-tty/test-set-raw-mode-modes.js b/test/pseudo-tty/test-set-raw-mode-modes.js index 8280aacb0a85..fa11b25f3c1c 100644 --- a/test/pseudo-tty/test-set-raw-mode-modes.js +++ b/test/pseudo-tty/test-set-raw-mode-modes.js @@ -1,15 +1,14 @@ 'use strict'; require('../common'); const assert = require('assert'); -const { spawnSync } = require('child_process'); +const { spawnSyncAndExitWithoutError } = require('../common/child_process'); function isOnlcrEnabled() { - const { stdout, stderr, status } = spawnSync('stty', ['-a'], { + const { child: { stdout } } = spawnSyncAndExitWithoutError('stty', ['-a'], { encoding: 'utf8', stdio: ['inherit', 'pipe', 'pipe'], }); - assert.strictEqual(status, 0, stderr); return /(?:^|[\s;])onlcr(?:[\s;]|$)/.test(stdout); } From 40307b29bf6dd78e649a88ba0457f5a55445097e Mon Sep 17 00:00:00 2001 From: greenhead Date: Thu, 27 Aug 2026 00:26:23 +0900 Subject: [PATCH 2/2] fixup! test: use common spawnSync helpers in more tests Signed-off-by: greenhead --- .../test-runner-coverage-default-exclusion.mjs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/test/parallel/test-runner-coverage-default-exclusion.mjs b/test/parallel/test-runner-coverage-default-exclusion.mjs index 8ce72ecbe6ad..acc8c3bbfe96 100644 --- a/test/parallel/test-runner-coverage-default-exclusion.mjs +++ b/test/parallel/test-runner-coverage-default-exclusion.mjs @@ -62,9 +62,7 @@ describe('test runner coverage default exclusion', skipIfNoInspector, () => { cwd: tmpdir.path }, { stderr: '', - stdout(output) { - assert(output.includes(report)); - }, + stdout: new RegExp(RegExp.escape(report)), }); }); @@ -80,9 +78,7 @@ describe('test runner coverage default exclusion', skipIfNoInspector, () => { cwd: tmpdir.path }, { stderr: '', - stdout(output) { - assertDefaultExclusions(output); - }, + stdout: assertDefaultExclusions, }); }); @@ -98,9 +94,7 @@ describe('test runner coverage default exclusion', skipIfNoInspector, () => { cwd: tmpdir.path }, { stderr: '', - stdout(output) { - assertDefaultExclusions(output); - }, + stdout: assertDefaultExclusions, }); });