2014-02-05 3 views
12

Скажем, у меня есть простой прибор вроде следующей (с использованием pytest-Джанго, но я думаю, он должен обратиться к pytest а):Несколько копий py.test арматуры

@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? В качестве альтернативы, я мог бы переместить настройку/отключение моего прибора в вспомогательные функции, чтобы я не дублировал слишком много кода.

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

ответ

17

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

@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: Также обратите внимание, что нет никакой необходимости в лямбда в финализаторе)

+1

1) Хороший вызов не нуждаясь лямбда в финализации. 2) Мне нравится ваш подход. Я фактически использую Factory Boy для создания этих моделей, поэтому я думаю, что в идеале мне даже не понадобилось бы создавать заводские светильники для каждой модели. Но у меня возникли проблемы с подклассом ModelFactory, чтобы рекурсивно добавлять финализаторы для SubFactories, поэтому я думаю, что я буду использовать ваш подход в качестве пробела остановки. Благодаря! –

+1

В будущем, единственной причиной, по которой я использовал финализаторы, было то, что pytest-django не очищал базу данных между тестами, потому что она не поддерживает несколько баз данных (см. Также https://github.com/pelme/pytest_django/issues/ 76). Для типа проблемы, описанного выше, я полностью рекомендую использовать FactoryBoy с pytest-django. –

0

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

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 =========================================== 
Смежные вопросы