pytest夹具的多个副本

Fra*_*k T 18 python testing django pytest

假设我有一个简单的夹具,如下所示(使用pytest-django,但它也适用于pytest):

@pytest.fixture
def my_thing(request, db):
    thing = MyModel.objects.create()
    request.addfinalizer(lambda: thing.delete())
    return thing
Run Code Online (Sandbox Code Playgroud)

当我的测试需要单个MyModel实例时,这很有用.但是,如果我需要两个(或三个或四个)呢?我希望每个实例都是不同的,但要以相同的方式设置.

我可以复制/粘贴代码并重命名夹具功能,但这看起来不够优雅.

同样,我试过:

@pytest.fixture
def my_thing_1(my_thing):
    return my_thing

@pytest.fixture
def my_thing_2(my_thing):
    return my_thing
Run Code Online (Sandbox Code Playgroud)

但是,这些中的每一个似乎都返回MyModel的相同实例.

有没有办法用pytest的内置功能做我想做的事情?或者,我可以将我的装置的设置/拆卸移动到辅助函数中,因此我不会复制太多的代码.

或者我是以错误的方式处理这整件事?

flu*_*lub 25

我的方法可能是创建一个可以生成对象的fixture:

@pytest.fixture
def thing(request, db):
    class ThingFactory(object):
        def get(self):
            thing = MyModel.objects.create()
            request.addfinalizer(thing.delete)
            return thing
    return ThingFactory()

def test_thing(thing):
    thing1 = thing.get()
    thing2 = thing.get()
Run Code Online (Sandbox Code Playgroud)

显然你可以做出.get()争论等.

(PS:还要注意在终结器中不需要lambda)

  • @ingomueller.net 使用 `with` [contextlib.ExitStack()](https://docs.python.org/3/library/contextlib.html?highlight=exitstack#contextlib.ExitStack) `as stack`,产生工厂,让 `.get()` 使用 `stack.callback()` 注册析构函数 (2认同)