【发布时间】:2023-03-04 09:50:01
【问题描述】:
我的 pytest 测试文件分布在多个包中,它们共享一些常见的固定装置。但是,我发现我的自动使用的会话范围固定装置运行了多次。
这是我项目的基本结构:
.
├── Pipfile
├── Pipfile.lock
├── __init__.py
├── common
│ ├── __init__.py
│ └── conftest.py
├── pkg_a
│ ├── __init__.py
│ ├── conftest.py
│ └── test_a.py
└── pkg_b
├── __init__.py
├── conftest.py
└── test_b.py
这里是每个.py文件的内容:
==> ./__init__.py <==
==> ./common/__init__.py <==
==> ./common/conftest.py <==
import pytest
@pytest.fixture(scope='session', autouse=True)
def setup():
print 'setting up'
yield
print 'tearing down'
==> ./pkg_a/__init__.py <==
==> ./pkg_a/conftest.py <==
from common.conftest import *
==> ./pkg_a/test_a.py <==
def test():
assert True
==> ./pkg_b/__init__.py <==
==> ./pkg_b/conftest.py <==
from common.conftest import *
==> ./pkg_b/test_b.py <==
def test_b():
assert True
这里是pytest的输出:
➜ pytest -s pkg_a pkg_b
========================== test session starts ==========================
platform darwin -- Python 2.7.15, pytest-3.10.0, py-1.7.0, pluggy-0.8.0
rootdir: /path/to/the/project, inifile:
collected 2 items
pkg_a/test_a.py setting up
.
pkg_b/test_b.py setting up
.tearing down
tearing down
======================= 2 passed in 0.02 seconds ========================
我对会话装置的理解是,它们只会在pytest 命令的生命周期内运行一次。但是这里setting up 和tearing down 被打印了两次,并且它们是交错的。
有没有办法只执行一次夹具?我希望 setting up 在整个测试会话的开头只打印一次,tearing down 在最后打印一次。
附:我知道参数化的会话夹具将被执行多次。但我不认为我的灯具是参数化的。
【问题讨论】:
-
项目结构看起来有点配置错误(为什么在项目根目录中有
__init__.py?它是一个包吗?为什么要为包创建测试目录?)。此外,从conftests 导入是一种不好的做法,因为它很容易破坏东西;conftests 不是普通的 python 模块,它们会在找到时被pytest自动执行。建议:删除不必要的__init__.pys,删除conftest导入,将common/conftest.py移动到项目根目录。 -
@hoefling 明白了。谢谢你的建议!是的,我项目的当前结构有点混乱。我仍然想知道......是否可以在当前结构下归档夹具?
-
@hoefling 我认为将测试文件与逻辑代码并排放置是有意义的。我删除了根文件夹中的
__init__.py,但结果是一样的。 -
再次声明:您必须在项目根目录中引入
conftest.py来执行测试并删除 conftest 导入。 -
您可以将测试与生产代码一起保存,但在组织代码时必须更加小心。
pytest会将conftest文件的父目录附加到sys.path,这很容易引入导入问题——尤其是当您在python 包中进行测试时。查看Good Integration Practices 是有意义的,但是根据我的经验,将测试保留在源目录中只有当您要使用源代码发布测试时才有意义,例如numpy或pandas这样做。
标签: python testing pytest fixtures