2011-07-12 27 views
55

To jest pytanie, które jest często zadawane w różnych formach i często uzyskuje odpowiedzi "lol you're does does doing doing properly". Jest to całkiem prawdopodobne, ponieważ istnieje zdrowy scenariusz, który ludzie (w tym ja) próbują wykorzystać jako implementację, a rozwiązanie nie jest oczywiste (jeśli wcześniej tego nie robiłeś).Import w języku Python do testów przy użyciu nosa - jaka jest najlepsza praktyka w przypadku importowania modułów powyżej bieżącego pakietu

Przyjmuje odpowiedź, która "pozwala wylecieć z butelki".

Podane

project/ 
    __init__.py 
    /code 
     __init__.py 
     sut.py 
    /tests 
     __init__.py 
     test_sut.py 

Gdzie tests_sut.py zaczyna:

import code.sut 

przebiegu nosetests w głównym katalogu prowadzi do:

ImportError: No module named code.sut 

Aleje wyjazd:

a) zrobić względne u śpiewać

from ..code import sut 

b) dodać pierwiastek projektu PYTHONPATH

c) używać

sys.path.append 

dodać ścieżkę .. przed przywozem na początku każdego modułu testowego.

d) po prostu pamiętać, aby zrobić

setup.py 

od projektu do instalacji modułów w miejscu opakowań przed wykonaniem testów.


Wymaga się więc, aby testy znajdowały się poniżej katalogu głównego pakietu testowego, który ma dostęp do projektu. Każda z powyższych rzeczy nie wydaje mi się "naturalna", okazała się problematyczna lub wydaje się zbyt ciężką pracą!

W języku java działa to, ale zasadniczo dzięki narzędziu do budowania/IDE umieszczając wszystkie klasy w ścieżce klas. Być może chodzi o to, że oczekuję "magii" od Pythona? Zauważyłem, że w testach platformy internetowej Flask opcja d) wydaje się preferowana.

W każdym razie poniższe stwierdzenia zalecające preferowane rozwiązanie usuną poczucie "nienaturalności" w mojej własnej.

+0

Podobne do http://stackoverflow.com/questions/6323860/sibling-package-imports/6466139#6466139 choć nie jest to dokładny duplikat. – Evpok

+0

To pięknie podsumowuje 80-90% mojej sytuacji - jeśli tylko jest jakieś wyjaśnienie, czy virtualenv zmieniłby odpowiedź ... – sage

Odpowiedz

8

Już odpowiedziałeś na pytanie całkiem nieźle .. D (instalacja do lokalizacji systemowej) jest preferowana dla kodu dystrybucyjnego. Zwykle używam C (modyfikuj sys.path), ponieważ nie chcę systemowych instalacji moich setek niestandardowych bibliotek. W teorii A (import względny) wydaje się ładniejszy, ale zdarzają się przypadki, w których zawodzi. B (PYTHONPATH) jest już dostępny, tak naprawdę, moim zdaniem, tylko do celów testowych.

To w dużym stopniu podsumowuje wszystkie opcje. Opcja, którą wolisz (Python magicznie wie, gdzie szukać) nie jest rozwiązaniem praktycznym, ponieważ może prowadzić do nieprzewidywalnych rezultatów, takich jak automatyczne wyszukiwanie bibliotek z niepowiązanych projektów.

Moim zdaniem, najlepszą rzeczą do zrobienia jest umieścić to w punkcie (a) wejścia do programu:

import sys, os 
sys.path = [os.path.abspath(os.path.dirname(__file__))] + sys.path 
+1

, ale domyślam się, że mój punkt wejścia (s!) To polecenie nosetests! Rozważałem zejście z trasy pisania nagłówka nosetests, wywołującego nose.run po dodaniu sys.path ... ale znowu było to nienaturalne. Dziękuję za to, pomoże mi to kontynuować. – leonigmig

+0

Jeśli przechodzisz przez testy nosa, punkty wejściowe są pojedynczymi modułami, które są importowane, a to będzie bardzo niezręczne. W takim przypadku możesz uznać, że PYTHONPATH jest najmniej kłopotliwą opcją (jak już powiedziałem, jest w porządku do celów testowych). Czuję twój ból tutaj - mam też nadzieję, że więcej osób będzie dzwonić, aby wydawało się, że jest w porządku (lub sugeruje lepsze rozwiązanie). – Luke

43

miałem ten sam problem i znalazł answer w pokrewnej pracy zapytania dla mnie .

Wystarczy usunąć __init__.py w katalogu głównym projektu.

+8

Świetna odpowiedź! Miałem już stary \ _ \ _ init \ _ \ _. Pyc, powodujący ten problem. – frabcus

+0

To mi nie pomogło, jak to ma się udać? – user541905

+1

@ user541905: ponieważ nos inteligentnie próbuje wypełnić twój 'sys.path'. Dobre wytłumaczenie z samego django-nosa: https://github.com/django-nose/django-nose#upgrading-from-django--13-to-django-14 – furins

3

wiem, że jest to odpowiedź sprawdzone i nadal uważam, że to dobry powód, aby udostępnić inne alternatywy :)

Jest nose-pathmunge daje kontrolę, aby ustawić sys.path podczas wywoływania nosestests.

Powiązane problemy