You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何设置package作用域的pytest fixture未按每个包实例化一次?

关于pytest package 作用域fixture的疑问

我正在理解pytest的package fixture作用域行为。把两个测试放在不同的包中,但设置package作用域的fixture只生成了一次,而我预期它会生成两次,这是为什么?

最小可复现示例(MRE)

目录结构

> tree
.
├── __init__.py
├── conftest.py
├── pkg1
│   ├── __init__.py
│   └── test_scope.py
└── pkg2
    ├── __init__.py
    └── test_scope.py

2 directories, 6 files

文件内容

  • 所有__init__.py文件为空。
  • conftest.py:
#!/usr/bin/env python3
import pytest

@pytest.fixture(scope="package")
def my_fixture():
    print("Package fixture invoked!")
  • 两个包中的test_scope.py文件:
#!/usr/bin/env python3

def test_(my_fixture):
    pass

实际运行结果

> pytest -s
============================ test session starts ============================
platform linux -- Python 3.10.12, pytest-7.4.4, pluggy-1.3.0
rootdir: /home/vmonteco/dojo-pytest/notebook/tests/concepts/fixtures/scope/pb
collected 2 items                                                           

pkg1/test_scope.py Package fixture invoked!
.
pkg2/test_scope.py .

============================= 2 passed in 0.01s =============================

预期结果

> pytest -s
============================ test session starts ============================
platform linux -- Python 3.10.12, pytest-7.4.4, pluggy-1.3.0
rootdir: /home/vmonteco/dojo-pytest/notebook/tests/concepts/fixtures/scope/pb
collected 2 items                                                           

pkg1/test_scope.py Package fixture invoked!
.
pkg2/test_scope.py Package fixture invoked!
.

============================= 2 passed in 0.01s =============================

解答

问题核心在于package作用域的判定规则和你定义fixture的位置不匹配:

  1. package作用域的生效逻辑:pytest的package作用域fixture,是基于它所在的conftest.py对应的包来确定作用范围的。你把my_fixture放在了根目录的conftest.py中,这个文件属于项目最顶层的根包,因此该fixture的作用域是整个根包,而非pkg1或pkg2这两个子包。

  2. 子包独立触发fixture的条件:要让每个子包的测试都触发一次package作用域fixture,需要在pkg1和pkg2各自的目录下创建专属的conftest.py,并在其中定义对应的package作用域fixture。

修改后的解决方案

调整目录结构,给每个子包添加conftest.py:

.
├── __init__.py
├── pkg1
│   ├── __init__.py
│   ├── conftest.py
│   └── test_scope.py
└── pkg2
    ├── __init__.py
    ├── conftest.py
    └── test_scope.py

每个子包的conftest.py内容一致:

#!/usr/bin/env python3
import pytest

@pytest.fixture(scope="package")
def my_fixture():
    print("Package fixture invoked!")

此时运行pytest -s,两个子包的测试会各自触发一次fixture,和你的预期结果一致。

如果不想重复编写fixture代码,可以通过复用逻辑优化:

  • 根目录conftest.py定义基础实现:
import pytest

def _my_fixture_impl():
    print("Package fixture invoked!")
  • 子包conftest.py继承并定义作用域:
import pytest
from ..conftest import _my_fixture_impl

@pytest.fixture(scope="package")
def my_fixture():
    return _my_fixture_impl()

这种方式既避免了代码冗余,又能保证每个子包的package作用域fixture独立触发。


内容的提问来源于stack exchange,提问作者vmonteco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 20:34:51