Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

The built-in test runner

An automated test is a small program that calls your code and checks the result. Tests are run after every change: if something breaks, you learn about it at once, not from the blog's visitors. Node.js has built-in modules for this — node:test (running tests) and node:assert (checks) — so nothing needs to be installed.

The first test

test() takes a name and a function with checks. assert.equal() compares the actual value with the expected one:

import { test } from 'node:test';
import assert from 'node:assert/strict';
 
function slugify(title) {
  return title.toLowerCase().trim().replace(/\s+/g, '-');
}
 
test('replaces spaces with hyphens', () => {
  assert.equal(slugify('Hello Node js'), 'hello-node-js');
});
 
test('trims spaces at the edges', () => {
  assert.equal(slugify('  Blog  '), 'blog');
});

Run the file with node: the terminal shows a report with two check marks and the line pass 2. If a check fails, the report shows the expected and actual values, and the program returns code 1.

Code and tests in separate files

In a project the function lives in src/slugify.js:

// src/slugify.js
export function slugify(title) {
  return title.toLowerCase().trim().replace(/\s+/g, '-');
}

And the tests live in the test folder, in a file ending in .test.js:

// test/slugify.test.js
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { slugify } from '../src/slugify.js';
 
test('replaces spaces with hyphens', () => {
  assert.equal(slugify('Hello Node js'), 'hello-node-js');
});

Running all tests

The --test flag finds files named like *.test.js in all project folders and runs them:

node --test

Add it to package.json to run it with the familiar npm test:

{
  "scripts": {
    "test": "node --test"
  }
}

With --watch, tests rerun on every save: node --test --watch.

Checks

CheckWhat it compares
assert.equal(a, b)Values, strictly with ===
assert.deepEqual(a, b)Objects and arrays by content
assert.ok(value)That the value is truthy
assert.throws(fn)That the function throws
await assert.rejects(promise)That the promise rejects

An asynchronous test

If the code is asynchronous, declare the test function async and await the result:

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { readFile, writeFile } from 'node:fs/promises';
 
test('posts are saved as JSON', async () => {
  await writeFile('posts-test.json', JSON.stringify([{ id: 1, title: 'Hello' }]));
  const posts = JSON.parse(await readFile('posts-test.json', 'utf8'));
  assert.deepEqual(posts, [{ id: 1, title: 'Hello' }]);
});

Common mistake

Two objects with the same content are different objects, so assert.equal() does not consider them equal:

import assert from 'node:assert/strict';
 
assert.deepEqual({ id: 1 }, { id: 1 }); // passes
console.log('deepEqual compares content');
// assert.equal({ id: 1 }, { id: 1 }) would fail

For objects and arrays use assert.deepEqual().

Thanks for reading!

Donate to the site — we work hard for you.