Как правильно импортировать пакеты с помощью py.test?

У меня есть следующий макет:

/spamalot
    /spam
        __init__.py
        spam.py
        /spam_on_eggs
            __init__.py
            spam_on_eggs.py
    /tests

        test_spam.py

Так случилось, что спам — это фляжное приложение.

В течение spam.py у меня есть

import spam_on_eggs.spam_on_eggs as eggs
# Other Flask setup & application code here.

И это прекрасно работает - из каталога spamalot я могу запустить python spam/spam.py

Однако, когда я начинаю добавлять в смесь тесты, это уже не так здорово.

В моем файле test_spam.py у меня есть:

import spam.spam
test_client = spam.spam.app.test_client()

def test_it_fails():
     assert False

Однако вместо того, чтобы потерпеть неудачу там, где я ожидал, она не работает в строке импорта:

/spamalot/ $ py.test
# some output
E    ImportError

Я могу исправить это, поместив __init__.py в свою папку /tests, но тогда я получаю другую ошибку ImportError:

spam/spam.py:1: in <module>
>    import spam_on_eggs.spam_on_eggs as eggs
E    ImportError: No module named 'spam_on_eggs'

Я могу решить это, изменив строку на:

from spam.spam_on_eggs import spam_on_eggs

Что позволяет мне тестировать, но тогда я теряю способность запускать $ python spam/spam.py, потому что я получаю

ImportError: no module named 'spam'

Очевидно, у меня есть пробел в понимании того, как работает импорт модулей и как py.test работает с этой системой.

Что мне не хватает?

Возможно ли иметь описанную мной схему и иметь возможность запускать как py.test, так и мой сервер из каталога spamalot?


person Wayne Werner    schedule 28.03.2014    source источник


Ответы (1)


py.test всегда будет использовать кратчайший путь к каталогу с __init__.py в нем.

Поместите __init__.py в spamalot, и вы сможете импортировать spamalot.spam.spam.

Ссылка: выбор макета теста

person User    schedule 28.03.2014
comment
Это превратило бы spamalot в модуль, не так ли? На самом деле это не то, что я ищу - если я хочу, чтобы мои тесты были в том же модуле, я просто добавлю их как подмодуль спама. - person Wayne Werner; 28.03.2014
comment
Также это на самом деле не сработало (тоже ImportError) - person Wayne Werner; 28.03.2014
comment
Это зависит от суперкаталога spamalot. Есть ли __init__.py? Взгляните на ссылку. Также рассмотрите возможность добавления пути к sys.path. - person User; 29.03.2014
comment
spamalot — это корень проекта (например, содержит .git папку, requirements.txt и т. д.) - person Wayne Werner; 29.03.2014