Project tests catch small regressions before a Node.js change reaches a package script, pull request, or deployment. The built-in node:test runner keeps that check inside Node.js itself when a separate framework is unnecessary.

Using ES module files with the .mjs extension avoids a package metadata prerequisite, so the first test can run before package.json has a module type. node:assert/strict raises assertion errors for mismatched values, and node –test reports those failures through the test runner.

Test file names control discovery. node –test finds names such as *.test.mjs and files under test/, so the test file should follow those patterns or be passed explicitly to the runner.

Steps to write Node.js tests with node:test:

  1. Create the module that the test will exercise.
    lib/math.mjs
    export function add(left, right) {
      return left + right;
    }
  2. Create a discovered test file under test/.
    test/math.test.mjs
    import test from "node:test";
    import assert from "node:assert/strict";
    import { add } from "../lib/math.mjs";
     
    test("adds two numbers", () => {
      assert.strictEqual(add(2, 3), 5);
    });

    The .test.mjs suffix lets node –test discover the file without extra arguments. Use .test.js instead when the project is already configured for ES modules.
    Related: How to enable ES modules in Node.js

  3. Run the built-in test runner from the project root.
    $ node --test
    ✔ adds two numbers (0.574709ms)
    ℹ tests 1
    ℹ suites 0
    ℹ pass 1
    ℹ fail 0
    ℹ cancelled 0
    ℹ skipped 0
    ℹ todo 0
    ℹ duration_ms 54.636666
  4. Change the expected value from 5 to 6 temporarily.

    Keep this as a deliberate failure check only. A failing test exits with a nonzero status and should not remain in the committed test file.

  5. Run the test runner again to confirm the assertion failure.
    $ node --test
    ✖ adds two numbers (1.194625ms)
    ℹ tests 1
    ℹ suites 0
    ℹ pass 0
    ℹ fail 1
    ℹ cancelled 0
    ℹ skipped 0
    ℹ todo 0
    ℹ duration_ms 60.495
    
    ✖ failing tests:
    
    test at test/math.test.mjs:5:1
    ✖ adds two numbers (1.194625ms)
      AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
    
      5 !== 6
    
    ##### snipped #####
      {
        code: 'ERR_ASSERTION',
        actual: 5,
        expected: 6,
        operator: 'strictEqual',
        diff: 'simple'
      }
  6. Restore the expected value to 5.
  7. Run the final passing test.
    $ node --test
    ✔ adds two numbers (0.829292ms)
    ℹ tests 1
    ℹ suites 0
    ℹ pass 1
    ℹ fail 0
    ℹ cancelled 0
    ℹ skipped 0
    ℹ todo 0
    ℹ duration_ms 65.937