2014-02-05 15 views
12

Sagen wir, ich habe eine einfache Befestigung wie folgt aus (mit pytest-django, aber ich denke, es sollte gelten auch für pytest):Mehrere Kopien eines py.test Halterung

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

Dies funktioniert gut, wenn Meine Tests benötigen eine einzelne Instanz von MyModel. Aber was ist, wenn ich zwei (oder drei oder vier) brauche? Ich möchte, dass jede Instanz verschieden ist, aber auf die gleiche Weise aufgebaut wird.

Ich könnte den Code kopieren und einfügen und die Fixture-Funktion umbenennen, aber das scheint unelegant.

Und ich habe versucht:

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

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

jedoch jede dieser erscheint die gleiche Instanz von MyModel zurückzukehren.

Gibt es eine Möglichkeit zu tun, was ich mit pytests integrierter Funktionalität machen will? Alternativ könnte ich das Setup/Teardown meines Geräts in Hilfsfunktionen verschieben, damit ich nicht zu viel Code vervielfältige.

Oder gehe ich die ganze Sache in die falsche Richtung?

Antwort

17

Mein Ansatz wäre wahrscheinlich eine Befestigung zu schaffen, die Ihre Objekte erzeugen können:

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

Offensichtlich kann man .get() ein Argument machen nehmen usw.

(PS: Auch beachten Sie, dass für das Lambda keine Notwendigkeit im Finalizer)

+1

1) Guten Anruf nicht Lambda im Finalizerthread benötigen. 2) Ich mag deinen Ansatz. Ich benutze eigentlich Factory Boy, um diese Modelle zu erstellen, also denke ich, dass ich idealerweise nicht einmal Factory-Fixtures für jedes Modell erstellen müsste. Aber ich habe Probleme, ModelFactory zu Unterklassen zu machen, um Finalisten für SubFactories rekursiv hinzuzufügen, also denke ich, dass ich Ihren Ansatz als Stop-Lücke verwenden werde. Vielen Dank! –

+1

Für zukünftige Referenzzwecke war der einzige Grund für die Verwendung von Finalizern, dass pytest-django die Datenbank zwischen den Tests nicht bereinigte, da sie nicht mehrere Datenbanken unterstützt (siehe auch https://github.com/pelme/pytest_django/issues/). 76). Für die Art von Problem, das ich oben beschrieben habe, empfehle ich von ganzem Herzen, FactoryBoy mit Pytest-Django zu verwenden. –

0

Ich komme zu dieser Frage sehr spät ... aber, mit einer parametrisierten Fixture und einfach die Fixture zurückzukehren, die du duplizieren willst, scheint auch zu funktionieren.

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) 

Wenn Sie den oben Test ausführen, erhalten Sie 2 verschiedenen "name" Armaturen

$ 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 =========================================== 
Verwandte Themen