Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple copies of a pytest fixture

Let's say I have a simple fixture like the following (using pytest-django, but it applies to pytest as well):

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

This works great when my tests need a single instance of MyModel. But what about if I need two (or three or four)? I want each instance to be distinct, but to be set up in the same way.

I could copy/paste the code and rename the fixture function, but that seems inelegant.

Similarly, I have tried:

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

However, each of these appears to return the same instance of MyModel.

Is there a way to do what I want using pytest's built-in functionality? Alternately, I could move the setup/teardown of my fixture out into helper functions so I'm not duplicating too much code.

Or am I going about this whole thing the wrong way?

like image 865
Frank T Avatar asked Feb 05 '14 17:02

Frank T


People also ask

Are pytest fixtures cached?

Pytest only caches one instance of a fixture at a time, which means that when using a parametrized fixture, pytest may invoke a fixture more than once in the given scope.

How many times will a fixture of module scope run?

Module: If the Module scope is defined, the fixture will be created/invoked only once per module. Class: With Class scope, one fixture will be created per class object. Session: With the Session scope, the fixture will be created only once for entire test session.

Can a pytest fixture use another fixture?

Fixtures can also be requested more than once during the same test, and pytest won't execute them again for that test. This means we can request fixtures in multiple fixtures that are dependent on them (and even again in the test itself) without those fixtures being executed more than once.

How often is a fixture function in pytest executed?

Fixtures with scope session will only be executed once per session. Every time you run pytest , it's considered to be one session.


1 Answers

My approach would probably to create a fixture which can generate your objects:

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

Obviously you can make .get() take an argument etc.

(PS: Also note there's no need for the lambda in the finalizer)

like image 182
flub Avatar answered Sep 28 '22 22:09

flub