Konwencja nazewnictwa dla pakietów testowych

11

Właściwie nazywamy nasze pakiety testowe tak, jak ich odpowiedniki do testowania. W rezultacie otrzymujemy następującą strukturę:

src/main/java
    com.hello.world
        helloWorld.java
src/test/java
    com.hello.world
        helloWorldTest.java

Zawsze czułem, że nie jest to zbyt mądre, ponieważ nie można odróżnić „test” od „testowania”, jeśli podano tylko nazwę pakietu. Z drugiej strony tak naprawdę nie znalazłem przypadku, w którym to ma znaczenie. Czy dobrą praktyką jest stosowanie tych samych konwencji nazewnictwa dla obu pakietów (dla przypadków testowych i klas źródłowych)? Jeśli nie, jakie byłoby lepsze podejście?

OddDev
źródło
1
Nie mam pojęcia, czy to dobra praktyka, ale jest popularna. Druga opcja (wstawienie „Test” w nazwie pakietu, nazwach metod itp.) Nieco za bardzo przypomina „Smurf nazewnictwo”. Jak mówisz, trudno jest pomyśleć o przypadkach, w których niemożność „rozróżnienia” między „testem” a „testowaniem”, gdyby tylko podano nazwę pakietu, stanowiłaby problem.
David Arno,
@DavidArno Dziękuję za Twój wkład :) Jak zatem uniknąć nazywania smerfa? Mam na myśli, że skończymy z com.hello.world.test.helloWorld.java, prawda?
OddDev,
W „smurf” problem jest kiedy masz metodę XXXTest()w com.hello.world.test.helloWorldTest.java. Zaleca się, aby „Test” pojawiał się tylko raz na ścieżce, więc albo (a) użyj testu w nazwie pakietu (i nazwij plik testowy tak samo jak testowany plik) lub (b) ustaw nazwę pakietu na to samo i dodaj „test” do nazwy pliku / klasy.
David Arno,
@DavidArno Ah, dziękuję za wyjaśnienie! Źle zrozumiałem twój pierwszy komentarz. Mam to teraz.
OddDev,
Dobrze bym twierdzą, że gdyby nie było jasne, ja dostałem mój pierwszy komentarz źle :)
David Arno

Odpowiedzi:

11

To dobra konwencja.

Czasami chcesz pisać testy jednostkowe również dla klas i metod prywatnych. Nie będziesz mógł wywoływać ich z klasy testów jednostkowych umieszczonych w innym pakiecie.

Nie powinno być żadnych wątpliwości co do posiadania klas testów jednostkowych w tej samej przestrzeni nazw, ponieważ nie powinny one znajdować się w ścieżce klas podczas kompilacji lub uruchamiania kodu produkcyjnego.

Oto przykład małego modułu z publicznym interfejsem, publiczną klasą fabryki i dwiema klasami implementacji pakietów:

src/main/java:
    com.hello.transmogrifier
        public interface Transmogrifier
        public class TransmogrifierFactory
        class MapTransmogrifier implements Transmogrifier
        class ListTransmogrifier implements Transmogrifier

scr/test/java:
    com.hello.transmogrifier
        public class TransmogrifierFactoryTest
        public class MapTransmogrifierTest
        public class ListTransmogrifierTest

Ukrywanie implementacji interfejsu Transmogrifier może być dobrym wyborem projektowym. Być może za wybór implementacji odpowiada klasa fabryczna.

Ponieważ implementacje są prywatne dla pakietów, należy umieścić klasy testów jednostkowych w tym samym pakiecie, jeśli chcesz je przetestować bezpośrednio. Jeśli masz klasy testów jednostkowych w jakimś innym pakiecie, masz bezpośredni dostęp do interfejsu publicznego i klasy fabrycznej z testów.

POCHODZIĆ Z
źródło
1
„Zwykle chcesz pisać testy jednostkowe również dla klas i metod prywatnych dla pakietów”. Nie! To naprawdę zła praktyka. Typy prywatne pakietów są szczegółami implementacji i nigdy nie powinny być testowane bezpośrednio. Testuj tylko publiczne interfejsy API.
David Arno,
1
@DavidArno Nie zgadzam się. Zastąpiłem jednak słowo „zwykle” słowem „czasami”, aby uniknąć tej konkretnej dyskusji.
PRZYJEDŹ Z
1
Możesz się nie zgadzać, co chcesz, ale testowanie wewnętrznego działania fragmentu kodu prowadzi zarówno do ścisłego powiązania między tymi wewnętrznymi działaniami a testami, a także do kruchych testów, które łatwo psują się podczas nawet prostego refaktoryzacji. To bardzo zła praktyka.
David Arno,
Jeśli chcę mieć pewność, że wszystkie moje implementacje Transmogrifier działają bez względu na to, co robi fabryka, to napiszę testy jednostkowe, które testują każdą implementację. Zauważ, że implementacje mają wspólny publiczny interfejs API, mimo że klasy są prywatne dla pakietu. Testy te nie powinny zostać przerwane, chyba że zmienię publiczny interfejs API. Właściwie prawdopodobnie napisałbym ogólny test dla Transmogrifiera, a następnie uruchomiłbym go dla każdej implementacji. Chociaż możliwe jest uzyskanie każdej implementacji przy użyciu fabryki, lepiej nie mieć tej zależności podczas testowania Transmogrifiers.
PRZYJEDŹ Z
Pewnego dnia, obejrzysz MapTransmogrifiera ListTransmogrifieri zdecydować, mogą one być wykonane w jednej klasie, więc tworzyć ListMapTransmogrifier, modyfikować fabrykę do korzystania z tego i usunąć dwie klasy. Kod się teraz nie kompiluje, więc musisz zmodyfikować każdy test w obu MapTransmogrifierTesti ListTransmogrifierTestuzyskać kompilację. Test kończy się niepowodzeniem. Czy to ze względu na zmianę testów lub tworzenie ListMapTransmogrifier? Wychodzi debugger, aby dowiedzieć się ... alternatywnie, gdy testy wykorzystują fabrykę, robisz ten refaktor i wszystko wciąż się kompiluje ...
David Arno