Skip to content

Tests

Für Entwickler können gute Tests Fehler im Programm frühzeitig erkennen und die spätere geistige Belastung durch fehlende Wartung und Bugs vermeiden. Daher ist das Schreiben guter Tests sehr wichtig. Go bietet im Bereich Tests sehr einfache und praktische Kommandozeilen-Tools mit go test. In der Standardbibliothek und vielen Open-Source-Frameworks sind Tests allgegenwärtig. Das Tool ist sehr einfach zu verwenden und unterstützt derzeit folgende Testarten:

  • Beispiele_tests
  • Unit-Tests
  • Benchmark-Tests
  • Fuzz-Tests

In Go werden die meisten APIs von der Standardbibliothek testing bereitgestellt.

TIP

Führen Sie in der Kommandozeile go help testfunc aus, um die offizielle Erklärung von Go für die oben genannten vier Testarten zu sehen.

Schreibkonventionen

Bevor Sie mit dem Schreiben von Tests beginnen, sollten Sie einige Konventionen beachten, die das Lernen erleichtern:

  • Test-Paket: Testdateien sollten am besten in einem separaten Paket liegen, das üblicherweise test genannt wird.
  • Testdateien: Testdateien enden normalerweise auf _test.go. Wenn Sie beispielsweise eine bestimmte Funktion testen möchten, benennen Sie die Datei function_test.go. Wenn Sie nach Testtypen weiter unterteilen möchten, können Sie auch den Testtyp als Dateipräfix verwenden, z. B. benchmark_marshaling_test.go oder example_marshaling_test.go.
  • Testfunktionen: Jede Testdatei enthält mehrere Testfunktionen für verschiedene Tests. Für verschiedene Testtypen gibt es unterschiedliche Namenskonventionen. Beispiele_tests heißen ExampleXXXX, Unit-Tests TestXXXX, Benchmark-Tests BenchmarkXXXX und Fuzz-Tests FuzzXXXX. So wissen Sie auch ohne Kommentare, um welche Art von Test es sich handelt.

TIP

Wenn der Paketname testdata ist, dient das Paket normalerweise zum Speichern von Hilfsdaten für Tests. Bei der Ausführung von Tests ignoriert Go Pakete namens testdata.

Wenn Sie die oben genannten Konventionen befolgen und einen guten Teststil entwickeln, sparen Sie später viel Wartungsaufwand.

Tests ausführen

Zum Ausführen von Tests wird hauptsächlich der Befehl go test verwendet. Hier ein konkretes Beispiel: Die zu testende Datei /say/hello.go enthält folgenden Code:

go
package say

import "fmt"

func Hello() {
  fmt.Println("hello")
}

func GoodBye() {
  fmt.Println("bye")
}

Und die Testdatei /test/example_test.go enthält folgenden Code:

go
package test

import (
  "golearn/say"
)

func ExampleHello() {
  say.Hello()
  // Output:
  // hello
}

func ExampleGoodBye() {
  say.GoodBye()
  // Output:
  // bye
}

func ExampleSay() {
  say.Hello()
  say.GoodBye()
  // Output:
  // hello
  // bye
}

Es gibt mehrere Möglichkeiten, diese Tests auszuführen. Wenn Sie alle Testfälle im Paket test ausführen möchten, können Sie den folgenden Befehl im Verzeichnis test ausführen:

sh
$ go test ./
PASS
ok      golearn/test    0.422s

./ bedeutet das aktuelle Verzeichnis. Go kompiliert alle Testdateien im Verzeichnis test neu und führt dann alle Testfälle aus. Aus dem Ergebnis ist ersichtlich, dass alle Testfälle bestanden wurden. Der Parameter kann auch mehrere Verzeichnisse enthalten, z. B.:

sh
$ go test ./ ../
ok      golearn/test
?       golearn [no test files]

TIP

Wenn der Parameter mehrere Pakete enthält, führt Go die bereits erfolgreich bestandenen Testfälle nicht erneut aus. Bei der Ausführung wird (cached) am Ende der Zeile hinzugefügt, um anzuzeigen, dass die Ausgabe aus dem Cache des vorherigen Durchlaufs stammt. Go speichert Testergebnisse im Cache, wenn die Test-Flags in der folgenden Menge enthalten sind:

-benchtime, -cpu,-list, -parallel, -run, -short, -timeout, -failfast, -v

Um den Cache zu deaktivieren, fügen Sie den Parameter -count=1 hinzu.

Sie können auch eine einzelne Testdatei angeben:

sh
$ go test example_test.go
ok      command-line-arguments  0.457s

Oder Sie können einen bestimmten Testfall in einer Testdatei angeben:

sh
$ go test -run ExampleSay
PASS
ok      golearn/test    0.038s

Obwohl alle oben genannten Fälle die Tests abgeschlossen haben, ist die Ausgabe zu knapp. Sie können den Parameter -v hinzufügen, um die Ausgabe detaillierter zu machen:

sh
$ go test ./ -v
=== RUN   ExampleHello
--- PASS: ExampleHello (0.00s)
=== RUN   ExampleGoodBye
--- PASS: ExampleGoodBye (0.00s)
=== RUN   ExampleSay
--- PASS: ExampleSay (0.00s)
PASS
ok      golearn/test    0.040s

Jetzt können Sie die Ausführungsreihenfolge, Dauer, den Status jedes Testfalls sowie die Gesamtdauer klar erkennen.

TIP

Der Befehl go test führt standardmäßig alle Unit-Tests, Beispiele_tests und Fuzz-Tests aus. Wenn Sie den Parameter -bench hinzufügen, werden alle Testtypen ausgeführt:

sh
$ go test -bench .

Verwenden Sie den Parameter -run, um bestimmte Tests auszuführen:

sh
$ go test -bench . -run ^$

Häufige Parameter

Go-Tests haben sehr viele Flag-Parameter. Im Folgenden werden nur die häufigsten Parameter vorgestellt. Weitere Details finden Sie mit dem Befehl go help testflag.

ParameterBeschreibung
-o fileGibt den Namen der kompilierten Binärdatei an
-cKompiliert nur die Testdateien, führt sie aber nicht aus
-jsonGibt Test-Logs im JSON-Format aus
-exec xprogFührt Tests mit xprog aus, entspricht go run
-bench regexpWählt Benchmark-Tests aus, die mit regexp übereinstimmen
-fuzz regexpWählt Fuzz-Tests aus, die mit regexp übereinstimmen
-fuzztime tAutomatische Endzeit für Fuzz-Tests, t ist ein Zeitintervall, bei Einheit x bedeutet es Anzahl
-fuzzminimizetime tMinimale Laufzeit für Fuzz-Tests
-count nFührt Tests n-mal aus, Standard ist 1
-coverAktiviert die Testabdeckungsanalyse
-covermode set,count,atomicSetzt den Modus für die Testabdeckungsanalyse
-cpuSetzt GOMAXPROCS für die Testausführung
-failfastStartet keine neuen Tests nach dem ersten Fehlschlag
-list regexpListet Testfälle auf, die mit regexp übereinstimmen
-parallel nErlaubt parallele Ausführung von Testfällen, die t.Parallel aufrufen
-run regexpFührt nur Testfälle aus, die mit regexp übereinstimmen
-skip regexpÜberspringt Testfälle, die mit regexp übereinstimmen
-timeout dWenn ein einzelner Test länger als das Zeitintervall d dauert, wird panic ausgelöst
-shuffle off,on,NMischt die Ausführungsreihenfolge der Tests, N ist der Zufallsseed
-vGibt detailliertere Test-Logs aus
-benchmemErfasst Speicherzuweisungen in Benchmark-Tests
-blockprofile block.outErfasst Goroutine-Blockierungen und schreibt sie in eine Datei
-blockprofilerate nSteuert die Blockierungs-Erfassungsrate
-coverprofile cover.outErfasst Testabdeckungsdaten und schreibt sie in eine Datei
-cpuprofile cpu.outErfasst CPU-Daten und schreibt sie in eine Datei
-memprofile mem.outErfasst Speicherzuweisungsdaten und schreibt sie in eine Datei
-memprofilerate nSteuert die Erfassungsrate für Speicherzuweisungen
-mutexprofile mutex.outErfasst Mutex-Konflikte und schreibt sie in eine Datei
-mutexprofilefraction nSetzt die Erfassung von n Goroutine-Konflikten um einen Mutex
-trace trace.outSchreibt Trace-Daten in eine Datei
-outputdir directoryGibt das Ausgabeverzeichnis für die oben genannten Dateien an

Beispiele_tests

Beispiele_tests dienen nicht wie die anderen drei Testtypen dazu, Programmprobleme zu finden. Sie dienen eher dazu, die Verwendung einer Funktion zu demonstrieren und als Dokumentation zu fungieren. Beispiele_tests sind kein offiziell definiertes Konzept und keine feste Konvention, sondern eher eine in der Praxis entstandene Gewohnheit. Ob Sie sich daran halten, liegt beim Entwickler. Beispiele_tests kommen in der Standardbibliothek sehr häufig vor und sind normalerweise von offiziellen Entwicklern geschriebene Code-Beispiele.

Unit-Tests

Unit-Tests testen die kleinste testbare Einheit in Software. Die Definition der Einheit hängt vom Entwickler ab – es kann eine Struktur, ein Paket, eine Funktion oder ein Typ sein.

Benchmark-Tests

Benchmark-Tests werden auch Leistungstests genannt und dienen normalerweise dazu, Speicherverbrauch, CPU-Auslastung, Ausführungszeit und andere Leistungskennzahlen zu testen.

Fuzz-Tests

Fuzz-Tests sind eine in Go 1.18 eingeführte neue Funktion, eine Erweiterung von Unit-Tests und Benchmark-Tests. Der Unterschied besteht darin, dass bei den beiden ersteren die Testdaten vom Entwickler manuell geschrieben werden müssen, während Fuzz-Tests über eine Corpus-Bibliothek zufällige Testdaten generieren können.

TIP

Fuzz-Tests ohne den Parameter -fuzz führen nur die Daten aus dem Corpus aus, erzeugen keine zufälligen Testdaten.

Typ-Unterstützung

In Go Fuzz werden folgende Typen unterstützt:

  • string, []byte
  • int, int8, int16, int32/rune, int64
  • uint, uint8/byte, uint16, uint32, uint64
  • float32, float64
  • bool

Golang by www.golangdev.cn edit