Как импортировать модуль для тестирования в тестовый модуль - PullRequest
1 голос
/ 27 апреля 2019

Проблема

У меня есть структура каталогов для моего проекта, которая соответствует стандарту для пакетов Python, так как он был создан с помощью этого шаблона cookiecutter: https://github.com/audreyr/cookiecutter-pypackage#quickstart

Структура каталогов:

project_name
├── project_name
│   ├── __init__.py         
│   └── module1.py
└── tests         
    └── test_module1.py 

Первая строка кода test_module1.py:

from project_name import module1

Но я получаю ModuleNotFoundError: No module named 'project_name'.

Насколько я понимаю, это должно работать, поскольку папка с именем project_name является пакетом, что обеспечивается наличием файла __init__.py.

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

Что я уже пробовал

Я попытался переименовать папку с файлом __init__.py во что-то другое, а затем импортировать, так как я думал, что это может быть связано с родительской папкой и дочерней папкой, которые имеют имя project_name. Это не сработало, та же ошибка.

Я также попытался превратить тестовую папку в пакет, создав в ней файл __init.py__, хотя в шаблоне Cokkiecutter его нет. Я читал во многих местах, что создание тестовой папки в пакет не рекомендуется, но некоторые предлагают такую ​​структуру. Это тоже не сработало.

Я тщательно искал решения этой, казалось бы, очень стандартной проблемы, некоторые ссылки здесь:

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

Чего я не хочу

Я не хочу изменять sys.path, как кажется из многих ответов. Для такой распространенной проблемы должен быть более чистый путь.

Что я делаю не так?

Изменить для дополнительной информации (см. Вопрос от @Nicholas):

Содержимое init .py´ равно

# -*- coding: utf-8 -*-
"""Top-level package for project_name."""
__author__ = """my_name"""
__email__ = 'my_email'
__version__ = '0.1.0'

Сгенерированный шаблоном Cookiecutter.

Внутри test_module1 я добавил следующее до появления ModuleNotFoundError:

import sys
import os

print(sys.path)    
print(os.getcwd()) 

sys.path печатает список, где первый элемент - это каталог tests.

['c:\\Users\\...\\project_name\\tests', 
 'C:\\Users\\...\\Miniconda3\\python37.zip', 
 'C:\\Users\\...\\Miniconda3\\DLLs', 'C:\\Users\\...\\Miniconda3\\lib', 
 'C:\\Users\\...\\Miniconda3', 
 'C:\\Users\\...\\Miniconda3\\lib\\site- packages', 
 'C:\\Users\\...\\Miniconda3\\lib\\site-packages\\win32', 
 'C:\\Users\\...\\Miniconda3\\lib\\site-packages\\win32\\lib', 
 'C:\\Users\\...\\Miniconda3\\lib\\site-packages\\Pythonwin']

Я не знаю, имеет ли значение строчная буква "c" в первом элементе.

os.getcwd() печатает корневой каталог 'c:\Users\....\project_name'. Также в нижнем регистре «с».

1 Ответ

1 голос
/ 27 апреля 2019

Необходимо создать виртуальную среду и установить проект, чтобы тестовые модули правильно разрешали операторы импорта.

В корневом каталоге проекта, то есть в каталоге project_name, который содержит подкаталог project_name и подкаталог tests, создайте файл setup.py (или pyproject.toml) для метаданных пакета. См. здесь для получения подробной информации об этой части.

Из этого же корневого каталога проекта, который теперь содержит установщик (setup.py), создайте и активируйте venv и установите свой проект:

python3 -m venv .venv
source .venv/bin/activatate  # linux/macOS
# .\Scripts\activate.bat  # windows
pip install --editable .
pip install pytest
pytest

Если по какой-то причине вы не хотите создавать установщик для вашего проекта, вы можете запустить pytest следующим образом из каталога проекта:

python3 -m pytest

В отличие от простой команды pytest, это добавит текущий рабочий каталог к ​​sys.path, позволяя разрешать операторы импорта в тестах.

...