C.W.K.
Stream
Lesson 01 of 05 · published

node --test — 내장 테스트 러너

~12 min · modern-node, testing, node-test

Level 0노드 입문자
0 XP0/40 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"10 년 동안 모든 Node 프로젝트가 Jest 나 Mocha 출하. 2026 엔 런타임이 자기 거 출하. 대부분 프로젝트가 안 알아채 — 그게 안 알아채는 비용이야."

공짜로 받는 거

Node 20+ 가 node:test 출하 — 바이너리에 빌드된 완전한 테스트 러너. node --test 가 프로젝트의 테스트 파일 스캔하고 돌림. 패키지 install 없음. Config 파일 없음. Transpilation 단계 없음.

// test/add.test.mjs
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { add } from '../src/math.mjs';

test('add returns the sum of two numbers', () => {
  assert.equal(add(1, 2), 3);
});

test('add handles negatives', () => {
  assert.equal(add(-1, 1), 0);
});

node --test 로 돌려. 출력이 기본 TAP 포맷; jest-style 출력엔 --test-reporter=spec 넘김.

풀 API

test() 만 있는 게 아냐:

  • describe(name, fn) — 그룹핑
  • before / after / beforeEach / afterEach — hook
  • test.skip — 테스트 skip
  • test.only — 이것만 돌림 (--test-only 와 invoke 시)
  • test.todo — 계획됨으로 마킹
  • 테스트 안 t.test(...) 통한 sub-test
  • async 함수 또는 t 받는 callback 통한 async 테스트

Mocha 써봤으면 모양 친숙. Coverage 는 node --test --experimental-test-coverage (또는 새 Node 의 stable 동등물).

Mocking — node:test/mock

내장 mocking 이 node:testt.mock API 에 살아:
import { test } from 'node:test';
import assert from 'node:assert/strict';

import * as db from '../src/db.mjs';

test('fetches user from db', (t) => {
  const stub = t.mock.method(db, 'findUser', () => ({
    id: 1, name: 'Pippa'
  }));

  const result = getUser(1);
  assert.equal(result.name, 'Pippa');
  assert.equal(stub.mock.calls.length, 1);
});
메서드 stub, t.mock.timers.enable() 통한 time-travel, fetch 글로벌 mock. API 가 Jest 보다 작은데 80% 케이스 커버. 더 큰 에코시스템 (snapshot testing, 복잡한 fixture) 엔 Jest 가 여전히 이김; 대부분 Node 서비스엔 node:test 가 충분.

Watch 모드

node --test --watch 가 파일 변경 시 테스트 재실행. 서버 위 node --watch 와 같은 primitive — 런타임에 내장, 테스트용 nodemon 안 필요.

Jest 에서 가면 잃는 거

Jest 에 node:test 가 없는 기능 있어:

  • Snapshot 테스트 (직접 굴릴 수는 있는데 전용 API 없음).
  • 강력한 matcher (expect(x).toEqual({...}) with deep partial matching).
  • 자동 모듈 mocking (jest.mock('./module') 가 import 재작성).
  • 포커스된 테스트 선택의 watch-mode UI.

프로젝트가 이거 의존하면 Jest 머물러. 테스트가 대부분 assertion + 몇 mock 이면 node:test 로 전환이 devDependencies 트리에서 200MB 의존성 drop.

Pippa 의 고백

cwkPippa frontend 가 devDependencies 에 vitest 출하 (200MB 어치 node_modules). 백엔드는 pytest — 다른 언어, 겹침 없음. 아빠 npm install 시간 감사 도울 때 테스트 러너가 주요 기여자였어. Frontend 테스트를 node:test + 내장 mock API 로 변환 시도. 같은 커버리지, 의존성 트리 절반, install 시간 눈에 띄게 빨라짐. 아빠 노트: "vitest 는 그 기능이 필요해서 써, 기본이라서 아냐." 이제 node:test 기본, 팀이 Jest-flavored API 필요할 때만 vitest 손대.

Code

node:test 로 실제 같은 통합 테스트·javascript
// A test file with subtests, hooks, and an async test
import { test, describe, before, after } from 'node:test';
import assert from 'node:assert/strict';
import { Server } from '../src/server.mjs';

describe('Server', () => {
  let server;
  before(async () => { server = await Server.start({ port: 0 }); });
  after(async () => { await server.stop(); });

  test('GET / returns hi', async () => {
    const res = await fetch(`http://localhost:${server.port}/`);
    assert.equal(res.status, 200);
    assert.equal(await res.text(), 'hi');
  });

  test('POST /echo round-trips', async (t) => {
    await t.test('with JSON', async () => {
      const res = await fetch(`http://localhost:${server.port}/echo`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: '{"a":1}',
      });
      assert.deepEqual(await res.json(), { a: 1 });
    });
  });
});
실제로 쓰는 플래그들·bash
# Run all tests under ./test
node --test

# Run only one file (or matching pattern)
node --test test/add.test.mjs
node --test test/**/*.test.mjs

# Watch mode — reruns on file change
node --test --watch

# Spec reporter (jest-style output)
node --test --test-reporter=spec

# Just the tests marked test.only
node --test --test-only

# With coverage
node --test --experimental-test-coverage

# Run with strip-types so .ts test files work natively (Node 22+)
node --test --experimental-strip-types test/**/*.test.ts

External links

Exercise

Jest (또는 vitest, mocha) 쓰는 작은 프로젝트를 node:test 로 변환. 변환이 bounded 되게 100 테스트 미만 프로젝트 골라. 추적: (a) install 시간과 node_modules 크기 전/후, (b) 재현 못 한 기능, (c) API 다르다는 이유로 다시 써야 한 테스트. 연습의 포인트는 세 번째 축 — 네 테스트 코드가 깨닫지 못한 채 뭘 의존하고 있어?
Hint
대부분 표면-레벨 변환은 기계적: expect(a).toBe(b)assert.equal(a, b), jest.fn()t.mock.fn(). Snapshot 테스트와 모듈 mocking 이 자주 깨끗하게 안 옮겨가는 두 패턴. jest.mock('./db') 원하고 있으면, 그게 모듈-레벨 mocking 이 필요했나 또는 의존성 주입이 더 깨끗할까 평가할 순간이야.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.