testing.T în Go

Tipul primit de fiecare funcție de test; prin el raportezi erori, scrii mesaje și controlezi testul.

Sintaxă
// în fișierul nume_test.go
func TestNume(t *testing.T) {
    // ...
}

Ce face testing.T

Testele în Go stau în fișiere care se termină cu _test.go, lângă codul testat. Fiecare funcție func TestXxx(t *testing.T) (numele începe cu Test și o literă mare) este un test. Comanda go test le găsește, le compilează și le rulează; go test -v afișează fiecare test, iar go test -run Nume rulează doar testele al căror nume se potrivește.

Prin t raportezi problemele: t.Error/t.Errorf marchează testul ca eșuat și continuă, t.Fatal/t.Fatalf îl opresc. t.Log scrie mesaje afișate doar cu -v sau când testul eșuează. Alte metode: t.Run (subteste), t.Helper, t.Skip, t.Parallel, t.Cleanup, t.TempDir, t.Setenv, t.Context.

Go nu are funcții assert: compari singur cu if și scrii un mesaj clar, de forma Functie(intrare) = rezultat, aștept valoare. Exemplele de mai jos arată două fișiere (codul și testul), apoi ce afișează go test.

Parametri

Parametru Descriere
t Valoarea primită de test; nu o creezi tu.

Ce returnează

Nu se aplică (este un tip).

Exemple

Exemplul 1: Primul test

// fișierul pret.go
package magazin

// PretCuTVA adaugă TVA de 21% la prețul fără TVA, rotunjit la bani.
func PretCuTVA(net float64) float64 {
    return float64(int(net*121+0.5)) / 100
}

// fișierul pret_test.go
package magazin

import "testing"

func TestPretCuTVA(t *testing.T) {
    got := PretCuTVA(100)
    if got != 121 {
        t.Errorf("PretCuTVA(100) = %v, aștept 121", got)
    }
}

Rezultatul în terminal (timpii diferă la fiecare rulare)

$ go test
PASS
ok  	magazin	0.234s
$ go test -v
=== RUN   TestPretCuTVA
--- PASS: TestPretCuTVA (0.00s)
PASS
ok  	magazin	0.131s

Exemplul 2: Un test care găsește o greșeală

Funcția folosește > în loc de >=, deci pentru exact 200 lei nu dă reducere. Mesajul de eroare arată fișierul și linia.

// fișierul reducere.go
package magazin

// Reducere returnează procentul de reducere: 5% de la 200 lei, 10% de la 500 lei.
func Reducere(total float64) int {
    switch {
    case total >= 500:
        return 10
    case total > 200:
        return 5
    default:
        return 0
    }
}

// fișierul reducere_test.go
package magazin

import "testing"

func TestReducere(t *testing.T) {
    cazuri := []struct {
        total float64
        vrem  int
    }{
        {50, 0},
        {200, 5},
        {350, 5},
        {500, 10},
    }
    for _, c := range cazuri {
        if got := Reducere(c.total); got != c.vrem {
            t.Errorf("Reducere(%v) = %d, aștept %d", c.total, got, c.vrem)
        }
    }
}

Rezultatul în terminal (timpii diferă la fiecare rulare)

$ go test -v
=== RUN   TestReducere
    reducere_test.go:17: Reducere(200) = 0, aștept 5
--- FAIL: TestReducere (0.00s)
FAIL
exit status 1
FAIL	magazin	0.248s

Exemplul 3: Mesaje cu t.Log și rularea unui singur test

// fișierul text.go
package magazin

import "strings"

// Slug transformă un titlu în text potrivit pentru URL.
func Slug(titlu string) string {
    return strings.ReplaceAll(strings.ToLower(strings.TrimSpace(titlu)), " ", "-")
}

// fișierul text_test.go
package magazin

import "testing"

func TestSlug(t *testing.T) {
    got := Slug("  Rețete de Toamnă ")
    t.Logf("Slug a returnat %q", got)
    if got != "rețete-de-toamnă" {
        t.Errorf("got %q", got)
    }
}

func TestSlugGol(t *testing.T) {
    if got := Slug(""); got != "" {
        t.Errorf("Slug(\"\") = %q, aștept textul gol", got)
    }
}

Rezultatul în terminal (timpii diferă la fiecare rulare)

$ go test -v -run TestSlug$
=== RUN   TestSlug
    text_test.go:7: Slug a returnat "rețete-de-toamnă"
--- PASS: TestSlug (0.00s)
PASS
ok  	magazin	0.254s

Greșeli frecvente

  • Numești funcția testPret sau Testpret. Numele trebuie să înceapă cu Test, urmat de o literă mare sau de nimic, altfel go test o ignoră.
  • Pui testele într-un fișier fără sufixul _test.go. Ele ajung în programul final, iar go test nu le rulează.
  • Compari numere cu zecimale cu == fără rotunjire. 0.1+0.2 != 0.3; rotunjește sau compară cu o toleranță.

Comenzi înrudite

  • testing.T.Error: Marchează testul ca eșuat și scrie un mesaj, dar lasă testul să continue (Errorf formatează ca Printf).
  • testing.T.Fatal: Marchează testul ca eșuat, scrie mesajul și oprește imediat testul curent; celelalte teste continuă.
  • testing.T.Run: Rulează o funcție ca subtest, cu nume propriu; ideal pentru testele bazate pe un tabel de cazuri.
  • testing.B: Tipul primit de funcțiile benchmark, care măsoară cât durează (și câtă memorie folosește) o bucată de cod.