Ich habe in Go verschiedene Benennungsstrategien für Testpakete gesehen und wollte wissen, welche Vor- und Nachteile die einzelnen sind und welche ich verwenden sollte.
Strategie 1:
Dateiname: github.com/user/myfunc.go
package myfunc
Name der Testdatei: github.com/user/myfunc_test.go
package myfunc
Ein Beispiel finden Sie in bzip2 .
Strategie 2:
Dateiname: github.com/user/myfunc.go
package myfunc
Name der Testdatei: github.com/user/myfunc_test.go
package myfunc_test
import (
"github.com/user/myfunc"
)
Ein Beispiel finden Sie unter Draht .
Strategie 3:
Dateiname: github.com/user/myfunc.go
package myfunc
Name der Testdatei: github.com/user/myfunc_test.go
package myfunc_test
import (
. "myfunc"
)
Ein Beispiel finden Sie unter Zeichenfolgen .
Die Go-Standardbibliothek scheint eine Mischung aus Strategie 1 und 2 zu verwenden. Welche der drei sollte ich verwenden? Es ist ein Schmerz, der package *_test
an meine Testpakete angehängt wird, da dies bedeutet, dass ich meine privaten Paketmethoden nicht testen kann, aber vielleicht gibt es einen versteckten Vorteil, den ich nicht kenne?
quelle
Antworten:
Der grundlegende Unterschied zwischen den drei von Ihnen aufgelisteten Strategien besteht darin, ob sich der Testcode im selben Paket befindet wie der zu testende Code. Die Entscheidung für die Verwendung
package myfunc
oderpackage myfunc_test
in der Testdatei hängt davon ab, ob Sie eine White-Box oder eine Black-Box ausführen möchten Tests .Es ist nichts Falsches daran, beide Methoden in einem Projekt zu verwenden. Zum Beispiel könnten Sie
myfunc_whitebox_test.go
und habenmyfunx_blackbox_test.go
.Testcode-Paketvergleich
package myfunc_test
diese Option, um sicherzustellen, dass Sie nur die exportierten Bezeichner verwenden .package myfunc
Sie diese Option, damit Sie Zugriff auf die nicht exportierten Bezeichner haben. Geeignet für Unit-Tests, die Zugriff auf nicht exportierte Variablen, Funktionen und Methoden erfordern.Vergleich der in Frage gestellten Strategien
myfunc_test.go
verwendetpackage myfunc
- In diesem Fall befindet sich der Testcode inmyfunc_test.go
demselben Paket wie der Code, in dem getestet wirdmyfunc.go
wird (myfunc
in diesem Beispiel).myfunc_test.go
verwendetpackage myfunc_test
- In diesem Fall wird der Testcode inmyfunc_test.go
"als separates Paket kompiliert und dann mit der Haupttest-Binärdatei verknüpft und ausgeführt". [Quelle: Zeilen 58–59 in der Quellcode test.go ]myfunc_test.go
verwendetpackage myfunc_test
aber importiertmyfunc
mit der Punktnotation - Dies ist eine Variante von Strategie 2, verwendet jedoch die Punktnotation zum Importierenmyfunc
.quelle
_test.go
getrennt von dem zu testenden Paket aufbewahrt werden (dasselbe Verhalten wie bei Strategie 2). Dies scheint nicht per github.com/golang/go/issues/15315_test.go
mit einem Nicht-_test
Paketnamen gefunden habe, der eine enthält, die einefunc init()
globale Paketvariable zum Testen ändert. Ich lag falsch..
löst dein Gabelproblem nicht. Es ist kein relativer Import. Es importiert nur die Bezeichner "in das aktuelle Paket".Dies hängt vom Umfang Ihrer Tests ab. Tests auf hoher Ebene (Integration, Akzeptanz usw.) sollten wahrscheinlich in einem separaten Paket abgelegt werden, um sicherzustellen, dass Sie das Paket über die exportierte API verwenden.
Wenn Sie ein großes Paket mit vielen Interna haben, die getestet werden müssen, verwenden Sie dasselbe Paket für Ihre Tests. Dies ist jedoch keine Einladung für Ihre Tests, auf einen privaten Status zuzugreifen. Das würde das Refactoring zu einem Albtraum machen. Wenn ich Strukturen in go schreibe, implementiere ich oft Schnittstellen. Es sind diese Schnittstellenmethoden, die ich aus meinen Tests aufrufe, nicht alle Hilfsmethoden / -funktionen einzeln.
quelle
Sie sollten nach Möglichkeit Strategie 1 verwenden. Sie können den speziellen
foo_test
Paketnamen verwenden, um Importzyklen zu vermeiden. Dies ist jedoch meistens der Fall, damit die Standardbibliothek mit demselben Mechanismus getestet werden kann. Zum Beispielstrings
kann nicht mit Strategie 1 getestet werden , da dastesting
Paket hängt davon abstrings
. Wie Sie sagten, haben Sie mit Strategie 2 oder 3 keinen Zugriff auf die privaten Kennungen des Pakets. Daher ist es normalerweise besser, es nicht zu verwenden, es sei denn, Sie müssen.quelle
Ein wichtiger Hinweis, den ich gerne
import .
von Golang CodeReviewComments hinzufügen möchte :Das
import .
Formular kann bei Tests hilfreich sein, die aufgrund zirkulärer Abhängigkeiten nicht Teil des zu testenden Pakets sein können:In diesem Fall kann sich die Testdatei nicht im Paket foo befinden, da sie verwendet wird
bar/testutil
, wodurch foo importiert wird. Also verwenden wir den 'Import'. Formular, damit die Datei vorgibt, Teil des Pakets foo zu sein, obwohl dies nicht der Fall ist.Mit Ausnahme dieses einen Falles nicht
import .
in Ihren Programmen verwenden. Dies erschwert das Lesen der Programme erheblich, da unklar ist, ob ein Name wie Quux im aktuellen Paket oder in einem importierten Paket eine Kennung der obersten Ebene darstellt.quelle