Импорт Python для тестирования с использованием носа - что лучше всего подходит для импорта модулей выше текущего пакета
Это вопрос, который часто задают в разных формах и часто получает ответы "LOL, вы не делаете это правильно". Довольно уверен, что из-за того, что люди (включая меня) используют здравый смысл, пытаются использовать его как реализацию, а решение не очевидно (если вы этого еще не делали).
Принял бы ответ, который "позволяет вылететь из бутылки".
Учитывая
project/
__init__.py
/code
__init__.py
sut.py
/tests
__init__.py
test_sut.py
Где начинается test_sut.py:
import code.sut
Запуск nosetests в корневом каталоге dir приводит к:
ImportError: No module named code.sut
Прогулки по авеню:
a) сделать относительный, используя
from ..code import sut
b) добавить корень проекта в PYTHONPATH
c) используйте
sys.path.append
чтобы добавить путь.. до импорта в начале каждого тестового модуля.
d) просто запомните
setup.py
в проекте, чтобы установить модули в пакеты сайта перед запуском тестов.
Таким образом, необходимо, чтобы тесты находились под корнем тестового пакета, которые имеют доступ к проекту. Каждый из вышеперечисленных не чувствует себя "естественным" для меня, оказался проблематичным или кажется слишком тяжелой работой!
В java это работает, но в основном с помощью инструмента сборки /IDE, размещающего все ваши классы в пути к классам. Возможно, проблема в том, что я ожидаю "волшебство" от Python? Обратите внимание, что в тестах на фреймворк Flask опция d) кажется предпочтительной.
В любом случае заявления, предлагающие предпочтительное решение, устраняют ощущение "неестественности" в моем собственном.
Ответы
Ответ 1
Ты уже хорошо ответил на свой вопрос.
D (установка на место системы) является предпочтительным для распространяемого кода. Обычно я использую C (изменить sys.path), потому что мне не нужны общесистемные установки моих сотен пользовательских библиотек. Теоретически A (относительный импорт) кажется более приятным, но бывают случаи, когда он терпит неудачу.
B (PYTHONPATH) прямо, действительно только для целей тестирования, на мой взгляд.
Это в значительной степени суммирует все варианты. Опция, которую вы предпочитаете (Python волшебно знает, где искать), на самом деле не является работоспособным решением, потому что это может привести к непредсказуемым результатам, таким как автоматическое обнаружение библиотек из несвязанных проектов.
На мой взгляд, лучше всего поместить это в точку входа в вашу программу:
import sys, os
sys.path = [os.path.abspath(os.path.dirname(__file__))] + sys.path
Ответ 2
У меня была та же проблема, и я нашел ответ в соответствующем вопросе для меня.
Просто удалите __init__.py в корне проекта.
Ответ 3
Я знаю, что есть ответ, и я по-прежнему считаю это хорошей причиной для обмена другими альтернативами:)
Существует nose-pathmunge, позволяющий вам установить sys.path
при вызове nosestests
.