python - pytest 与 pip install 中断
问题描述
我正在一个名为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
. 创建一个空./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的评论中找到)给了我一点提示,它不包括用于搜索库的路径中的 cwd,因为它正在寻找在test
pyenv 中,而不是在 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/
将解决这个问题,但我想了解为什么安装破折号会破坏事情,如果我们当前的设置有问题,请帮助其他人避免它。
(我也在https://github.com/pytest-dev/pytest/discussions/8270上发布了这个,希望对堆栈溢出有更多的响应。)
解决方案
这里的问题是您的本地test
包隐藏test
了标准库中的模块。一般来说,对任何 stdlib 模块进行命名是一种不好的做法,应该避免;然而,由于
该
test
包仅供 Python 内部使用。它的文档是为了 Python 的核心开发人员的利益。不鼓励在 Python 标准库之外使用此包,因为此处提到的代码可能会在 Python 版本之间更改或删除,恕不另行通知。
和
该
test
包包含 Python 的所有回归测试以及模块test.support
和test.regrtest
.test.support
用于在test.regrtest
驱动测试套件时增强您的测试。
一种暗示test
不会在回归测试运行之外使用。但是,这不是真的future
-它在安装 aliases 时导入test.support
,导致 stdlib在开始测试收集之前test
出现。您与 一起安装,因为它是直接依赖项。现在,当您开始运行时,它会加载导入的插件,然后在尝试收集本地包时,导入失败,因为已经导入了另一个包!sys.modules
pytest
futures
dash
pytest
dash
future
test
test
pytest
test
解决方案
我建议将本地test
包重命名为 eg tests
。这将停止 stdlib 模块的名称隐藏。
如果您无法重命名测试包,可以想象几种解决方法来规避 stdlib 的导入test
:
清理导入
conftest.py
在您的项目根目录(不在test
目录中,否则它将不起作用)中创建一个文件,其中包含以下内容:
import sys
sys.modules.pop("test", None)
这将“取消导入”标准库test
,使您的本地test
包可在测试集合中导入。
改变sys.path
以使本地test
包在 stdlib 之前可选择
只需运行python -m pytest ...
或PYTHONPATH=. pytest ...
确保在站点之前插入项目的根目录sys.path
,因此import test
将始终以导入本地包结束。
推荐阅读
- java - 如何使用 JAXP SAX 解析器忽略 XML 注释中包含的数据?
- node.js - 如何从环回打印我的 MongoDB 查询
- angular - 用于生产的 Angular 构建消耗太多内存?
- roblox - 团队创建搜索栏未显示
- oracle - 计算 Oracle 的日期范围
- python - “在 0.000 秒内运行 0 次测试”
- django - 如何在 Django 中使用 `reverse()` 函数的 `current_app` 和 `urlconf` 参数
- javascript - 使用 BeautifulSoup 抓取 JavaScript (ReactTable)
- apache - 如何在 Red Hat Linux 中检查 apache 配置的有效性?
- c - 使用指定的初始化程序使用 `char []` 成员初始化嵌套结构