Modulelessen (1/5)
Het `test`-pakket
In Go zijn tests onderdeel van de stdlib: geen externe bibliotheek, geen raamwerk om te configureren. Het enige wat je nodig hebt is een *_test.go bestand naast de code, een paar TestXxx functies en de opdracht go test.
Basisconventies
- Testbestanden hebben de naam
<something>_test.goen bevinden zich in hetzelfde pakket als de code die ze testen (of in een<name>_testpakket voor "black-box-tests"). - Testfuncties hebben een exacte handtekening:
func TestXxx(t *testing.T)waarbijXxxbegint met een hoofdletter. - Je importeert
testinguit de stdlib. - Nee
assertEquals: je gebruiktif got != want { t.Errorf(...) }metfmt-werkwoorden.
// math.go
package math
func Sum(a, b int) int { return a + b }
// math_test.go
package math
import "testing"
func TestSum(t *testing.T) {
got := Sum(2, 3)
if got != 5 {
t.Errorf("Sum(2,3) = %d; voglio %d", got, 5)
}
}Voer het uit met:
go test ./... # all packages in the module
go test -v ./pkg # verbose: prints test names
go test -run TestSum # only tests matching the regext.Error versus t.Fatal
Dit zijn de twee basiswerkwoorden om een fout aan te geven:
| Werkwijze | Effect |
|---|---|
t.Log(args...) | Registreert maar faalt niet (alleen zichtbaar met -v of bij falen). |
t.Error(args...) | Registreert, markeert FAIL, gaat door met de testfunctie. |
t.Errorf(fmt, ...) | Vind Error leuk met opmaak. |
t.Fatal(args...) | Registreert, markeert FAIL, stopt de test (roept runtime.Goexit aan). |
t.Fatalf(fmt, ...) | Vind Fatal leuk met opmaak. |
Vuistregel: gebruik Fatal als doorgaan geen zin heeft (bijvoorbeeld een mislukte installatie, dreigende nul-pointer-dereferentie); anders Error, waarmee u alle fouten in één keer kunt zien.
func TestOpen(t *testing.T) {
f, err := os.Open("fixtures/sample.txt")
if err != nil {
t.Fatal(err) // if it doesn't open, the next steps would fail on nil
}
defer f.Close()
// ... assert on content with t.Errorf
}Opzetten en afbreken met t.Cleanup
Om bronnen vrij te geven aan het einde van een test (of subtest), gebruik je t.Cleanup in plaats van defer:
func TestDB(t *testing.T) {
db := newTestDB(t)
t.Cleanup(func() { db.Close() })
// ... test
}Het voordeel ten opzichte van defer: de helper die db aanmaakt, kan de opruiming intern registreren, zodat bellers dit niet hoeven te onthouden.
Helpers testen
De t.Helper() methode markeert een functie als een "helper": wanneer een test mislukt, slaat de stacktrace de helperfunctie over en verwijst deze rechtstreeks naar de aanroeper:
func mustParseInt(t *testing.T, s string) int {
t.Helper()
n, err := strconv.Atoi(s)
if err != nil {
t.Fatalf("parse %q: %v", s, err)
}
return n
}Oefeningen
Definieer de TestSum-functie die Sum(2,3) == 5 verifieert met behulp van t.Errorf met een opgemaakt bericht.
Oplossing beschikbaar na 3 pogingen
Gebruik in TestDiv t.Fatal om de test onmiddellijk te stoppen als Div een onverwachte waarde retourneert.
Oplossing beschikbaar na 3 pogingen
Wat is het fundamentele verschil tussen t.Error en t.Fatal?
if err != nil {
t.???(err)
}