Direkt zum Hauptinhalt springen
eLearner.app
Modul 9 · Lektion 1 von 541/50 im Kurs~12 min
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.go und 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), wobei Xxx mit einem Großbuchstaben beginnt.
  • Sie importieren testing aus der stdlib.
  • Kein assertEquals: Sie verwenden if got != want { t.Errorf(...) } mit fmt-Verben.
Go
// 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:

Bash
go test ./...        # all packages in the module
go test -v ./pkg     # verbose: prints test names
go test -run TestSum  # only tests matching the regex

t.Error vs. t.Fatal

Dies sind die beiden grundlegenden Verben, um einen Fehler zu signalisieren:

MethodeWirkung
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.

Go
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:

Go
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:

Go
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

Übung#go.m9.l1.e1
Versuche: 0Wird geladen…

Definieren Sie die TestSum-Funktion, die Sum(2,3) == 5 mithilfe von t.Errorf mit einer formatierten Nachricht überprüft.

Editor wird geladen…

Lösung nach 3 Versuchen verfügbar

Übung#go.m9.l1.e2
Versuche: 0Wird geladen…

Verwenden Sie in TestDiv t.Fatal, um den Test sofort zu stoppen, wenn Div einen unerwarteten Wert zurückgibt.

Editor wird geladen…

Lösung nach 3 Versuchen verfügbar

Quiz#go.m9.l1.e3
Bereit

Was ist der grundlegende Unterschied zwischen t.Error und t.Fatal?

Go
if err != nil {
  t.???(err)
}
Antwortoptionen