Kontekst:
Obecnie pracuję nad małym projektem w Pythonie. Zazwyczaj tworzę swoje klasy za pomocą kilku udokumentowanych metod publicznych, ale głównie zajmuję się koncepcjami wysokiego poziomu (co użytkownik klasy powinien wiedzieć i stosować) oraz szeregiem ukrytych (zaczynających się od podkreślenia) metod, które są odpowiedzialne za przetwarzanie złożone lub niskiego poziomu.
Wiem, że testy są niezbędne, aby zapewnić zaufanie do kodu i upewnić się, że żadna późniejsza modyfikacja nie złamała poprzedniego zachowania.
Problem:
Aby zbudować publiczne metody wyższego poziomu na zaufanej bazie, ogólnie testuję metody prywatne. Łatwiej jest mi ustalić, czy modyfikacja kodu wprowadziła regresje i gdzie. Oznacza to, że te testy wewnętrzne mogą naruszyć niewielkie zmiany i będą musiały zostać naprawione / wymienione
Ale wiem też, że prywatna metoda testowania jednostkowego jest co najmniej sporną koncepcją lub częściej uważaną za złą praktykę. Powodem jest to, że należy przetestować tylko zachowanie publiczne ( zob. )
Pytanie:
Dbam o przestrzeganie najlepszych praktyk i chciałbym zrozumieć:
- dlaczego stosowanie testów jednostkowych metod prywatnych / ukrytych jest złe (jakie jest ryzyko)?
- jakie są najlepsze praktyki, gdy metody publiczne mogą korzystać z niskiego poziomu i / lub złożonego przetwarzania?
Precyzja:
- Nie jest to jak pytanie. Python nie ma prawdziwej koncepcji prywatności, a ukrytych metod po prostu nie ma na liście, ale można ich użyć, gdy znasz ich nazwę
- Nigdy nie uczono mnie zasad i schematów programowania: moje ostatnie zajęcia pochodzą z lat 80-tych ... Nauczyłem się języków głównie metodą prób i niepowodzeń oraz referencji w Internecie (od wielu lat mój ulubiony jest Stack Exchange)
źródło
Odpowiedzi:
Kilka powodów:
Zwykle, gdy masz ochotę przetestować prywatną metodę klasy, jest to zapach projektowy (klasa lodowa, niewystarczająca ilość elementów publicznych wielokrotnego użytku itp.). W grze prawie zawsze występuje jakiś „większy” problem.
Możesz je przetestować za pomocą interfejsu publicznego (w taki sposób chcesz je przetestować, ponieważ w ten sposób klient będzie je wywoływał / używał). Możesz uzyskać fałszywe poczucie bezpieczeństwa, widząc zielone światło na wszystkich pozytywnych testach dla twoich prywatnych metod. O wiele lepiej / bezpieczniej jest testować najnowsze przypadki prywatnych funkcji za pośrednictwem publicznego interfejsu.
Ryzykujesz poważne powielanie testów (testy, które wyglądają / czują się bardzo podobne), testując prywatne metody. Ma to poważne konsekwencje, gdy zmienią się wymagania, ponieważ przerwie się o wiele więcej testów, niż to konieczne. Może także postawić cię w sytuacji, w której trudno jest dokonać refaktoryzacji ze względu na zestaw testowy ... co jest największą ironią, ponieważ zestaw testowy jest po to, aby pomóc ci bezpiecznie przeprojektować i refaktoryzować!
Wskazówka, jeśli nadal masz ochotę przetestować części prywatne (nie używaj jej, jeśli Ci to przeszkadza, i YMMV, ale w przeszłości działało to dobrze dla mnie): czasami pisanie testów jednostkowych dla funkcji prywatnych, aby się upewnić działają dokładnie tak , jak myślisz, że mogą być cenne (szczególnie jeśli nie znasz języka). Jednak po upewnieniu się, że działają, usuń testy i zawsze upewnij się, że publiczne testy są solidne i zostaną wyłapane, jeśli ktoś zrobi rażącą zmianę wspomnianej funkcji prywatnej.
Kiedy testować prywatne metody: Ponieważ ta odpowiedź stała się (nieco) popularna, czuję się zobowiązany do wspomnienia, że „najlepsza praktyka” jest zawsze taka: „najlepsza praktyka”. Nie oznacza to, że powinieneś robić to dogmatycznie lub na ślepo. Jeśli uważasz, że powinieneś przetestować swoje prywatne metody i mieć uzasadniony powód (np. Piszesz testy charakteryzujące starszą aplikację), to przetestuj swoje prywatne metody . Szczególne okoliczności zawsze przeważają nad jakąkolwiek ogólną zasadą lub najlepszą praktyką. Pamiętaj tylko o niektórych rzeczach, które mogą pójść nie tak (patrz wyżej).
Mam odpowiedź, która szczegółowo omawia to na SO, której nie powtórzę tutaj: /programming/105007/should-i-test-private-methods-or-only-public-ones/ 47401015 # 47401015
źródło
bin_search(arr, item)
(publiczny) ibin_search(arr, item, low, hi)
(prywatny, istnieje wiele sposobów wyszukiwania bin), to wszystko, czego potrzebujesz do przetestowania, to publiczne (bin_search(arr, item)
)Biorąc pod uwagę, że jednym z głównych celów testów jednostkowych jest to, że można przefakturować elementy wewnętrzne programu, a następnie być w stanie zweryfikować, czy nie złamano jego funkcjonalności, jest to odwrotne od zamierzonego, jeśli testy jednostkowe działają na tak drobnym poziomie szczegółowości, że każda zmiana kodu programu wymaga przepisania testów.
źródło
Pisanie testów jednostkowych dla metod prywatnych wiąże testy jednostkowe ze szczegółami implementacji.
Testy jednostkowe powinny przetestować zachowanie klasy na zewnętrznej powierzchni klasy (jest to publiczny interfejs API). Testy jednostkowe nie powinny wiedzieć nic o wnętrznościach klasy. Pisanie testów jednostkowych na podstawie szczegółów implementacyjnych klasy wiąże ręce w przypadku refaktoryzacji. Refaktoryzacja prawie na pewno przerwie te testy, ponieważ nie są one częścią stabilnego interfejsu API.
To powiedziawszy dlaczego może chcesz pisać testy jednostkowe dla metod prywatnych?
Istnieje naturalne napięcie między testami jednostkowymi a przyrostowym rozwojem. Twórcy oprogramowania korzystający z REPL (pętla odczytu-ewaluacji-wydruku) mogą zaświadczyć, jak produktywne może być szybkie pisanie i testowanie niewielkich fragmentów funkcjonalności podczas „rozwijania” klasy lub funkcji. Jedynym dobrym sposobem na zrobienie tego w środowiskach, w których przeprowadzane są testy jednostkowe, jest napisanie testów jednostkowych dla metod prywatnych, ale jest to bardzo trudne. Testy jednostkowe wymagają czasu, aby napisać, potrzebujesz rzeczywistej metody testowania, a Twoja platforma testowa musi obsługiwać możliwość zachowania metody prywatnej, aby nie zanieczyszczała twojego zewnętrznego API.
Niektóre ekosystemy, takie jak C # i .NET, mają sposoby na tworzenie środowisk podobnych do REPL (narzędzia takie jak Linqpad to robią), ale ich użyteczność jest ograniczona, ponieważ nie masz dostępu do swojego projektu. Bezpośrednie okno w Visual Studio jest niewygodne; wciąż nie ma pełnej Intellisense, musisz używać w pełni kwalifikowanych nazw i uruchamia kompilację za każdym razem, gdy go używasz.
źródło
Z mojego doświadczenia wynika, że jednostka testująca klasy wewnętrzne, metody zwykle oznaczają, że muszę wyjąć przetestowane funkcje, klasy. Aby stworzyć kolejny poziom abstrakcji.
Prowadzi to do lepszego przestrzegania zasady jednolitej odpowiedzialności.
źródło
Myślę, że to dobre pytanie, ponieważ ujawnia typowy problem podczas testowania zasięgu. Ale dobra odpowiedź powinna powiedzieć, że pytanie nie jest do końca prawda, ponieważ w teorii, powinno nie być w stanie przetestować jednostkę prywatnych metod. Dlatego są prywatne .
Może lepszym pytaniem byłoby „Co powinienem zrobić, gdy chcę przetestować metody prywatne?”, a odpowiedź jest w pewnym stopniu oczywista: należy je udostępnić w sposób umożliwiający testowanie. To niekoniecznie oznacza, że powinieneś upublicznić metodę i to wszystko. Najprawdopodobniej będziesz chciał zrobić wyższą abstrakcję; przenieś do innej biblioteki lub interfejsu API, abyś mógł przeprowadzić testy na tej bibliotece, bez ujawniania tej funkcji w głównym interfejsie API.
Pamiętaj, że istnieje powód, dla którego twoje metody mają różne poziomy dostępności i zawsze powinieneś pomyśleć o tym, w jaki sposób Twoje klasy będą używane na końcu.
źródło