node –test (node:test) în Node.js

Rulare și linie de comandă Node.js 18.0 (stabil din 20.0)

Rulează testele automate cu testerul inclus în Node.js: test, describe, it, fără Jest sau Mocha.

Sintaxă
node --test [fișiere sau tipare]
import { test, describe, it } from "node:test";
test("nume", () => { ... });

Ce face node --test (node:test)

Modulul node:test oferă funcțiile test(), describe() și it(). Un test este o funcție care verifică un rezultat, de obicei cu node:assert/strict; dacă funcția aruncă o eroare (sau promisiunea ei este respinsă), testul a picat. Funcțiile async sunt așteptate automat.

node --test fără alte argumente caută fișierele de test din proiect după nume: *.test.mjs, *-test.js, *_test.js, fișierele din directoare numite test și altele asemănătoare (fără node_modules). Fiecare fișier rulează în procesul lui. La final apare un rezumat, iar codul de ieșire este 1 dacă a picat vreun test, așa că merge direct în CI.

Opțiuni utile: --test-name-pattern rulează doar testele al căror nume se potrivește, --watch le reia la fiecare salvare, --test-reporter=tap schimbă formatul. Raportul de acoperire (--experimental-test-coverage) este încă experimental. Testele pot fi marcate cu test.skip, test.todo sau test.only, iar funcțiile pot fi înlocuite temporar cu t.mock.fn().

Parametri

Parametru Descriere
test(nume, [opțiuni], fn) Definește un test. fn primește contextul testului (t).
describe(nume, fn) / it(nume, fn) Grupează teste într-o suită / alias pentru test, ca în Mocha și Jest.
before, after, beforeEach, afterEach Cod rulat înainte și după teste (pregătire, curățenie).
--test-name-pattern=regex Rulează doar testele cu nume potrivit.
--test-reporter=spec|tap|dot|junit|lcov Formatul raportului (spec implicit în terminal).

Ce returnează

Codul de ieșire al comenzii: 0 dacă toate testele au trecut, 1 dacă a picat cel puțin unul.

Exemple

Exemplul 1: Primele teste

Fișierul suma.mjs exportă funcțiile suma(a, b) și medie(note), care aruncă o eroare pentru o listă goală. Testele stau în suma.test.mjs, iar node --test le găsește singur după nume.

// suma.test.mjs
import { test } from "node:test";
import assert from "node:assert/strict";
import { suma, medie } from "./suma.mjs";

test("suma adună două numere", () => {
  assert.equal(suma(2, 3), 5);
});

test("media notelor", () => {
  assert.equal(medie([9, 10, 8]), 9);
});

test("lista goală aruncă eroare", () => {
  assert.throws(() => medie([]), /goală/);
});

// în terminal: node --test

Ieșire în terminal

✔ suma adună două numere (0.885458ms)
✔ media notelor (0.109041ms)
✔ lista goală aruncă eroare (0.24775ms)
ℹ tests 3
ℹ suites 0
ℹ pass 3
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 57.395291

Exemplul 2: describe, it și un test care pică

Al doilea test așteaptă greșit valoarea 1. Raportul arată ce test a picat, valoarea primită și pe cea așteptată (stiva de apeluri a fost scurtată).

// cos.test.mjs
import { describe, it } from "node:test";
import assert from "node:assert/strict";

function totalCos(produse) {
  return produse.reduce((s, p) => s + p.pret * p.cantitate, 0);
}

describe("coșul de cumpărături", () => {
  it("calculează totalul", () => {
    const cos = [{ pret: 12.5, cantitate: 2 }, { pret: 30, cantitate: 1 }];
    assert.equal(totalCos(cos), 55);
  });

  it("coșul gol are total 0", () => {
    assert.equal(totalCos([]), 1);
  });
});

// în terminal: node --test cos.test.mjs

Ieșire în terminal

▶ coșul de cumpărături
  ✔ calculează totalul (3.123125ms)
  ✖ coșul gol are total 0 (1.031167ms)
✖ coșul de cumpărături (4.945667ms)
ℹ tests 2
ℹ suites 1
ℹ pass 1
ℹ fail 1
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 87.863667

✖ failing tests:

test at cos.test.mjs:14:3
✖ coșul gol are total 0 (1.031167ms)
  AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:

  0 !== 1

      at TestContext.<anonymous> (file:///.../cos.test.mjs:15:12)
      ...

Exemplul 3: Funcții simulate cu t.mock.fn

t.mock.fn() creează o funcție care ține minte de câte ori și cu ce argumente a fost apelată. Aici înlocuiește trimiterea unui e-mail. Rulează cu node --test notificari.test.mjs; toate testele trec.

// notificari.test.mjs
import { test } from "node:test";
import assert from "node:assert/strict";

function anuntaNote(elevi, trimite) {
  for (const elev of elevi) {
    if (elev.nota < 5) trimite(elev.email, `Ai nota ${elev.nota}`);
  }
}

test("trimite mesaj doar elevilor sub 5", (t) => {
  const trimite = t.mock.fn();
  anuntaNote([
    { email: "ana@exemplu.ro", nota: 9 },
    { email: "ion@exemplu.ro", nota: 4 },
  ], trimite);

  assert.equal(trimite.mock.callCount(), 1);
  assert.deepEqual(trimite.mock.calls[0].arguments, ["ion@exemplu.ro", "Ai nota 4"]);
});

Greșeli frecvente

  • Numești fișierul teste-suma.mjs și node --test nu-l găsește. Folosește un nume recunoscut (suma.test.mjs) sau dă calea explicit: node --test teste-suma.mjs.
  • Folosești assert.equal din node:assert (fără /strict): compară cu ==, deci "5" și 5 sunt considerate egale. Importă din node:assert/strict.
  • Uiți await în fața unei promisiuni verificate cu assert.rejects: testul se termină înainte de verificare și trece fals. Scrie await assert.rejects(...).

Comenzi înrudite

  • assert (node:assert/strict): Verificări care aruncă o eroare dacă o condiție nu este adevărată: baza testelor cu node:test.
  • node --run: Rulează un script din câmpul „scripts” al package.json direct cu Node.js, mai repede decât npm run.
  • npm run: Rulează un script din câmpul „scripts” al package.json, cu node_modules/.bin în PATH și cu scripturile pre/post.
  • node --watch: Repornește automat scriptul când salvezi fișierul sau unul dintre modulele importate, fără nodemon.