From a170ee0c62eb3e306fd13d6d2d42ec14bdbcf0fb Mon Sep 17 00:00:00 2001 From: Edy Silva Date: Mon, 16 Mar 2026 13:56:41 -0300 Subject: [PATCH 1/2] test_runner: set non-zero exit code when suite errors occur --- lib/internal/test_runner/utils.js | 3 +++ test/fixtures/test-runner/describe_error.js | 10 ++++++++++ test/parallel/test-runner-exit-code.js | 8 ++++++++ 3 files changed, 21 insertions(+) create mode 100644 test/fixtures/test-runner/describe_error.js diff --git a/lib/internal/test_runner/utils.js b/lib/internal/test_runner/utils.js index 5b53342933cdcb..db7e2ee50dd8d6 100644 --- a/lib/internal/test_runner/utils.js +++ b/lib/internal/test_runner/utils.js @@ -384,6 +384,9 @@ function countCompletedTest(test, harness = test.root.harness) { } if (test.reportedType === 'suite') { harness.counters.suites++; + if (!test.passed) { + harness.success = false; + } return; } // Check SKIP and TODO tests first, as those should not be counted as diff --git a/test/fixtures/test-runner/describe_error.js b/test/fixtures/test-runner/describe_error.js new file mode 100644 index 00000000000000..6d0d933a704268 --- /dev/null +++ b/test/fixtures/test-runner/describe_error.js @@ -0,0 +1,10 @@ +'use strict'; +const { describe, it } = require('node:test'); + +describe('should fail', () => { + throw new Error('error in describe'); +}); + +describe('should pass', () => { + it('ok', () => {}); +}); \ No newline at end of file diff --git a/test/parallel/test-runner-exit-code.js b/test/parallel/test-runner-exit-code.js index 4024a52841bb28..c25becee3f708f 100644 --- a/test/parallel/test-runner-exit-code.js +++ b/test/parallel/test-runner-exit-code.js @@ -70,6 +70,14 @@ if (process.argv[2] === 'child') { assert.strictEqual(child.status, 1); assert.strictEqual(child.signal, null); + // An error thrown inside describe() should cause a non-zero exit code. + child = spawnSync(process.execPath, [ + '--test', + fixtures.path('test-runner', 'describe_error.js'), + ]); + assert.strictEqual(child.status, 1); + assert.strictEqual(child.signal, null); + // With process isolation (default), the test name shown is the file path // because the parent runner only knows about file-level tests const neverEndingSync = fixtures.path('test-runner', 'never_ending_sync.js'); From 4328ac80007a3a676ff555f5b9582a13d8881a4c Mon Sep 17 00:00:00 2001 From: Edy Silva Date: Mon, 16 Mar 2026 13:59:28 -0300 Subject: [PATCH 2/2] add missing newline --- test/fixtures/test-runner/describe_error.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fixtures/test-runner/describe_error.js b/test/fixtures/test-runner/describe_error.js index 6d0d933a704268..04e9d1faa042d1 100644 --- a/test/fixtures/test-runner/describe_error.js +++ b/test/fixtures/test-runner/describe_error.js @@ -7,4 +7,4 @@ describe('should fail', () => { describe('should pass', () => { it('ok', () => {}); -}); \ No newline at end of file +});