【问题标题】:pytest breaks with pip installpytest 与 pip install 中断
【发布时间】:2021-01-26 22:31:57
【问题描述】:

我正在一个名为test (https://github.com/covid-projections/covid-data-model/tree/main/test) 的目录中包含测试和一些测试帮助程序库的存储库中工作。神秘地pip install dash 似乎打破了我们的测试。我在 debian 笔记本电脑上的 pyenv 中使用 python 3.7.9。我用一个非常简单的例子重现了这个问题:

激活新的 pyenv virtualenv 并使用 pip install git+https://github.com/pytest-dev/pytest 安装最新的 pytest。创建一个空的./test/__init__.py 和以下两个文件:

$ cat ./test/real_test.py
from test import test_helpers

def test_one():
  assert "foobar" == test_helpers.SOME_CONSTANT
$ cat ./test/test_helpers.py
SOME_CONSTANT = "foo"

运行 test/real_test.py 符合预期,但未通过测试。现在pip install dash==1.19.0 测试无法运行

_____________________________________________________________________________ ERROR collecting test/real_test.py _____________________________________________________________________________
ImportError while importing test module '/home/thecap/tmp/nomodule/test/real_test.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
../../.pyenv/versions/3.7.9/lib/python3.7/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
E   ModuleNotFoundError: No module named 'test.real_test'

运行pytest --import-mode=importlib test/real_test.py(在https://github.com/pytest-dev/pytest/issues/7408 的cmets 中找到)给了我一点提示,它不包括用于搜索库的路径中的cwd,因为它正在查看pyenv 中的test ,而不是在 cwd 中。

ImportError while importing test module '/home/thecap/tmp/nomodule/test/real_test.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test/real_test.py:1: in <module>
    from test import test_helpers
E   ImportError: cannot import name 'test_helpers' from 'test' (/home/thecap/.pyenv/versions/3.7.9/lib/python3.7/test/__init__.py)

在运行 pip uninstall dash 后对我来说神秘的是,pytest test/real_test.py 的测试按预期运行,但 pytest --import-mode=importlib test/real_test.py 仍然无法正常运行。

我怀疑将我们的测试从 test/ 移动到 tests/ 可以解决这个问题,但我想了解为什么安装 dash 会破坏事情,如果我们当前的设置有问题,请帮助其他人避免它。

(我也在https://github.com/pytest-dev/pytest/discussions/8270 发布了这个帖子,希望对堆栈溢出有更多的回应。)

【问题讨论】:

  • 这是一个有趣的问题,当安装了dash 时,不知何故rootdir 不在sys.path 中。在没有插件活动的情况下运行工作:pytest test/real_test.py -p no:dash,还显式地将根目录添加到sys.path 工作:python -m pytest test/real_test.pyPYTHONPATH=. pytest test/real_test.py。不过,我仍然不明白为什么安装 dash 会破坏它。
  • 我猜dash 的问题是它使用来自futures 的代码,在安装别名时导入test,因此当pytest 开始测试时,您的本地包以后无法导入collection (pytest 将项目根目录添加到sys.path 并调用import test,但sys.modules 已经包含来自stdlib 的test,所以它没有效果。这就是为什么提前将根目录添加到sys.path够用了,但是我想别名 futures 会出错)。
  • 简短回答 - 不要创建名称隐藏标准库的包或模块,这迟早会破坏某些东西:-)
  • 虽然我也想说这根本不是你的错 - test module docs 明确指出它仅供 Python 内部使用。 我宁愿令标准库在内部回归测试运行之外使用它感到惊讶。作为一种解决方法,我可以建议在项目根目录中创建一个conftest.py,内容为import sys; sys.modules.pop("test", None) - 这应该可以解决导入问题。
  • 非常感谢@hoefling!我测试了 conftest.py 解决方法,我们将把 test 重命名为 tests。我还将更新 github 讨论并尝试使用 stdlib 提交错误。

标签: python pip pytest


【解决方案1】:

这里的问题是您的本地 test 包会隐藏标准库中的 test 模块。一般来说,对任何 stdlib 模块进行命名是一种不好的做法,应该避免;然而,由于

test 包仅供 Python 内部使用。它的文档是为了 Python 的核心开发人员的利益。不鼓励在 Python 标准库之外使用此包,因为此处提到的代码可能会在 Python 版本之间更改或删除,恕不另行通知。

test 包包含 Python 的所有回归测试以及模块 test.supporttest.regrtesttest.support 用于增强您的测试,而test.regrtest 驱动测试套件。

暗示test 不会在回归测试运行之外使用。 future 不是这样,尽管 - it's importing test.support when installing aliases 导致 stdlib 的 testpytest 开始测试收集之前出现在 sys.modules 中。你安装了futuresdash,因为it's a direct dependency。现在,当您启动 pytest 运行时,它会加载 dash 插件,该插件导入 future,该插件导入 test,然后,当您尝试收集本地 test 包时,pytest 导入失败,因为另一个 @ 987654346@已经导入!

解决方案

我建议将本地 test 包重命名为例如tests。这将停止 stdlib 模块的名称隐藏。

如果你不能重命名测试包,可以想象几种解决方法来规避stdlib的test的导入:

清理导入

在您的项目根目录中创建一个文件conftest.py(不在test 目录中,否则它将不起作用),内容如下:

import sys

sys.modules.pop("test", None)

这将“取消导入”stdlib 的 test,使您的本地 test 包可在测试集合中导入。

更改 sys.path 以使本地 test 包在 stdlib 包之前可选择

只需运行python -m pytest ...PYTHONPATH=. pytest ... 以确保将项目的根目录插入到sys.path 中的站点之前,因此import test 将始终以导入本地包结束。

【讨论】:

  • 结案!谢谢你!
猜你喜欢
  • 2015-11-01
  • 2017-03-20
  • 1970-01-01
  • 2015-06-01
  • 2019-11-18
  • 2021-10-19
  • 2015-07-30
  • 1970-01-01
  • 2022-11-08
相关资源
最近更新 更多