Lektionen des Moduls (1/5)
Das `testing`-Package
In Go sind Tests Teil der stdlib: keine externe Bibliothek, kein zu konfigurierendes Framework. Sie benötigen lediglich eine *_test.go-Datei neben dem Code, einige TestXxx-Funktionen und den go test-Befehl.
Grundlegende Konventionen
- Testdateien heißen
<something>_test.gound befinden sich im gleichen Paket wie der Code, den sie testen (oder in einem<name>_test-Paket für „Black-Box-Tests“). - Testfunktionen haben eine exakte Signatur:
func TestXxx(t *testing.T), wobeiXxxmit einem Großbuchstaben beginnt. - Sie importieren
testingaus der stdlib. - Kein
assertEquals: Sie verwendenif got != want { t.Errorf(...) }mitfmt-Verben.
// 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)
}
}Führen Sie es aus mit:
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 vs. t.Fatal
Dies sind die beiden grundlegenden Verben, um einen Fehler zu signalisieren:
| Methode | Wirkung |
|---|---|
t.Log(args...) | Protokolliert, schlägt aber nicht fehl (nur sichtbar mit -v oder bei Fehler). |
t.Error(args...) | Protokolliert, markiert FAIL, setzt die Testfunktion fort. |
t.Errorf(fmt, ...) | Wie Error mit Formatierung. |
t.Fatal(args...) | Protokolliert, markiert FAIL, stoppt den Test (ruft runtime.Goexit auf). |
t.Fatalf(fmt, ...) | Wie Fatal mit Formatierung. |
Faustregel: Verwenden Sie Fatal, wenn das Fortfahren keinen Sinn ergibt (z. B. fehlgeschlagenes Setup, bevorstehende Nullzeiger-Dereferenzierung); andernfalls Error, wodurch Sie alle Fehler in einem einzigen Lauf sehen können.
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
}Auf- und Abbau mit t.Cleanup
Um Ressourcen am Ende eines Tests (oder Untertests) freizugeben, verwenden Sie t.Cleanup anstelle von defer:
func TestDB(t *testing.T) {
db := newTestDB(t)
t.Cleanup(func() { db.Close() })
// ... test
}Der Vorteil gegenüber defer: Der Helfer, der db erstellt, kann die Bereinigung intern registrieren, sodass sich Anrufer sie nicht merken müssen.
Testhelfer
Die t.Helper()-Methode markiert eine Funktion als „Helfer“: Wenn ein Test fehlschlägt, überspringt der Stack-Trace die Hilfsfunktion und verweist direkt auf den Aufrufer:
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
}Übungen
Definieren Sie die TestSum-Funktion, die Sum(2,3) == 5 mithilfe von t.Errorf mit einer formatierten Nachricht überprüft.
Lösung nach 3 Versuchen verfügbar
Verwenden Sie in TestDiv t.Fatal, um den Test sofort zu stoppen, wenn Div einen unerwarteten Wert zurückgibt.
Lösung nach 3 Versuchen verfügbar
Was ist der grundlegende Unterschied zwischen t.Error und t.Fatal?
if err != nil {
t.???(err)
}