A test file is a normal module that imports test from node:test and calls it. Given a src/cart.js exporting subtotal(items) and applyCoupon(total, code) — the latter throwing Unknown coupon: NOPE — the tests go in test/cart.test.js:
import test from 'node:test';
import assert from 'node:assert/strict';
import { subtotal, applyCoupon } from '../src/cart.js';
test('subtotal adds up price times quantity', () => {
assert.equal(subtotal([{ price: 3, qty: 2 }, { price: 5, qty: 1 }]), 11);
});
test('an unknown coupon is rejected', () => {
assert.throws(() => applyCoupon(30, 'NOPE'), /Unknown coupon/);
});node --test finds the file, runs it in its own child process and prints the default spec report: ✔ subtotal adds up price times quantity (0.76ms), ✔ an unknown coupon is rejected (0.4287ms), ℹ tests 2 / ℹ pass 2 / ℹ fail 0. With no path arguments it walks the current directory, skips node_modules, and matches **/*.test.{cjs,mjs,js}, **/*-test.*, **/*_test.*, **/test-*.*, **/test.* and everything under **/test/** — the same patterns for .ts, .mts and .cts unless you pass --no-strip-types, so a TypeScript project needs no wiring (TypeScript on Node).
Make one expectation wrong — a helper returns currency: 'USD', the test asks for 'EUR' — and the run prints this, then exits with status 1:
✖ failing tests: test at test\fail.test.js:8:1 ✖ summarize reports the cart (2.5369ms) AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + actual - expected { count: 2, + currency: 'USD', - currency: 'EUR', total: 11 } at TestContext.<anonymous> (file:///.../test/fail.test.js:9:10) |
| Output of a failing run |
The diff shows only the key that differs, so a twenty-field object does not bury the one mistake, and the stack points at your assertion rather than at runner internals. Every failure is repeated in this "failing tests" block at the end of the run, the part to scroll to on a large suite. A run with no failure that still exits 1 means an unhandled rejection after a test finished — a promise you started and never awaited.