Reguli mici, diferență mare
Testele bune respectă câteva obiceiuri:
1. Nume clare — greet falls back for an empty name spune ce s-a stricat fără să deschizi fișierul.
2. Un singur comportament per test — testele mici arată direct spre problemă.
3. Tabele pentru multe cazuri — o singură buclă în loc de teste copiate.
4. Mesaje cu got și want — un eșec trebuie să se explice singur.
5. Teste separate ca să vezi tot, un singur test acolo unde nu are rost să continui.
6. Rulează testele des — după fiecare modificare mică, nu o singură dată la final.
7. Testele stau lângă cod — același folder, sufixul .test.ts.
Mesaje de eșec care ajută
Un test care eșuează este citit într-un moment de confuzie — mesajul trebuie să poarte toată povestea: ce apel, ce a venit înapoi, ce se aștepta.
O formă bună este func(input) = got; want want. Trecerea șirurilor prin JSON.stringify le pune între ghilimele, așa că un spațiu lipsă sau o virgulă lipsă se vede imediat.
Un mesaj cu toată povestea
greet întoarce salutul greșit. Mesajul nostru arată apelul, valoarea got și valoarea want, iar executorul de teste adaugă dedesubt propriile linii + actual - expected — eroarea (cuvânt greșit, virgulă și semn de exclamare lipsă) se vede doar din rezultat, fără să deschizi codul.
Ieșire: program TypeScript și rezultatul capturat
import { test } from "node:test"
import assert from "node:assert/strict"
// greet are o eroare: cuvânt greșit, lipsesc virgula și semnul "!".
function greet(name: string): string {
return "Hi " + name
}
test("greet by name", () => {
const got = greet("Ana")
const want = "Hello, Ana!"
assert.equal(got, want,
`greet("Ana") = ${JSON.stringify(got)}; want ${JSON.stringify(want)}`)
})
Un singur comportament per test
Un test care verifică cinci lucruri are cinci motive să eșueze — iar numele lui poate descrie doar unul dintre ele. Împărțirea pe comportamente păstrează fiecare test mic și numele lui cinstit. Aici contează de două ori, pentru că o aserțiune eșuată oprește testul din care face parte: cinci verificări într-un singur test înseamnă că vezi mereu doar primul eșec.
Salutul normal și varianta de rezervă pentru numele gol sunt două comportamente, așa că primesc două teste. Când unul eșuează, numele lui îți spune deja ce comportament s-a stricat.
Două comportamente, două teste
greet uses the name verifică situația normală, iar greet falls back for an empty name varianta de rezervă. Rezultatul le listează separat — un eșec ar arăta exact spre un singur comportament.
Ieșire: program TypeScript și rezultatul capturat
import { test } from "node:test"
import assert from "node:assert/strict"
function greet(name: string): string {
if (name === "") {
return "Hello, stranger!"
}
return "Hello, " + name + "!"
}
test("greet uses the name", () => {
const got = greet("Ana")
assert.equal(got, "Hello, Ana!", `greet("Ana") = ${JSON.stringify(got)}`)
})
test("greet falls back for an empty name", () => {
const got = greet("")
assert.equal(got, "Hello, stranger!", `greet("") = ${JSON.stringify(got)}`)
})
Cât este testat: acoperirea
node --test --experimental-test-coverage măsoară ce parte din codul tău execută testele cu adevărat. Afișează câte un rând pentru fiecare fișier, cu trei procente — linii, ramuri și funcții — plus numerele liniilor la care nu a ajuns nimic.
Numărul este o busolă, nu un scop: o valoare mică arată căi netestate. O acoperire de 100% nu dovedește că acel cod este corect, dar liniile neacoperite sunt sigur neverificate.
Măsoară acoperirea
describeTemperature are trei ramuri, iar testul parcurge una singură. Raportul arată line % 76.47 și branch % 60.00 și numește liniile neacoperite 6-7 9-10 — return-ul freezing și cel hot. Teste pentru ramura rece și pentru cea fierbinte ar ridica ambele numere.
Se măsoară tot fișierul, testele incluse, de aceea numărul pentru linii nu este mai mic: liniile de test au rulat toate.
Ieșire: program TypeScript și rezultatul capturat
import { test } from "node:test"
import assert from "node:assert/strict"
function describeTemperature(celsius: number): string {
if (celsius < 0) {
return "freezing"
}
if (celsius > 30) {
return "hot"
}
return "mild"
}
test("20 degrees is mild", () => {
const got = describeTemperature(20)
assert.equal(got, "mild", `describeTemperature(20) = ${JSON.stringify(got)}`)
})