Widziałem kilka różnych strategii nazewnictwa pakietów testowych w Go i chciałem wiedzieć, jakie są zalety i wady każdego z nich i którego powinienem użyć.
Strategia 1:
Nazwa pliku: github.com/user/myfunc.go
package myfunc
Nazwa pliku testowego: github.com/user/myfunc_test.go
package myfunc
Zobacz przykład bzip2 .
Strategia 2:
Nazwa pliku: github.com/user/myfunc.go
package myfunc
Nazwa pliku testowego: github.com/user/myfunc_test.go
package myfunc_test
import (
"github.com/user/myfunc"
)
Zobacz przykład drutu .
Strategia 3:
Nazwa pliku: github.com/user/myfunc.go
package myfunc
Nazwa pliku testowego: github.com/user/myfunc_test.go
package myfunc_test
import (
. "myfunc"
)
Zobacz ciągi dla przykładu.
Wydaje się, że biblioteka standardowa Go używa kombinacji strategii 1 i 2. Której z trzech opcji powinienem użyć? Jest to uciążliwe dołączanie package *_test
do moich pakietów testowych, ponieważ oznacza to, że nie mogę przetestować prywatnych metod mojego pakietu, ale może istnieje ukryta zaleta, której nie jestem świadomy?
źródło
Odpowiedzi:
Podstawowa różnica między trzema wymienionymi strategiami polega na tym, czy kod testowy znajduje się w tym samym pakiecie co testowany kod. Decyzję o użyciu
package myfunc
lubpackage myfunc_test
w pliku testowego zależy od tego, czy chcesz wykonać białoskrzynkowe lub czarnej skrzynki testowania.Nie ma nic złego w używaniu obu metod w projekcie. Na przykład możesz mieć
myfunc_whitebox_test.go
imyfunx_blackbox_test.go
.Porównanie pakietów kodów testowych
package myfunc_test
, które zapewni, że używasz tylko wyeksportowanych identyfikatorów .package myfunc
, aby mieć dostęp do niewyeksportowanych identyfikatorów. Dobre dla testów jednostkowych, które wymagają dostępu do nieeksportowanych zmiennych, funkcji i metod.Porównanie strategii wymienionych w pytaniu
myfunc_test.go
używapackage myfunc
- w tym przypadku kod testowymyfunc_test.go
będzie w tym samym pakiecie co testowany kodmyfunc.go
, który jestmyfunc
w tym przykładzie.myfunc_test.go
używapackage myfunc_test
- w tym przypadku kod testowy wmyfunc_test.go
„zostanie skompilowany jako oddzielny pakiet, a następnie połączony i uruchomiony z głównym testowym plikiem binarnym”. [Źródło: wiersze 58–59 w kodzie źródłowym test.go ]myfunc_test.go
używa,package myfunc_test
ale importujemyfunc
przy użyciu notacji z kropkami - jest to wariant strategii 2, ale używa notacji kropkowej do importumyfunc
.źródło
_test.go
oddzielnym pakietem niż testowany pakiet (takie samo zachowanie jak w Strategii 2). Wydaje się, że nie jest to udokumentowane na github.com/golang/go/issues/15315_test.go
o_test
nazwie niebędącej pakietem zawierającej a,func init()
który zmienia jakąś globalną zmienną pakietu do testowania. Myliłem się..
nie rozwiązuje problemu z widelcem. To nie jest względny import. Po prostu importuje identyfikatory „do bieżącego pakietu”.To zależy od zakresu twoich testów. Testy wysokiego poziomu (integracja, akceptacja itp.) Powinny być prawdopodobnie umieszczone w osobnym pakiecie, aby upewnić się, że używasz pakietu za pośrednictwem wyeksportowanego API.
Jeśli masz duży pakiet z wieloma elementami wewnętrznymi, które muszą zostać przetestowane, użyj tego samego pakietu do testów. Ale to nie jest zaproszenie do twoich testów, aby uzyskać dostęp do jakiegokolwiek stanu prywatnego. To uczyniłoby refaktoryzację koszmarem. Kiedy piszę struktury w go , często implementuję interfejsy. To te metody interfejsu wywołuję z moich testów, a nie wszystkie metody / funkcje pomocnika z osobna.
źródło
Powinieneś używać strategii 1, kiedy tylko jest to możliwe. Możesz użyć specjalnej
foo_test
nazwy pakietu, aby uniknąć cykli importu, ale to głównie tam, więc standardowa biblioteka może być testowana za pomocą tego samego mechanizmu. Na przykładstrings
nie można przetestować strategii 1, ponieważtesting
pakiet zależy odstrings
. Jak powiedziałeś, ze strategią 2 lub 3 nie masz dostępu do prywatnych identyfikatorów pakietu, więc zwykle lepiej go nie używać, chyba że musisz.źródło
Jedna ważna uwaga, o której chciałbym dodać
import .
z Golang CodeReviewComments :import .
Forma może być użyteczne w badaniach, że ze względu na koliste zależności, nie mogą być wykonane w skład pakietu testowany:W tym przypadku plik testowy nie może znajdować się w pakiecie foo, ponieważ używa
bar/testutil
, który importuje foo. Dlatego używamy terminu „import”. form, aby plik udawał, że jest częścią pakietu foo, nawet jeśli tak nie jest.Z wyjątkiem tego jednego przypadku, nie używaj
import .
w swoich programach. To sprawia, że programy są znacznie trudniejsze do odczytania, ponieważ nie jest jasne, czy nazwa taka jak Quux jest identyfikatorem najwyższego poziomu w bieżącym pakiecie, czy w pakiecie importowanym.źródło