【问题标题】:pytest: prevent imported auto-used session fixture from executing multiple timespytest:防止导入的自动使用的会话夹具多次执行
【发布时间】: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 uptearing 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 是有意义的,但是根据我的经验,将测试保留在源目录中只有当您要使用源代码发布测试时才有意义,例如numpypandas 这样做。

标签: python testing pytest fixtures


【解决方案1】:

你是对的。会话范围的夹具应该只运行一次。但是如果你仔细观察,test_a 有两个设置装置。一个来自 common/conftest.py,另一个来自 pkg_a/conftest.py。您不需要在 pkg_a/conftest.py 中导入 common.conftest.py。 pytest 从项目根目录开始收集 conftest 文件。 您可以通过--setup-show 开关查看夹具设置过程:pytest test_a.py --setup-show

要解决您的问题,您可以从 test_a(b)/conftest.py 文件中删除 from common.conftest import *

更多关于pytest的conftest集合在这里:https://docs.pytest.org/en/2.7.3/plugins.html

【讨论】:

  • 如果我从pkg_a/conftest.py 中删除import,则不会为pkg_a 执行夹具。如果我从两个包中删除import,则根本不会执行夹具。不打印setting uptearing down。我想要的是setting up 出现在开头,tearing down 只在结尾出现一次。
猜你喜欢
  • 2021-09-03
  • 2013-03-11
  • 2018-02-13
  • 1970-01-01
  • 1970-01-01
  • 2020-01-16
  • 2022-09-23
  • 1970-01-01
  • 2012-08-18
相关资源
最近更新 更多