Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pytest use same fixture twice in one function

For my web server, I have a login fixture that create a user and returns the headers needed to send requests. For a certain test, I need two users. How can I use the same fixture twice in one function?

from test.fixtures import login


class TestGroups(object):

    def test_get_own_only(self, login, login):
         pass
like image 384
danijar Avatar asked Mar 19 '16 10:03

danijar


People also ask

Can We request multiple fixtures at the same time in pytest?

Here’s another quick example to demonstrate: 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.

What is a fixture in pytest?

One of the things that makes pytest’s fixture system so powerful, is that it gives us the ability to define a generic setup step that can be reused over and over, just like a normal function would be used. Two different tests can request the same fixture and have pytest give each test their own result from that fixture.

How does pytest work?

When pytest goes to run a test, it looks at the parameters in that test function’s signature, and then searches for fixtures that have the same names as those parameters. Once pytest finds them, it runs those fixtures, captures what they returned (if anything), and passes those objects into the test function as arguments.

How to share a fixture across multiple tests in Python?

To avoid losing these changes, we effectively want to share the same fixture instance across these tests. There is an easy way to solve this, we can just extract all three tests into it’s own module and create a module scoped fixture using @pytest.fixtures (scope='module'), everything should work as expected.


3 Answers

An alternative is just to copy the fixture function. This is both simple and correctly handles parameterized fixtures, calling the test function with all combinations of parameters for both fixtures. This example code below raises 9 assertions:

import pytest  @pytest.fixture(params=[0, 1, 2]) def first(request):     return request.param  second = first  def test_double_fixture(first, second):     assert False, '{} {}'.format(first, second) 
like image 102
danijar Avatar answered Sep 20 '22 09:09

danijar


I do it with Dummy class which will implement fixture functionality. Then just call it from your test. Provide clarify method name to better understand what is your test doing.

import pytest  @pytest.fixture def login():     class Dummy:         def make_user(self):             return 'New user name'     return Dummy()  def test_something(login):     a = login.make_user()     b = login.make_user()     assert a == b 
like image 35
Sergey Voronezhskiy Avatar answered Sep 18 '22 09:09

Sergey Voronezhskiy


The trick is to use mark.parametrize with the "indirect" switch, thus:

@pytest.fixture
def data_repeated(request):
    return [deepcopy({'a': 1, 'b': 2}) for _ in range(request.param)]


@pytest.mark.parametrize('data_repeated', [3], indirect=['data_repeated'])
def test(data_repeated):
    assert data_repeated == [
        {'a': 1, 'b': 2},
        {'a': 1, 'b': 2},
        {'a': 1, 'b': 2}]
like image 40
Dunk Avatar answered Sep 20 '22 09:09

Dunk