如果移动到 conftest,带有 pytest-lazy-fixture 的 Pytest 参数化夹具会失败

Pytest parametrized fixture with pytest-lazy-fixture fails if moved to conftest

我已经编写了这个简单的参数化夹具

@pytest.fixture(params=[
    pytest.lazy_fixture("client_a"),
    pytest.lazy_fixture("client_b"),
    pytest.lazy_fixture("client_c"),
])
def client_all(request):
    return request.param

放在测试文件中时它可以完美运行。当我将它移动到 conftest.py 时,结果是:

ImportError while loading conftest '/project/tests/conftest.py'. conftest.py:181: in ??? E AttributeError: module 'pytest' has no attribute 'lazy_fixture'

显然调试 pytest 的插件管理器是不可行的,但我注意到 pytest-lazy-fixture 中的 pytest_configure 函数在我收到此错误时从未被调用,但它确实在 fixture 工作时被调用,所以问题一定是在加载插件列表时出现的。我预计它会与其他一些 pytest 选项发生奇怪的冲突,但我不知道如何从这里继续前进。

请注意,该插件在整个项目的其他文件中使用,但仅用于参数化单个测试,从不作为夹具参数。

似乎在 pytest 4.0 中删除了一个 old issue. pytest_namespace 钩子,这意味着由于 pytest.lazyfixture 是一个插件,它仅在 conftest.py 之后添加。直接导入lazy_fixture即可解决

from pytest_lazyfixture import lazy_fixture

@pytest.fixture(params=[
    lazy_fixture("client_a"),
    lazy_fixture("client_b"),
    lazy_fixture("client_c"),
])
def client_all(request):
    return request.param

插件在 conftest 文件和 fixture 加载后配置。

因此,在注册您的全局装置时,pytest.lazy_fixture 命名空间尚不存在,因为对 pytest_configure 的调用尚未发生。

正确的使用方法是从它自己的模块本身加载它:

from pytest_lazyfixture import lazy_fixture

@pytest.fixture(params=[
    lazy_fixture("client_a"),
    lazy_fixture("client_b"),
    lazy_fixture("client_c"),
])
def client_all(request):
   ...

The docs don't clearly mention 这个,就像调用钩子的时候一样,但是在源代码中,我们可以看到它是按以下顺序发生的:

  1. main()被称为
  2. main() 调用 _prepareconfig. It loads and registers the plugins using the plugin manager(PytestPluginManager, a subclass of Pluggy's PluginManager).
  3. config._do_configure() then does the actual configuration by calling call_historic 在 Pluggy 的 _HookCaller class.