如何将要测试的模块导入到测试模块中

How to import the module to test into the test module

问题

我的项目有一个目录结构,它遵循 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 文件的文件夹重命名为其他名称,然后导入,因为我认为这可能与名称为 [=17 的父文件夹和子文件夹有关=].这没有用,同样的错误。

我还尝试通过在其中创建一个 __init.py__ 文件将测试文件夹变成一个包,即使 Cookiecutter 模板没有那个。 我在很多地方读到不鼓励将测试文件夹放入包中,但有些人建议采用这种结构。那也不管用。

我已经彻底搜索了这个看似非常标准的问题的解决方案,一些链接在这里:

我最后一次尝试是用 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'。还有一个小写的'c'。

您应该创建一个虚拟环境并安装项目,以便测试模块正确解析导入语句。

在项目根目录,即包含子目录project_name和子目录tests的目录project_name,创建一个setup.py(或pyproject.toml ) 包元数据文件。有关该部分的详细信息,请参阅 here

从现在包含安装程序 (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 允许在测试中解析导入语句。