Un singur test, multe cazuri
Majoritatea funcțiilor au nevoie de aceeași verificare pentru multe intrări: valori obișnuite, valori negative, zero, cazuri limită. Dacă copiezi testul de cinci ori, ai cinci locuri de întreținut.
Răspunsul obișnuit este un test bazat pe tabel: pui cazurile într-un tablou de obiecte — fiecare caz conține un nume, intrările și rezultatul așteptat — și rulezi o singură buclă peste ele.
Adăugarea unui caz nou devine o singură linie nouă în tabel. Acesta este cel mai des întâlnit tipar de testare pe care îl vei vedea în codul real.
Tabelul
Tabelul este un tablou de obiecte cu un tip denumit, scris chiar lângă test. Fiecare intrare este un caz: un nume (pentru mesajul de eroare), intrările și rezultatul așteptat.
Bucla apelează funcția o dată pentru fiecare caz și compară rezultatul. Prima nepotrivire aruncă o eroare și încheie testul, așa că mesajul poartă numele cazului — astfel afli care rând s-a stricat.
Patru cazuri într-un singur tabel
Patru cazuri, o buclă, o verificare. Toate trec aici, așa că rularea afișează o singură linie ✔ add over the table. Ca să testezi a cincea situație, ai adăuga o linie în tabel — bucla rămâne neatinsă.
Ieșire: program TypeScript și rezultatul capturat
import { test } from "node:test"
import assert from "node:assert/strict"
function add(a: number, b: number): number {
return a + b
}
type Case = {
name: string
a: number
b: number
want: number
}
const cases: Case[] = [
{ name: "one plus one", a: 1, b: 1, want: 2 },
{ name: "positive and negative", a: 5, b: -3, want: 2 },
{ name: "both negative", a: -2, b: -4, want: -6 },
{ name: "zeros", a: 0, b: 0, want: 0 }
]
test("add over the table", () => {
for (const c of cases) {
const got = add(c.a, c.b)
assert.equal(got, c.want, `${c.name}: add(${c.a}, ${c.b}) = ${got}; așteptat ${c.want}`)
}
})
Subteste
Apelarea t.test(name, fn) în interiorul unui test transformă fiecare caz din tabel într-un subtest propriu. Funcția testului exterior primește contextul de test t ca argument, iar fiecare caz este așteptat cu await, ca să se termine înainte de a începe următorul.
Numele cazurilor apar acum în rezultat, indentate sub testul părinte, fiecare cu propriul ✔ sau ✖. Astfel, un caz stricat se observă ușor într-un tabel lung.
Fiecare caz primește un nume
Același tabel, învelit în t.test. Rezultatul listează acum toate cele patru cazuri separat, sub ▶ add, iar rezumatul numără cinci teste: părintele plus cele patru subteste ale sale.
Ieșire: program TypeScript și rezultatul capturat
import { test } from "node:test"
import assert from "node:assert/strict"
function add(a: number, b: number): number {
return a + b
}
type Case = {
name: string
a: number
b: number
want: number
}
const cases: Case[] = [
{ name: "one plus one", a: 1, b: 1, want: 2 },
{ name: "positive and negative", a: 5, b: -3, want: 2 },
{ name: "both negative", a: -2, b: -4, want: -6 },
{ name: "zeros", a: 0, b: 0, want: 0 }
]
test("add", async (t) => {
for (const c of cases) {
await t.test(c.name, () => {
const got = add(c.a, c.b)
assert.equal(got, c.want, `add(${c.a}, ${c.b}) = ${got}; așteptat ${c.want}`)
})
}
})
Rularea unui singur caz
Testele pot fi alese din linia de comandă după nume, cu --test-name-pattern:
node --test --test-reporter=spec --test-name-pattern 'both negative'
Tiparul este comparat cu numele fiecărui test înregistrat. Un subtest nu poate fi selectat singur — când testul părinte nu se potrivește, nimic din interiorul lui nu rulează — așa că, pentru ca acest lucru să funcționeze, fiecare caz primește propriul apel test(…) de nivel superior, cu numele cazului în el.
Este perfect cât timp repari un singur caz stricat: rulezi din nou doar acel caz până devine verde, apoi rulezi din nou totul.
Filtrare după nume
Tabelul este înregistrat ca patru teste separate, numite add: one plus one și așa mai departe. Rulând cu tiparul both negative, se execută doar unul dintre cele patru — rezumatul spune tests 1.
Ieșire: program TypeScript și rezultatul capturat
import { test } from "node:test"
import assert from "node:assert/strict"
function add(a: number, b: number): number {
return a + b
}
type Case = {
name: string
a: number
b: number
want: number
}
const cases: Case[] = [
{ name: "one plus one", a: 1, b: 1, want: 2 },
{ name: "positive and negative", a: 5, b: -3, want: 2 },
{ name: "both negative", a: -2, b: -4, want: -6 },
{ name: "zeros", a: 0, b: 0, want: 0 }
]
// Câte un test de nivel superior pentru fiecare caz, ca un tipar de nume să poată alege unul singur.
for (const c of cases) {
test(`add: ${c.name}`, () => {
const got = add(c.a, c.b)
assert.equal(got, c.want, `add(${c.a}, ${c.b}) = ${got}; așteptat ${c.want}`)
})
}