Naprawdę zakochałem się w testach jednostkowych i TDD - jestem zainfekowany testowo.
Jednak testy jednostkowe są zwykle stosowane w metodach publicznych. Czasami jednak muszę przetestować pewne założenia-twierdzenia również metodami prywatnymi, ponieważ niektóre z nich są „niebezpieczne”, a refaktoryzacja nie może dalej pomóc. (Wiem, ramy testowania umożliwiają testowanie metod prywatnych).
Stało się więc moim zwyczajem, że zarówno pierwsza, jak i ostatnia linia metody prywatnej są twierdzeniami.
Zauważyłem jednak, że zwykle używam twierdzeń w metodach publicznych (a także prywatnych) tylko dla pewności. Czy może to być „testowanie duplikacji”, ponieważ założenia metody publicznej są testowane z zewnątrz przez system testów jednostkowych?
Czy ktoś mógłby pomyśleć o zbyt wielu twierdzeniach jako zapachu kodu?
źródło
Odpowiedzi:
Te twierdzenia są naprawdę przydatne do testowania twoich założeń, ale służą także innemu bardzo ważnemu celowi: dokumentacji. Każdy czytelnik metody publicznej może odczytać stwierdzenia, aby szybko określić warunki wstępne i końcowe, bez konieczności patrzenia na zestaw testów. Z tego powodu zalecam trzymanie tych asertów ze względów związanych z dokumentacją, a nie ze względów testowych. Technicznie powielasz twierdzenia, ale służą one dwóm różnym celom i są bardzo przydatne w obu przypadkach.
Zachowanie ich jako zapewnień jest lepsze niż zwykłe stosowanie komentarzy, ponieważ aktywnie sprawdzają założenia przy każdym uruchomieniu.
źródło
Wygląda na to, że próbujesz wykonać projekt według umowy ręcznie.
Wykonanie DbC jest dobrym pomysłem, ale powinieneś przynajmniej rozważyć przejście na język, który obsługuje go natywnie (taki jak Eiffel ) lub przynajmniej użyć ramowej umowy dla swojej platformy (np. Microsoft Code Contracts dla .NETjest całkiem niezły, prawdopodobnie najbardziej wyrafinowany system kontraktów, nawet potężniejszy niż Eiffel). W ten sposób możesz lepiej wykorzystać siłę kontraktów. Np. Używając istniejącego frameworka, możesz ujawnić kontrakty w dokumentacji lub IDE (np. Kontrakty kodowe dla .NET są pokazane w IntelliSense, a jeśli masz VS Ultimate, możesz nawet sprawdzić statycznie przez automatyczną weryfikację twierdzeń w czasie kompilacji, podczas gdy piszesz; podobnie wiele ram kontraktów Java ma dokumentację JavaDoc, która automatycznie wyodrębni kontrakty do dokumentacji interfejsu API JavaDoc).
I nawet jeśli okaże się, że w twojej sytuacji nie ma alternatywy dla zrobienia tego ręcznie, teraz przynajmniej wiesz, jak się nazywa, i możesz o tym poczytać.
Krótko mówiąc: jeśli rzeczywiście robisz DbC, nawet jeśli o tym nie wiesz, te twierdzenia są całkowicie w porządku.
źródło
Ilekroć nie masz pełnej kontroli nad parametrami wejściowymi, bardzo dobrym pomysłem jest przetestowanie z góry prostych błędów. Na przykład brak wartości null.
To nie jest powielanie swoich badań, jak powinny sprawdzić, czy kod zawiedzie odpowiednio podane złych parametrów wejściowych, a następnie udokumentować , że .
Nie sądzę, że powinieneś twierdzić o parametrach zwracanych (chyba że masz jawnie niezmiennik, który czytelnik powinien zrozumieć). Jest to także praca najbardziej nieprzystosowanych.
Osobiście nie podoba mi się to
assert
w Javie, ponieważ można je wyłączyć, a wtedy jest to fałszywe zabezpieczenie.źródło
Myślę, że stosowanie asercji w metodach publicznych jest jeszcze ważniejsze, ponieważ tam nie kontrolujesz danych wejściowych i istnieje większe prawdopodobieństwo złamania założenia.
Testowanie warunków wejściowych powinno odbywać się we wszystkich metodach publicznych i chronionych. Jeśli dane wejściowe są przekazywane bezpośrednio do metody prywatnej, testowanie danych wejściowych może być zbędne.
Testowanie warunków wyjściowych (np. Stan obiektu lub zwracana wartość! = Null) powinno odbywać się w metodach wewnętrznych (np. Metodach prywatnych). Jeśli dane wyjściowe są przekazywane bezpośrednio z metody prywatnej do wyniku metody publicznej bez dodatkowych obliczeń lub zmian stanu wewnętrznego, wówczas testowanie warunków wyjściowych metody publicznej może być zbędne.
Zgadzam się jednak z Oleksi, że redundancja może zwiększyć czytelność, a także może zwiększyć konserwowalność (jeśli bezpośrednie przydzielanie lub zwrot nie będzie już w przyszłości).
źródło
Trudno jest być niezależnym od języka w tej kwestii, ponieważ szczegóły, w jaki sposób realizowane są twierdzenia i „poprawna” obsługa błędów / wyjątków, mają wpływ na odpowiedź. Oto moje 0,02 USD, oparte na mojej wiedzy o Javie i C ++.
Asercje w prywatnych metodach są dobre, zakładając, że nie przesadzasz i nie umieszczasz ich wszędzie . Jeśli stosujesz naprawdę proste metody lub wielokrotnie sprawdzasz rzeczy takie jak niezmienne pola, niepotrzebnie zaśmiecasz kod.
Twierdzeń w metodach publicznych na ogół najlepiej unikać. Nadal powinieneś robić takie rzeczy, jak sprawdzanie, czy umowa metody nie jest naruszona, ale jeśli tak, powinieneś zgłaszać wyjątki o odpowiednim typie z sensownymi komunikatami, w miarę możliwości przywracać stan itp. (Co @rwong nazywa „pełnym” właściwe postępowanie z błędami ”).
Ogólnie rzecz biorąc, należy używać tylko twierdzeń, aby pomóc swój rozwój / debugowania. Nie możesz założyć, że ktokolwiek używa twojego API, będzie miał nawet włączone asercje, gdy użyje twojego kodu. Chociaż mają one pewne zastosowanie w dokumentowaniu kodu, często istnieją lepsze sposoby dokumentowania tych samych rzeczy (tj. Dokumentacji metod, wyjątków).
źródło
Dodając do listy (głównie) wyjątkowych odpowiedzi, innym powodem wielu twierdzeń i powielania, jest to, że nie wiesz jak, kiedy lub przez kogo klasa zostanie zmodyfikowana w ciągu jej życia. Jeśli piszesz wyrzuć kod, który będzie martwy za rok, nie martw się. Jeśli piszesz kod, który będzie używany za ponad 20 lat, będzie wyglądał zupełnie inaczej - a przyjęte przez Ciebie założenie może już nie być aktualne. Facet, który dokona tej zmiany, podziękuje ci za twierdzenia.
Również nie wszyscy programiści są doskonali - ponownie twierdzenia oznaczają, że jeden z tych „wpadek” nie rozprzestrzeni się zbyt daleko.
Nie lekceważ wpływu, jaki te twierdzenia (i inne kontrole założeń) będą miały na obniżenie kosztów utrzymania.
źródło
Posiadanie duplikatów stwierdzeń nie jest samo w sobie złe, ale posiadanie takich stwierdzeń „po prostu upewnienie się” nie jest najlepsze. To naprawdę sprowadza się do tego, co dokładnie każdy test próbuje osiągnąć. Podaj tylko to, co jest absolutnie potrzebne. Jeśli test używa Moq do sprawdzenia, czy metoda została wywołana, tak naprawdę nie ma znaczenia, co stanie się po wywołaniu tej metody, test dotyczy jedynie upewnienia się, że metoda została wywołana.
Jeśli każdy pojedynczy test jednostkowy zawiera ten sam zestaw twierdzeń, z wyjątkiem jednego lub dwóch, wówczas po nieco refaktoryzacji wszystkie testy mogą zakończyć się niepowodzeniem z tego samego powodu, zamiast pokazywać prawdziwy wpływ refaktora. Możesz skończyć w sytuacji, gdy uruchomisz wszystkie testy, wszystkie kończą się niepowodzeniem, ponieważ każdy test ma te same stwierdzenia, naprawiasz tę awarię, uruchamiasz testy ponownie, nieudane z innego powodu, naprawiasz tę awarię. Powtarzaj, aż skończysz.
Weź również pod uwagę utrzymanie projektu testowego. Co się stanie, gdy dodasz nowy parametr lub dane wyjściowe zostaną nieco zmodyfikowane, czy musiałbyś wrócić przez szereg testów i zmienić aser lub dodać aser? I w zależności od kodu możesz skończyć o wiele więcej, aby upewnić się, że wszystkie twierdzenia przejdą.
Rozumiem urok zachęcania do uwzględnienia duplikatów w teście jednostkowym, ale to naprawdę przesada. Poszedłem tą samą ścieżką z moim pierwszym projektem testowym. Odszedłem od tego, ponieważ sama konserwacja doprowadzała mnie do szału.
źródło
Jeśli Twoja struktura testowania pozwala na akcesoria, dobrym pomysłem jest również testowanie jednostkowe metod prywatnych (IMO).
Ja robię. Twierdzenia są w porządku, ale twoim pierwszym celem powinno być zrobienie tego, aby scenariusz nie był nawet możliwy ; nie tylko, że tak się nie dzieje.
źródło
To zła praktyka.
Nie powinieneś testować metod publicznych / prywatnych. Powinieneś przetestować całą klasę. Tylko upewnij się, że masz dobry zasięg.
Jeśli wybierzesz (prymitywny) sposób testowania każdej metody osobno jako ogólną zasadę, bardzo trudno będzie ci w przyszłości zmienić klasę. I to jedna z najlepszych rzeczy, które umożliwia TDD.
Poza tym jest to powielanie. Ponadto sugeruje, że autor kodu tak naprawdę nie wiedział, co robi. Zabawne jest to, że tak .
Niektóre osoby traktują swoje testy z mniejszą ostrożnością niż kod produkcyjny. Nie powinni. Jeśli już, to moje doświadczenie sugeruje nawet ostrożniejsze traktowanie testów. Są tego warte.
źródło