Несколько копий инструментария py.test

Скажем, у меня есть простой инструмент, подобный следующему (используя pytest-django, но я думаю, что он должен применяться и к pytest):

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

Это отлично работает, когда мои тесты нуждаются в одном экземпляре MyModel. Но как насчет того, нужны ли мне два (или три или четыре)? Я хочу, чтобы каждый экземпляр отличался, но настраивался таким же образом.

Я мог бы скопировать/вставить код и переименовать функцию привязки, но это кажется неэлегантным.

Аналогично, я пробовал:

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

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

Однако каждый из них возвращает тот же экземпляр MyModel.

Есть ли способ сделать то, что я хочу, используя встроенные функции pytest? В качестве альтернативы, я мог бы переместить установку/отключение моего прибора в вспомогательные функции, чтобы я не дублировал слишком много кода.

Или я все это неправильно делаю?

Ответ 1

Мой подход, вероятно, создаст инструмент, который может генерировать ваши объекты:

@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()

Очевидно, вы можете сделать .get() аргумент и т.д.

(PS: Также обратите внимание, что нет необходимости в лямбда в финализаторе)

Ответ 2

Я очень скоро прихожу к этому вопросу... но, используя параметризованный прибор и просто возвращающее приспособление, которое вы хотите дублировать, похоже, тоже работает.

import pytest
import random

@pytest.fixture
def name():
    return random.randint(0, 10)


@pytest.fixture(params=[0, 1])
def parametrized_name(request, name):
    return name


def test_something(parametrized_name):
    print "Testing with name: " + str(parametrized_name)

Если вы выполняете вышеуказанный тест, вы получаете 2 разных "названия"

$ pytest -s blah.py
============================================= test session starts ==============================================
platform linux2 -- Python 2.7.14, pytest-3.3.2, py-1.5.2, pluggy-0.6.0
rootdir: /home/bsquizza/repos/blah/tests, inifile:
collected 2 items                                                                                              

blah.py Testing with name: 7
.Testing with name: 10
.                                                                                               [100%]

=========================================== 2 passed in 0.01 seconds ===========================================