ошибка pytest при импорте моей функции декоратор - PullRequest
0 голосов
/ 06 ноября 2019

Я создаю тестовый модуль pytest для функции в моем программном обеспечении.

Прежде чем даже начать тестирование, pyunit, похоже, не может импортировать мой декоратор "cache_offline", который косвенно импортируется при импортеЯ тестирую функцию в своем тесте.

Я использую Anaconda для встраивания Python 3.7 и pytest 5.2.2

Я пытался закомментировать код, в котором декоратор применяется к моим функциям,когда я делаю так, ошибка pytest исчезает, и тесты выполняются правильно.

Мой тест находится в ./tests/scripts/test_scripts_helper.py, и я запускаю pytest в корне проекта . Pytest правильно находит мой тест (см. сообщение об ошибке),так что здесь проблема не в этом.

Мой тест импортирует и хочет проверить функцию read_tiff_tag из пакета vorace.scripts_helper, который импортирует функцию safe_mkdir из пакета vorace.core.misc, который импортируетпакет vorace.core.vorace, в котором 3 функции украшены декоратором cache_offline из package vorace.core.misc

Я пытался запустить оба теста, используя py.test или python -m pytest в корне mу проекта.

Мой проект имеет следующую структуру (упрощенно). Корень кода - ./vorace Корень теста - ./tests

.
├── conftest.py
├── tests
│   ├── __init__.py
│   ├── scripts
│   │   ├── __init__.py
│   │   └── test_scripts_helper.py
│   └── tests_data
│       └── test_ROI.tif
└── vorace
    ├── __init__.py
    ├── core
    │   ├── __init__.py
    │   ├── misc.py
    │   └── vorace.py
    └── scripts
        ├── __init__.py
        ├── batch_analyzis.py
        └── scripts_helper.py

Я пытался:

  • с пустым __init__.py и без него в каждой подпапке testsпапки. -> без изменений
  • с пустым conftest.py в корне проекта и без него. -> без изменений
  • выполнение теста, который не требует импорта в моем файле test_scripts_helper.py (мой тест вызывает комментирование проблемы) -> тест выполняется правильно

Я подозреваю, что это проблема кругового импорта, но мне всегда говорили, что это не может произойти в python. Может быть, декораторы являются исключением из этого правила?

Мой vorace.core.misc код с декоратором

from vorace.core import vorace
[...]
def cache_offline(cache_path=os.getcwd()):
    [...]
    def decorator(func):
        [...]
        def wrapper(*args, **kwargs):
            [...]
            return result
        return wrapper
    return decorator

def safe_mkdir(path):
    [...]

Одна из декорированных функций в vorace.core.vorace

from vorace.core.misc import *
[...]
@cache_offline(cache_path=".cache")
def classify_clusters_by_connectivity(xyz_data):
   [...]
[...]

Результат выполнения py.test в корне проекта

==================== test session starts ====================
platform linux -- Python 3.7.3, pytest-5.2.2, py-1.8.0, pluggy-0.12.0
rootdir: /home/flo/PycharmProjects/VorAce
plugins: arraydiff-0.3, openfiles-0.3.2, doctestplus-0.3.0, remotedata-0.3.1
collected 0 items / 1 errors                                                                                  

==================== ERRORS ====================
_________ ERROR collecting tests/scripts/test_scripts_helper.py _________
tests/scripts/test_scripts_helper.py:1: in <module>
    import vorace.scripts.scripts_helper as sh
vorace/scripts/scripts_helper.py:6: in <module>
    from vorace.core.misc import safe_mkdir
vorace/core/misc.py:8: in <module>
    from vorace.core import vorace
vorace/core/vorace.py:91: in <module>
    @cache_offline(cache_path=".cache")
E   NameError: name 'cache_offline' is not defined


Если я выполню простой 0 == 0 тест в моем файле tests/scripts/test_scripts_helper.py без импорта из моего проекта, тест будет успешно выполнен.

Ответы [ 2 ]

0 голосов
/ 06 ноября 2019

РЕДАКТИРОВАТЬ: я наконец получил подтверждение кругового импорта. В противоположность тому, что я думал, импорт определенных имен из модуля, как в from x import y, может быть чувствителен к циклическому импорту, где import x не может.

Чтобы решить это, я просто импортировал модуль ииспользуйте синтаксис, используя модуль с префиксом вызова функции. Больше информации здесь: https://www.reddit.com/r/Python/comments/51hdup/from_import_vs_import_on_circular_import/

Проблема, которая, в конечном счете, не относится конкретно к декоратору или pytest.


Я решил эту проблему, поместив свой декоратор cache_offline в отдельныйпакет vorace.core.caching.py. Теперь я импортирую этот пакет только из vorace.core.vorace, где находится функция, которая должна быть оформлена.

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

Тем не менее, у pytest по-прежнему есть проблема, поэтому он не должен потерпеть неудачу при импорте. Я все еще принимаю любой ответ, который может объяснить, почему pytest не может импортировать мой декоратор, и я сохраняю resol для ответа такого рода.

0 голосов
/ 06 ноября 2019

Когда вы запускаете ./tests/scripts/test_scripts_helper.py, python автоматически устанавливает ./tests/scripts/ в PYTHONPATH, но не устанавливает никаких других каталогов, поэтому весь ваш импорт из других пользовательских файлов должен завершиться неудачей.

Установите все ваши рабочие каталоги в переменную среды PYTHONPATH,Нечто подобное в оболочке Linux.

PYTHONPATH="${PYTHONPATH}:$dir
...