Jeśli piszesz bibliotekę lub aplikację, dokąd idą pliki testów jednostkowych?
Miło jest oddzielić pliki testowe od głównego kodu aplikacji, ale niewygodne jest umieszczenie ich w podkatalogu „testy” w katalogu głównym aplikacji, ponieważ utrudnia importowanie modułów, które będziesz testować.
Czy jest tutaj najlepsza praktyka?
python
unit-testing
code-organization
Tylko czytać
źródło
źródło
Odpowiedzi:
W przypadku pliku
module.py
test jednostkowy powinien być zwykle wywoływanytest_module.py
zgodnie z konwencjami nazewnictwa w języku Python.Istnieje kilka powszechnie akceptowanych miejsc do umieszczenia
test_module.py
:module.py
.../tests/test_module.py
(na tym samym poziomie co katalog kodu).tests/test_module.py
(jeden poziom w katalogu kodów).Wolę numer 1 ze względu na prostotę znajdowania testów i ich importowania. Niezależnie od używanego systemu kompilacji można łatwo skonfigurować uruchamianie plików od
test_
. W rzeczywistości domyślnymunittest
wzorcem używanym do wykrywania testów jesttest*.py
.źródło
Tylko 1 plik testowy
Jeśli jest tylko 1 plik testowy, zaleca się umieszczenie go w katalogu najwyższego poziomu:
Uruchom test w CLI
Wiele plików testowych
Jeśli ma wiele plików testowych, umieść go w
tests
folderze:Uruchom test w CLI
Posługiwać się
unittest discovery
unittest discovery
znajdzie wszystkie testy w folderze pakietu.Utwórz
__init__.py
wtests/
folderzeUruchom test w CLI
Odniesienie
pytest
Dobre praktyki dotyczące układu testuunittest
Struktura testu jednostkowego
źródło
Powszechną praktyką jest umieszczanie katalogu testów w tym samym katalogu nadrzędnym co moduł / pakiet. Więc jeśli moduł nazywał się foo.py, układ katalogu wyglądałby następująco:
Oczywiście nie ma na to jednego sposobu. Możesz także utworzyć podkatalog testów i zaimportować moduł za pomocą importu bezwzględnego .
Gdziekolwiek umieścisz swoje testy, polecam użyć nosa do ich przeprowadzenia. Nos przeszukuje twoje katalogi w poszukiwaniu testów. W ten sposób możesz przeprowadzać testy wszędzie tam, gdzie jest to najbardziej sensowne z organizacyjnego punktu widzenia.
źródło
Mieliśmy to samo pytanie, pisząc Pythoscope ( https://pypi.org/project/pythoscope/ ), który generuje testy jednostkowe programów w języku Python. Przed wybraniem katalogu zapytaliśmy ludzi na temat testowania na liście python, było wiele różnych opinii. Na koniec postanowiliśmy umieścić katalog „testy” w tym samym katalogu, co kod źródłowy. W tym katalogu generujemy plik testowy dla każdego modułu w katalogu nadrzędnym.
źródło
Ja również zwykle umieszczam swoje testy jednostkowe w samym pliku, jak zauważa Jeremy Cantrell powyżej, chociaż zwykle nie umieszczam funkcji testowej w głównej części, ale raczej umieszczam wszystko w
blok. To kończy się dodaniem dokumentacji do pliku jako „przykładowego kodu” na temat używania testowanego pliku python.
Powinienem dodać, że mam tendencję do pisania bardzo ciasnych modułów / klas. Jeśli twoje moduły wymagają bardzo dużej liczby testów, możesz umieścić je w innym, ale nawet wtedy nadal dodam:
Dzięki temu każdy, kto czyta kod źródłowy, wie, gdzie szukać kodu testowego.
źródło
Co jakiś czas sprawdzam temat umieszczania testów i za każdym razem większość zaleca osobną strukturę folderów obok kodu biblioteki, ale stwierdzam, że za każdym razem argumenty są takie same i nie są tak przekonujące. Kładę moje moduły testowe gdzieś obok modułów podstawowych.
Głównym powodem tego jest: refaktoryzacja .
Kiedy się poruszam, chcę, aby moduły testowe poruszały się z kodem; łatwo jest przegrać testy, jeśli są w osobnym drzewie. Bądźmy szczerzy, prędzej czy później skończysz z zupełnie inną strukturą folderów, taką jak django , flask i wiele innych. Co jest w porządku, jeśli cię to nie obchodzi.
Główne pytanie, które powinieneś sobie zadać, brzmi:
Piszę:
Jeśli:
Osobny folder i dodatkowy wysiłek w celu utrzymania jego struktury mogą być bardziej odpowiednie. Nikt nie będzie narzekał na wdrożenie testów w produkcji .
Ale równie łatwo jest wykluczyć testy z dystrybucji, gdy są mieszane z folderami podstawowymi; umieść to w setup.py :
Jeśli b:
Możesz życzyć - jak każdy z nas - że piszesz biblioteki wielokrotnego użytku, ale przez większość czasu ich życie jest związane z życiem projektu. Priorytetem powinna być możliwość łatwego utrzymania projektu.
Następnie, jeśli wykonałeś dobrą robotę, a twój moduł dobrze pasuje do innego projektu, prawdopodobnie zostanie skopiowany - nie rozwidlony lub utworzony w osobnej bibliotece - do tego nowego projektu i przeniesie testy, które leżą obok niego w tej samej strukturze folderów jest łatwe w porównaniu z testowaniem wyników w bałaganie, którym stał się osobny folder testowy. (Możesz argumentować, że nie powinien to być bałagan, ale bądźmy realistami).
Tak więc wybór należy do ciebie, ale twierdzę, że przy pomieszanych testach osiągasz te same rzeczy, co w osobnym folderze, ale przy mniejszym wysiłku w utrzymaniu porządku.
źródło
Korzystam z
tests/
katalogu, a następnie importuję główne moduły aplikacji za pomocą importu względnego. Tak więc w MyApp / testy / foo.py mogą być:aby zaimportować
MyApp.foo
moduł.źródło
Nie wierzę, że istnieje „najlepsza praktyka”.
Umieszczam swoje testy w innym katalogu poza kodem aplikacji. Następnie dodaję główny katalog aplikacji do sys.path (umożliwiając importowanie modułów z dowolnego miejsca) w moim skrypcie testera (który robi również inne rzeczy) przed uruchomieniem wszystkich testów. W ten sposób nigdy nie muszę usuwać katalogu testów z głównego kodu, gdy go wypuszczam, co oszczędza mi czasu i wysiłku, nawet jeśli jest to bardzo mała ilość.
źródło
os.sys.path.append(os.dirname('..'))
Z mojego doświadczenia w tworzeniu frameworków testujących w Pythonie sugerowałbym umieszczenie testów jednostkowych Pythona w osobnym katalogu. Zachowaj symetryczną strukturę katalogów. Byłoby to pomocne w pakowaniu tylko podstawowych bibliotek, a nie w pakowanie testów jednostkowych. Poniżej zaimplementowano schemat.
W ten sposób, gdy pakujesz te biblioteki za pomocą rpm, możesz po prostu spakować główne moduły biblioteczne (tylko). Pomaga to w utrzymaniu, szczególnie w zwinnym środowisku.
źródło
Polecam sprawdzenie niektórych głównych projektów Pythona na GitHub i uzyskanie pomysłów.
Kiedy twój kod się powiększy i dodasz więcej bibliotek, lepiej jest utworzyć folder testowy w tym samym katalogu, w którym znajduje się setup.py i utworzyć kopię lustrzaną struktury katalogu projektu dla każdego typu testu (unittest, integracja, ...)
Na przykład, jeśli masz strukturę katalogów, taką jak:
Po dodaniu folderu testowego będziesz miał strukturę katalogów, takich jak:
Wiele poprawnie napisanych pakietów Pythona używa tej samej struktury. Bardzo dobrym przykładem jest pakiet Boto. Sprawdź https://github.com/boto/boto
źródło
matplotlib
ma to podmatplotlib/lib/matplotlib/tests
( github.com/matplotlib/matplotlib/tree/… ),sklearn
ma to podscikitelearn/sklearn/tests
( github.com/scikit-learn/scikit-learn/tree/master/sklearn/tests )Jak to robię...
Struktura folderów:
Setup.py wskazuje src / jako lokalizację zawierającą moduły moich projektów, a następnie uruchamiam:
Co dodaje mój projekt do pakietów stron, wskazując na moją kopię roboczą. Do uruchomienia moich testów używam:
Za pomocą dowolnego testera, który skonfigurowałem.
źródło
code.py
. Bardziej sensowne byłoby nazywanie katalogu najwyższego poziomu „projektem”.Wolę katalog testów najwyższego poziomu. Oznacza to, że import staje się nieco trudniejszy. Do tego mam dwa rozwiązania:
test_suite='tests.runalltests.suite'
dosetup()
, a może po prostu uruchomić testy:python setup.py test
PYTHONPATH=. python tests/runalltests.py
Oto jak te rzeczy są obsługiwane przez kod w M2Crypto:
Jeśli wolisz przeprowadzać testy z testami nosa, może być konieczne wykonanie czegoś nieco innego.
źródło
Używamy
W każdym pliku testowego możemy wstawić
../src/
wsys.path
. To nie jest najlepsze rozwiązanie, ale działa. Myślę, że byłoby wspaniale, gdyby ktoś pojawił się w Javie z czymś takim jak maven, co daje standardowe konwencje, które działają, bez względu na projekt nad którym pracujesz.źródło
Jeśli testy są proste, po prostu umieść je w dokumentacji - większość frameworków testowych dla Pythona będzie w stanie tego użyć:
W przypadku innych bardziej zaangażowanych testów umieściłem je w
../tests/test_module.py
lub wtests/test_module.py
.źródło
W języku C # ogólnie dzieliłem testy na osobny zestaw.
W Pythonie - do tej pory - miałem tendencję do pisania doctestów, gdzie test znajduje się w dokumentacji funkcji, lub umieszczania ich w
if __name__ == "__main__"
bloku na dole modułu.źródło
Pisząc pakiet o nazwie „foo”, umieszczę testy jednostkowe w osobnym pakiecie „foo_test”. Moduły i podpakiety będą wtedy miały taką samą nazwę jak moduł pakietu SUT. Np. Testy dla modułu foo.xy znajdują się w foo_test.xy Pliki __init__.py każdego pakietu testowego zawierają następnie pakiet AllTests, który zawiera wszystkie pakiety testowe pakietu. setuptools zapewnia wygodny sposób na określenie głównego pakietu testowego, dzięki czemu po „python setup.py develop” możesz po prostu użyć „python setup.py test” lub „python setup.py test -s foo_test.x.SomeTestSuite” do tylko określony pakiet.
źródło
Testy umieszczam w tym samym katalogu, co testowany kod (CUT); na
foo.py
testy będąfoo_ut.py
lub podobne. (Poprawiam proces wykrywania testów, aby je znaleźć.)To umieszcza testy obok kodu na liście katalogów, co sprawia, że testy są dostępne i sprawia, że otwieranie testów jest tak proste, jak to możliwe, gdy są one w osobnym pliku. (W przypadku edytorów wiersza poleceń
vim foo*
i podczas korzystania z graficznej przeglądarki systemu plików wystarczy kliknąć plik CUT, a następnie bezpośrednio sąsiadujący plik testowy.)Jak zauważyli inni , ułatwia to również refaktoryzację i wyodrębnienie kodu do użycia w innym miejscu, jeśli zajdzie taka potrzeba.
Naprawdę nie podoba mi się pomysł umieszczania testów w zupełnie innym drzewie katalogów; dlaczego utrudniać programistom otwieranie testów podczas otwierania pliku za pomocą CUT? To nie jest tak, że zdecydowana większość programistów tak chętnie pisze lub poprawia testy, że zignorują wszelkie bariery, zamiast je usprawiedliwiać. (Wręcz przeciwnie, z mojego doświadczenia; nawet jeśli uczynisz to tak łatwym, jak to możliwe, znam wielu programistów, którym nie przeszkadza pisanie testów.)
źródło
Niedawno zacząłem programować w Pythonie, więc tak naprawdę nie miałem okazji znaleźć najlepszych praktyk. Ale napisałem moduł, który wyszukuje i uruchamia wszystkie testy.
Więc mam:
Będę musiał zobaczyć, jak to pójdzie, gdy przejdę do większych projektów.
źródło