关于python:Pytest:如何解决tests文件夹中缺少__init__.py的问题?

Pytest: how to work around missing __init__.py in the tests folder?

我将所有pytest文件存储在项目根目录下的tests子目录中。 该目录或更高目录中没有__init__.py,并且pytest tests/test_a.py可以正常工作。 我也可以直接从tests文件夹中运行pytest test_a.py

1
2
3
4
5
6
|--<project_root>
+---[tests]
    test_a.py
    base.py
    config.py
    conftest.py

test_a.py中的测试类继承自base.py。 现在的问题是,由于缺少__init__.py,IDE工具无法正常工作,并且无法解决导入问题。 在tests下添加__init__.py可解决IDE中的所有导入错误,但是由于py.test无法导入conftest.py,因此测试将不再通过pytest test_a.py运行。

在我的conftest.py中,我具有以下导入:

1
from config import HOST_URL_DEFAULT, USER, PASSWORD

结果是:

1
2
ModuleNotFoundError: No module named 'config'
ERROR: could not load /project_root/tests/conftest.py

有没有一种方法可以解决此问题,以便IDE工具都能正常工作并且pytest可以正常工作? 如果可能的话,我想避免使用点导入。

更新:阅读此答案后,我认为我终于开始更多地了解python导入的工作原理。


添加__init__.py并在conftest.py中使用相对或绝对导入:

1
2
3
4
# relative
from .config import HOST_URL_DEFAULT, USER, PASSWORD
# absolute
from tests.config import HOST_URL_DEFAULT, USER, PASSWORD

在一个包中(由__init__.py标识),您需要明确的导入路径。使用不合格的导入(from config import ...)取决于PYTHONPATHsys.modules,包括您的软件包根目录-这通常不可靠,应避免使用,因为它会绕过软件包基础结构。

您这里拥有的(其他模块使用的config.py)是一个软件包。将其视为一个。

pytest不会阻止将测试包与__init__.py一起使用!确实有很多用例-例如您的。

pytest阻止的是在同一源根目录中包含源程序包和测试程序包。但是,这意味着您应该移动源软件包,而不是测试软件包!

1
2
3
4
5
6
7
mysource/  # root directory for both mypackage and mytests
+- mypackage/  # should be src/mypackage instead!
   +- __init__.py
   +- abcd.py
+- mytests
   +- __init__.py
   +- tests_abcd.py  # ``from mypackage import abcd`` imports from source

问题是运行mytests意味着mypackage也可以从源导入。也就是说,您的测试适用于您的源包,而不适用于已安装的包。如果您的安装过程中有任何错误,测试将无法捕获。有关详细信息,请参见pytest文档中链接的博客。