Node.js Native Test Runner
If anyone missed it, Node.js 18 includes a test runner/test definition module (node --test
and node:test
respectively).
node:test
exports a test
function and you can run the Node CLI with a --test
flag which does some basic search/matching for test files.
Full Documentation: nodejs.org/api/test.html
Table of Contents
Example Node.js Tests with Assertions
The recommended way to do assertions is to use the existing assert
module.
Combination of node:test
+ node:assert/strict
are good for testing pure code (ie. check output is as expected).
For module interception or advanced stubbing, you’ll have to look elsewhere, although I did find CallTracker the other day, which isn’t as complete as jest.fn() or sinon stubs but you can create a stub that reports on how many times it’s been called, see assert.CallTracker docs.
In short: you can write and run tests in Node.js without any npm packages.
A simple example, in a ping.mjs
file.
import test from 'node:test';
import assert from 'node:assert/strict';
const ping = () => 'pong';
test('ping', (_t) => {
assert.equal(ping(), 'pong');
});
We can run the above using node --test ping.mjs
or node ping.mjs
which gives the following output:
node ping.mjs
(node:2191) ExperimentalWarning: The test runner is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
TAP version 13
ok 1 - ping
---
duration_ms: 0.001783726
...
1..1
# tests 1
# pass 1
# fail 0
# skipped 0
# todo 0
# duration_ms 0.91425132
Given a failure by changing assert.equal(ping(), 'pong');
to assert.equal(ping(), 'ping');
, we would get the following output:
node ping.mjs
(node:2321) ExperimentalWarning: The test runner is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
TAP version 13
not ok 1 - ping
---
duration_ms: 0.00915903
failureType: 'testCodeFailure'
error: |-
Expected values to be strictly equal:
'pong' !== 'ping'
code: 'ERR_ASSERTION'
stack: |-
TestContext.<anonymous> (ping.mjs:5:10)
Test.runInAsyncScope (node:async_hooks:202:9)
Test.run (node:internal/test_runner/test:340:20)
Test.start (node:internal/test_runner/test:292:17)
Test.test (node:internal/test_runner/harness:126:18)
file://ping.mjs:5:1
ModuleJob.run (node:internal/modules/esm/module_job:198:25)
async Promise.all (index 0)
async ESMLoader.import (node:internal/modules/esm/loader:409:24)
async loadESM (node:internal/process/esm_loader:85:5)
...
1..1
# tests 1
# pass 0
# fail 1
# skipped 0
# todo 0
# duration_ms 0.684553003
See more examples at github.com/HugoDF/microbundle-ts-pkg/tree/master/test
Recommended module interception, spy/stub/mock and snapshot assertion for node:test
For more advanced functionality to augment your tests:
- module interception can be done using proxyquire or esmock.
- spying and stubbing can be done with sinon
- a standalone snapshot solution is snapshot-assertion
Notes on node:test
TAP output
Back to the Node.js test runner, it outputs in TAP, which is the “test anything protocol”, here’s the specification: testanything.org/tap-specification.html.
That means you can take your output and pipe it into existing formatters and there was already node-tap as a userland runner implementation.
Closing remarks
Final couple of things, which are a given for most modern Node.js test runners:
- it supports all the usual test function formats ie. Promise rejection, error throwing,
done
callback not invoked are all reported as failures - there’s “skip/only” and “sub-tests/test suite” concepts
Node.js “test” files that use node:test
can be run directly using node file.js
for example. node --test <more-options>
can be used for running multiple files at once, see “test runner execution model”.
Photo by DiEGO MüLLER on Unsplash
Get The Jest Handbook (100 pages)
Take your JavaScript testing to the next level by learning the ins and outs of Jest, the top JavaScript testing library.
orJoin 1000s of developers learning about Enterprise-grade Node.js & JavaScript