很多程序员最近才注意到一件事:Node.js 其实早就自带 Test Runner 了。
有人惊讶,有人质疑,还有人直接一句话否定:“这不就是个玩具吗?谁会真用它做项目测试?”
但如果你把时间线拉长,就会发现一个非常耐人寻味的现象:一个 2022 年就进入 Node 核心的功能,为什么偏偏在 2026 年开始被反复讨论?

答案并不在功能本身,而在环境变了。
Test Runner先把一个容易被误解的事实说清楚。
Node.js 的内置 Test Runner 并不是新东西,它随着 Node 18 在 2022 年就已经存在。
这三年里,它一直在那儿,不抢风头,也不争生态。
但也正因为如此,它被绝大多数人忽略了。
不是因为它不能用,而是因为当时的我们,用不到它。

回想过去几年,前端和 Node 工程的默认路径是什么?
项目一开始,就先选框架,再选测试方案:Jest、Mocha、Vitest、各种插件、各种配置。
测试被默认当成“工程体系的一部分”,而不是“代码本身的一部分”。

在那个阶段,Node 自带的测试,看起来确实太朴素了。
为什么很少人用它?我们已经习惯把“复杂”当成“专业”。
而 2026 年的现实是,越来越多的代码,已经不再走这条路线。
工具脚本、CLI、API 服务、自动化任务、AI 生成代码、一次性验证逻辑……
test('synchronous passing test', (t) => { // This test passes because it does not throw an exception. assert.strictEqual(1, 1); }); test('synchronous failing test', (t) => { // This test fails because it throws an exception. assert.strictEqual(1, 2); }); test('asynchronous passing test', async (t) => { // This test passes because the Promise returned by the async // function is settled and not rejected. assert.strictEqual(1, 1); }); test('asynchronous failing test', async (t) => { // This test fails because the Promise returned by the async // function is rejected. assert.strictEqual(1, 2); }); test('failing test using Promises', (t) => { // Promises can be used directly as well. return new Promise((resolve, reject) => { setImmediate(() => { reject(new Error('this will cause the test to fail')); }); }); }); test('callback passing test', (t, done) => { // done() is the callback function. When the setImmediate() runs, it invokes // done() with no arguments. setImmediate(done); }); test('callback failing test', (t, done) => { // When the setImmediate() runs, done() is invoked with an Error object and // the test fails. setImmediate(() => { done(new Error('callback failure')); }); });这些场景真正需要的,不是庞大的测试生态,而是快速确认代码有没有跑偏。
这时候,Node 内置 Test Runner 的价值才第一次真正显现出来。
它并不是为了取代 Jest。
它存在的意义,是把“写测试”的门槛,降到和写一个普通脚本一样低。
不用装依赖,不用配置环境,不用纠结模块体系。Node 在,测试就能跑。
这听起来很“原始”,但也恰恰是它的优势。
什么时候使用它Node.js 的 Test Runner,对中小项目、工具型项目、独立开发者来说,已经是“刚刚好”的状态。
你不需要它帮你做复杂 mock,你只关心输入和输出是不是可靠。
而这种“够用就好”的哲学,正在成为主流。
更关键的是,这个变化和 AI 有着直接关系。
当越来越多的代码由 AI 生成时,人类程序员的角色正在发生转移:从“逐行编写”,变成“快速验证”。
在这种模式下,测试不再是工程负担,而是安全带。
而 Node 内置测试,恰好适合被嵌入这种快速循环中。
这也是为什么你会看到一个明显的分化趋势:
复杂前端项目,依然会继续使用 Jest、Vitest,而后端服务、脚本工具、AI 自动化项目,开始认真考虑 Node 自带测试。
不是谁淘汰了谁,而是使用场景正在分流。
从更大的视角看,这件事还有一个更值得警惕的信号。

Node.js 正在从“运行平台”,变成“基础系统”。测试、权限、模块、运行时能力,正在被逐步内置。
'use strict'; const assert = require('node:assert'); const { mock, test } = require('node:test'); test('spies on a function', () => { const sum = mock.fn((a, b) => { return a + b; }); assert.strictEqual(sum.mock.callCount(), 0); assert.strictEqual(sum(3, 4), 7); assert.strictEqual(sum.mock.callCount(), 1); const call = sum.mock.calls[0]; assert.deepStrictEqual(call.arguments, [3, 4]); assert.strictEqual(call.result, 7); assert.strictEqual(call.error, undefined); // Reset the globally tracked mocks. mock.reset(); });当底层足够强,上层工具自然会变轻。
总结Node.js 内置 Test Runner 真正提出的问题,并不是技术选型。
而是一个更尖锐的问题:
当写测试的成本几乎为零时,你还会不会继续为“不写测试”找理由?
欢迎评论区说说你的选择。你觉得它只是个过渡方案,还是一个被低估的长期选项?
评论列表