- Pytest:帮助您编写更好的程序
- 完整的 Pytest 文档
- 安装和入门
- 使用和调用
- 在现有测试套件中使用 pytest
- 测试中断言的编写和报告
- Pytest 夹具:显式、模块化、可扩展
- 用属性标记测试函数
- MonkeyPatching / Mocking 模块和环境
- 临时目录和文件
- 捕获 stdout/stderr 输出
- 捕获警告
- 模块和测试文件的 Doctest 集成
- 跳过和 xfail:处理无法成功的测试
- 参数化夹具和测试功能
- 缓存:使用交叉测试运行状态
- UnitTest.TestCase 支持
- 运行为鼻子编写的测试
- 经典的 Xunit 风格设置
- 安装和使用插件
- 编写插件
- 登录
- 良好的集成实践
- 古怪的测试
- Pytest 导入机制和 sys.path/PYTHONPATH
- 设置 bash 完成
- API 引用
- _pytest.hookspec
- _pytest.python_api
- _pytest.outcomes
- _pytest.config
- _pytest.mark
- _pytest.recwarn
- _pytest.assertion
- _pytest.freeze_support
- _pytest.fixtures
- _pytest.cacheprovider
- _pytest.capture
- _pytest.doctest
- _pytest.junitxml
- _pytest.logging
- _pytest.monkeypatch
- _pytest.pytester
- _pytest.tmpdir
- _pytest.python
- _pytest.nodes
- _pytest.reports
- _pytest._code.code
- _pytest.config.argparsing
- _pytest.main
- pluggy.callers
- _pytest.config.exceptions
- py.test 2.0.0:断言++、UnitTest++、Reporting++、Config++、Docs++
- 示例和自定义技巧
- 配置
- 贡献开始
- 向后兼容策略
- Python 2.7 和 3.4 支持
- 企业版 pytest
- 项目实例
- 历史笔记
- 弃用和移除
- 发展指南
- 演讲和辅导
Pytest 导入机制和 sys.path/PYTHONPATH
导入模式
pytest作为测试框架需要导入测试模块和 conftest.py
执行文件。
在Python中导入文件(至少直到最近)是一个非常重要的过程,经常需要更改 sys.path . 导入过程的某些方面可以通过 --import-mode
命令行标志,可以假定这些值:
prepend
(default): the directory path containing each module will be inserted into the beginning ofsys.path
if not already there, and then imported with the __import__ 内置的。这要求当测试目录树不在包中排列时,测试模块名称必须是唯一的,因为模块将放入
sys.modules
导入后。这是经典的机制,可以追溯到Python2仍然受支持的时候。
append
:包含每个模块的目录追加到sys.path
如果不是已经在那里,并且进口__import__
.这样可以更好地针对已安装的包版本运行测试模块,即使被测试的包具有相同的导入根。例如:
testing/__init__.py testing/test_pkg_under_test.py pkg_under_test/
测试将针对已安装的版本运行
pkg_under_test
什么时候?--import-mode=append
使用while withprepend
他们会选择本地版本。这种混乱是我们提倡使用的原因 src 布局。等同于
prepend
,要求测试模块名称在测试目录树未排列在包中时是唯一的,因为这些模块将放入sys.modules
导入后。importlib
: new in pytest-6.0, this mode uses importlib 导入测试模块。这样就可以完全控制导入过程,而且不需要更改sys.path
或sys.modules
完全。由于这个原因,这根本不要求测试模块名称是唯一的,但也使得测试模块彼此不可导入。对于不在Python包中的测试,这在以前的模式中是可能的,因为更改的副作用
sys.path
和sys.modules
上面提到过。有此要求的用户应该将他们的测试转换成适当的包。我们打算
importlib
未来版本中的默认值。
prepend
和 append
导入模式方案
以下是使用时的场景列表 prepend
或 append
pytest需要更改的导入模式 sys.path
为了导入测试模块或 conftest.py
文件,以及用户可能因此而遇到的问题。
测试模块/ conftest.py
包中的文件
考虑此文件和目录布局:
root/ |- foo/ |- __init__.py |- conftest.py |- bar/ |- __init__.py |- tests/ |- __init__.py |- test_foo.py
执行时:
pytest root/
Pytest会找到 foo/bar/tests/test_foo.py
意识到它是一个包的一部分,因为 __init__.py
文件在同一文件夹中。然后它将向上搜索,直到找到最后一个仍包含 __init__.py
文件以查找包 root (在这种情况下) foo/
)要加载模块,它将插入 root/
到前面 sys.path
(如果还没有)以便加载 test_foo.py
作为 模块 foo.bar.tests.test_foo
.
同样的逻辑也适用于 conftest.py
文件:它将作为导入 foo.conftest
模块。
当测试位于包中时,保留完整的包名称非常重要,以避免出现问题并允许测试模块具有重复的名称。这也将在中详细讨论 Python测试发现的约定 .
独立测试模块/ conftest.py
文件夹
考虑此文件和目录布局:
root/ |- foo/ |- conftest.py |- bar/ |- tests/ |- test_foo.py
执行时:
pytest root/
Pytest会找到 foo/bar/tests/test_foo.py
意识到它不是一个包裹的一部分,因为没有 __init__.py
文件在同一文件夹中。然后它将添加 root/foo/bar/tests
到 sys.path
为了进口 test_foo.py
作为 模块 test_foo
. 同样的情况也发生在 conftest.py
添加文件 root/foo
到 sys.path
将其导入 conftest
.
因此,此布局不能具有相同名称的测试模块,因为它们都将在全局导入命名空间中导入。
这也将在中详细讨论 Python测试发现的约定 .
调用 pytest
对战 python -m pytest
使用运行pytest pytest [...]
而不是 python -m pytest [...]
产生几乎相同的行为,除了后者将当前目录添加到 sys.path
,这是标准的 python
行为。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论