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
testgenannt wird. - Testdateien: Testdateien enden normalerweise auf
_test.go. Wenn Sie beispielsweise eine bestimmte Funktion testen möchten, benennen Sie die Dateifunction_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.gooderexample_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-TestsTestXXXX, Benchmark-TestsBenchmarkXXXXund Fuzz-TestsFuzzXXXX. 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:
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:
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:
$ 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.:
$ 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, -vUm den Cache zu deaktivieren, fügen Sie den Parameter -count=1 hinzu.
Sie können auch eine einzelne Testdatei angeben:
$ go test example_test.go
ok command-line-arguments 0.457sOder Sie können einen bestimmten Testfall in einer Testdatei angeben:
$ go test -run ExampleSay
PASS
ok golearn/test 0.038sObwohl 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:
$ 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.040sJetzt 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:
$ go test -bench .Verwenden Sie den Parameter -run, um bestimmte Tests auszuführen:
$ 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.
| Parameter | Beschreibung |
|---|---|
-o file | Gibt den Namen der kompilierten Binärdatei an |
-c | Kompiliert nur die Testdateien, führt sie aber nicht aus |
-json | Gibt Test-Logs im JSON-Format aus |
-exec xprog | Führt Tests mit xprog aus, entspricht go run |
-bench regexp | Wählt Benchmark-Tests aus, die mit regexp übereinstimmen |
-fuzz regexp | Wählt Fuzz-Tests aus, die mit regexp übereinstimmen |
-fuzztime t | Automatische Endzeit für Fuzz-Tests, t ist ein Zeitintervall, bei Einheit x bedeutet es Anzahl |
-fuzzminimizetime t | Minimale Laufzeit für Fuzz-Tests |
-count n | Führt Tests n-mal aus, Standard ist 1 |
-cover | Aktiviert die Testabdeckungsanalyse |
-covermode set,count,atomic | Setzt den Modus für die Testabdeckungsanalyse |
-cpu | Setzt GOMAXPROCS für die Testausführung |
-failfast | Startet keine neuen Tests nach dem ersten Fehlschlag |
-list regexp | Listet Testfälle auf, die mit regexp übereinstimmen |
-parallel n | Erlaubt parallele Ausführung von Testfällen, die t.Parallel aufrufen |
-run regexp | Führt nur Testfälle aus, die mit regexp übereinstimmen |
-skip regexp | Überspringt Testfälle, die mit regexp übereinstimmen |
-timeout d | Wenn ein einzelner Test länger als das Zeitintervall d dauert, wird panic ausgelöst |
-shuffle off,on,N | Mischt die Ausführungsreihenfolge der Tests, N ist der Zufallsseed |
-v | Gibt detailliertere Test-Logs aus |
-benchmem | Erfasst Speicherzuweisungen in Benchmark-Tests |
-blockprofile block.out | Erfasst Goroutine-Blockierungen und schreibt sie in eine Datei |
-blockprofilerate n | Steuert die Blockierungs-Erfassungsrate |
-coverprofile cover.out | Erfasst Testabdeckungsdaten und schreibt sie in eine Datei |
-cpuprofile cpu.out | Erfasst CPU-Daten und schreibt sie in eine Datei |
-memprofile mem.out | Erfasst Speicherzuweisungsdaten und schreibt sie in eine Datei |
-memprofilerate n | Steuert die Erfassungsrate für Speicherzuweisungen |
-mutexprofile mutex.out | Erfasst Mutex-Konflikte und schreibt sie in eine Datei |
-mutexprofilefraction n | Setzt die Erfassung von n Goroutine-Konflikten um einen Mutex |
-trace trace.out | Schreibt Trace-Daten in eine Datei |
-outputdir directory | Gibt 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,[]byteint,int8,int16,int32/rune,int64uint,uint8/byte,uint16,uint32,uint64float32,float64bool
