Odpowiedzi:
Sposób organizacji testów jest raczej nieistotny w porównaniu ze znaczeniem ich posiadania.
Najważniejsze w dobrym zestawie testowym jest to, że obejmuje on całą funkcjonalność; dzięki temu za każdym razem, gdy pojawi się defekt regresji, od razu zauważysz. To, czy napisać jeden test dla każdej metody, jeden test dla każdej kombinacji wartości wejściowych metody, czy nawet jeden test dla każdej możliwej ścieżki kodu w ramach tej metody, jest mniej ważne. To, czy zorganizować te testy w kilka, czy w wiele klas testowych, jest jeszcze mniej ważne: zestaw testów powinien zawsze kończyć się pełnym sukcesem, więc nie ma znaczenia, czy nie przejdzie jednego z trzech czy dwóch z siedemnastu testów - oba są błędne i muszą być naprawiony.
Oczywiście, kod testowy jest również kodem, więc powinien być zgodny ze zwykłymi najlepszymi praktykami w zakresie konserwacji, modułowości itp. Ale o tym musi decydować stopień łatwości konserwacji samego zestawu testów, a nie zależność klas testowych klasy, które testują. Obie wspomniane zasady mogą pomóc Ci zapamiętać, gdzie znaleźć rzeczy, jeśli konsekwentnie je przestrzegasz, ale w tym przypadku spójność jest ważniejsza niż wybór polityki.
Zgodnie z twoim konkretnym pytaniem konwencja JUnit ma mieć zgodność 1: 1 między klasami aplikacji ( Foo1.java
, Foo2.java
) a klasami testowymi JUnit ( Foo1Test.java
, Foo2Test.java
).
To powiedziawszy, zgadzam się całym sercem z podkreśleniem przez Kiliana znaczenia ducha / celów testów jednostkowych w stosunku do wszelkich możliwych schematów organizacyjnych. Wybierz niektóre konwencje i trzymaj się ich przez większość czasu, jednocześnie ostrożnie dopuszczając wyjątki od swoich konwencji, gdy są one uzasadnione.
Czy lepiej jest mieć osobną klasę dla każdej metody, czy mieć tylko jedną klasę testową dla każdej rzeczywistej klasy?
Jeśli musisz napisać osobne klasy testowe dla metod jednej klasy, masz zły projekt. Metody powinny być małe, łatwe do odczytania, łatwe do przetestowania i łatwe do zmiany. Testy mogą być nieco dłuższe niż oryginalny kod ze względu na tworzenie danych testowych, kpiny itp., Ale nie powinny być znacznie dłuższe. Jeśli tak, testowana klasa jest zbyt złożona i na pewno ma więcej niż jedną rzecz ( zasada pojedynczej odpowiedzialności ): popracuj nad projektem.
Myślę, że zarówno „jedna klasa testowa na metodę”, jak i „jedna klasa testowa na klasę” są zwykle zbyt ekstremalne.
Ogólnie rzecz biorąc, chcesz mieć jedną kontrolę na metodę testową / test jednostkowy. Mogą to być na przykład liczne twierdzenia sprawdzające, czy list.isEmpty = true
a list.Length = 0
, a więc jedna metoda testowa / test jednostkowy na zachowanie.
Ułatwia to wymyślenie nazwy metody testowej opisującej zachowanie. Chcesz pogrupować metody testowe w klasę testową, więc kiedy je czytasz test classname.test method
, ma to sens. Zwykle mają one wspólny kod instalacyjny, który następnie można łatwo umieścić w konfiguracji testowej / urządzeniu. W zależności od testowanej klasy może to być jedna klasa testowa dla całej klasy, a także jedna klasa testowa dla jednej metody. Ale zwykle będzie to gdzieś pośrodku.
Podobnie jak w przypadku normalnego kodu, chcesz, aby testy były jak najbardziej czytelne. Pomaga mi przestrzeganie stylu organizowania kodu testowego określonego przez BDD „kiedy-to-wtedy” lub „zorganizuj-działaj-twierdzę”. Klasa testowa może to mieć, to konfiguracja. Następnie każda metoda testowa w tej klasie korzysta z danej (lub jej części) i ma jedną, kiedy i jedną wtedy.
Pomyśl również o testach jednostkowych jako dokumentacji dotyczącej korzystania z funkcjonalności testowanej klasy. Dzięki dobrym testom jednostkowym możesz przeczytać testy, aby dowiedzieć się, jak korzystać z funkcjonalności klasy, której chcesz użyć, i jakie będą dokładnie efekty.
Kiedy coś się psuje, a test jednostkowy się nie powiedzie, chcesz, aby zrozumienie, co się zepsuło, było jak najłatwiejsze, jedno stwierdzenie na test bardzo tu pomaga. Gdy w jednym teście jest wiele asercji, tylko pierwsza nie powiedzie się, a następnie metoda zakończy działanie, więc nie wiesz, czy inne zachowanie testowane w kolejnych testach również zostanie zerwane, dopóki nie naprawisz rzeczy, która spowodowała, że pierwsze asercja zakończyło się niepowodzeniem. Z jednym stwierdzeniem wszystkie pozostałe metody testowe są nadal wykonywane i znacznie szybciej jest zrozumieć głębię niepowodzenia.
Oczywiście zgadzam się z Kilianem Fothem: w praktyce możesz mieć szczęście, przeprowadzając kilka testów jednostkowych kodu, nad którym pracujesz. A każdy mały zlokalizowany test jest lepszy niż żaden test, lub tylko duże testy integracyjne, które są uruchamiane na serwerze kompilacji, zajmują dużo czasu i zwykle nie są bardzo zlokalizowane (nie mówią szybko, gdzie jest błąd - ty Będę musiał trochę popracować).
Myślę, że to prawda, że każda klasa ma swoją klasę testową. Chodzi o scentralizowanie wszystkich testów jednostkowych związanych z klasą docelową w jednej klasie testowej. Wtedy na przykład MyClass.java
zostanie wywołana klasa testowa MyClassTest.java
.