【问题标题】:Pytest: how to work around missing __init__.py in the tests folder?Pytest:如何解决测试文件夹中缺少 __init__.py 的问题?
【发布时间】:2018-06-11 11:08:59
【问题描述】:

我将所有 pytest 文件存储在项目根目录下的 tests 子目录中。该目录或以上目录中没有__init__.pypytest tests/test_a.py 按预期工作。我也可以直接从tests 文件夹中运行pytest test_a.py

|--<project_root>
+---[tests]
    test_a.py
    base.py
    config.py
    conftest.py

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

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

from config import HOST_URL_DEFAULT, USER, PASSWORD

导致:

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

有没有办法解决这个问题,让 IDE 工具 pytest 继续工作?如果可能,我想避免使用点导入。

更新:阅读this answer后,我想我终于开始了解更多python导入的工作原理了。

【问题讨论】:

  • 为什么pytest导入config.py失败?
  • @MisterMiyagi:pytest 无法导入的是conftest.py,抱歉打错了。我没有在测试代码的任何地方明确导入conftest.py,但该文件存在并且我正在使用它。我更新了问题以显示导致错误的确切原因。
  • 所以问题在于您的 IDE 而不是pytest?也许可以告诉 IDE tests 是项目设置中某处的命名空间包。如果您将__init__.py 放在tests 目录中,config 模块的限定名称将更改为tests.config,您必须按照答案建议调整导入。无论哪种方式,可能值得查看Good Integration Practices 以获取有关不同测试布局的提示。
  • 至少在PyCharm中,可以在项目设置中添加tests作为源根;这解决了导入问题。

标签: python pytest


【解决方案1】:

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

# 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 的测试包!有一些名副其实的用例——比如你的。

pytestdoes discourage 有一个源包在同一个源根目录下的测试包。然而,这意味着你应该移动你的源包,而不是你的测试包!

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 也可以从源代码导入。也就是说,您的测试在您的源包上运行,而不是您安装的包。如果您的安装过程中有任何错误,测试将无法捕捉到它。 See the blog linked in the pytest docs for details.

【讨论】:

  • 我的理解是 pytest 不鼓励使用 __init__.py 进行测试,它确实设法在不将所有内容都打包成包的情况下运行代码。
  • pytest 不要求您将非包转换为包。不过,您已经有一个包裹。
  • @ccpizza 我添加了一些进一步的描述,pytest 不鼓励在测试包旁边有源包,而不是本身没有测试包。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-27
  • 2019-07-12
  • 2021-06-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多