nodejs / nodejs/node

Test runner with isolation=none does not work in child process

オープン
#60,020 コメント 6 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

child_process test_runner
主要言語
JavaScript
スター
122k
フォーク
37.3k
平均マージ
4日 2時間
マージ済み PR(30日)
283

説明

Version

v24.9.0

Platform
Linux home 5.15.0-153-generic #163-Ubuntu SMP Thu Aug 7 16:37:18 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Subsystem

No response

What steps will reproduce the bug?

runner.js

import cluster from 'node:cluster';
import { run } from "node:test";

if (cluster.isPrimary) {
  cluster.fork();
} else {
  const stream = run({
    isolation: "none",
  });

  stream.on("data", (data) => {
    console.log("on data", data.type);
  });

  stream.on("end", () => {
    console.log("on end")
    process.exit(0);
  });

  stream.on("error", (err) => {
    console.log("on error", err);
  });
}

dummy.test.js

import { describe, it } from "node:test";
import * as assert from "node:assert";

describe("suite", () => {
  it("works", ()  => {
    assert.ok(true);
  });
});

How often does it reproduce? Is there a required condition?

Always. No.

What is the expected behavior? Why is that the expected behavior?

With isolation: "process" (the default), here's the output:

on data test:enqueue
on data test:dequeue
on data test:enqueue
on data test:dequeue
on data test:enqueue
on data test:dequeue
on data test:complete
on data test:start
on data test:start
on data test:pass
on data test:complete
on data test:plan
on data test:pass
on data test:summary
on data test:complete
on data test:plan
on data test:diagnostic
on data test:diagnostic
on data test:diagnostic
on data test:diagnostic
on data test:diagnostic
on data test:diagnostic
on data test:diagnostic
on data test:diagnostic
on data test:summary
on end

Process finished with exit code 0

The process cleanly exits at the end of the tests.

What do you see instead?

With isolation: "none", here's the output:

on data test:enqueue
on data test:dequeue
on data test:enqueue
on data test:dequeue
on data test:complete
on data test:start
on data test:start
on data test:pass
on data test:complete
on data test:plan
on data test:pass

And the process hangs.

Additional information

The goal was to use the "cluster" module to run the tests in parallel with the shard option:

import { run } from "node:test";
import { spec } from "node:test/reporters";
import { PassThrough } from "node:stream";
import { availableParallelism } from "node:os";
import cluster from 'node:cluster';

const concurrency = availableParallelism();
let completed = 0;

if (cluster.isPrimary) {
  const mergedStream = new PassThrough({
    objectMode: true
  });

  cluster.on("message", (_worker, message) => {
    mergedStream.emit("data", message);
  });

  mergedStream
    .compose(spec)
    .pipe(process.stdout);

  for (let i = 1; i <= concurrency; i++) {
    cluster.fork({
      SHARD_INDEX: i,
      SHARD_TOTAL: concurrency,
    });
  }

  cluster.on("exit", (worker, code, signal) => {
    if (++completed === concurrency) {
      mergedStream.end();
    }
  });
} else {
  const stream = run({
    isolation: "none",
    shard: {
      index: parseInt(process.env.SHARD_INDEX, 10),
      total: parseInt(process.env.SHARD_TOTAL, 10),
    },
  });

  stream.on("data", (chunk) => {
    process.send(chunk);
  });
}

Related: https://github.com/nodejs/node/issues/55939

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

runner.js と dummy.test.js で再現から始め、cluster の子プロセスから呼び出されたときに isolation が "none" に設定される node:test の run() エントリポイントを追跡します。そのストリームのライフサイクルを、デフォルトの "process" isolation および関連する issue 55939 と比較します。子プロセスのストリームが残りのイベントを発行し、終了し、シャードのサポートを維持したまま正常に終了すれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
javascript, node.js
領域
testing-qa
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
活発
明瞭さ
おおむね明確
初心者へのやさしさ
55/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。