Pytest fixture with scope "class" 运行 每个方法

Pytest fixture with scope "class" running on every method

我正在尝试使用 Pytest 创建测试环境。这个想法是将测试方法分组为 classes。

对于每个 class/group,我想附加一个要进行参数化的 config 夹具。这样我就可以 运行 使用 "configuration A" 进行所有测试,然后使用 "configuration B" 进行所有测试,依此类推。

而且,我想要一个 reset 固定装置,它可以在特定方法或 class 的所有方法之前执行。

我遇到的问题是,一旦我应用我的 reset 夹具(到一个方法或整个 class),config 夹具似乎在函数范围而不是 class 范围内工作。因此,一旦我应用 reset 夹具,config 夹具就会在 class.

中的每个方法中调用 before/after

以下代码段重现了该问题:

import pytest
from pytest import *

@fixture(scope='class')
def config(request):
    print("\nconfiguring with %s" % request.param)
    yield
    print("\ncleaning up config")

@fixture(scope='function')
def reset():
    print("\nreseting")

@mark.parametrize("config", ["config-A", "config-B"], indirect=True)
#@mark.usefixtures("reset")
class TestMoreStuff(object):

    def test_a(self, config):
        pass

    def test_b(self, config):
        pass

    def test_c(self, config):
        pass

测试显示了 config fixture 应该如何工作,整个 class 只执行一次。如果取消注释 usefixtures 装饰,您会注意到 config fixture 将在每个测试方法中执行。 是否可以在不触发此行为的情况下使用 reset 夹具?

这取决于您使用的 pytest 版本。

pytest 的旧版本中实现此功能存在一些语义问题。所以,这个想法还没有在旧的 pytest 中实现。有人已经提出了实施相同的建议。你可以参考this

"Fixture scope doesn't work when parametrized tests use parametrized fixtures"。 这是错误。 可以参考this

此问题已在最新版本的 pytest 中得到解决。这是与 pytest 3.2.5

相同的 commit

希望对您有所帮助。

正如我在评论中提到的,这似乎是 Pytest 3.2.5 中的错误。

有一个解决方法,即 "force" 参数化的范围。因此,在这种情况下,如果您在 parametrize 装饰器中包含 scope="class",您将获得所需的行为。

import pytest
from pytest import *

@fixture(scope='class')
def config(request):
    print("\nconfiguring with %s" % request.param)
    yield
    print("\ncleaning up config")

@fixture(scope='function')
def reset():
    print("\nreseting")

@mark.parametrize("config", ["config-A", "config-B"], indirect=True, scope="class")
@mark.usefixtures("reset")
class TestMoreStuff(object):

    def test_a(self, config):
        pass

    def test_b(self, config):
        pass

    def test_c(self, config):
        pass