WyllianNeo
WyllianNeo

Reputation: 363

I can have a generic fixture and call different values from that in my test?

I'm new on python and pytest, and at the momment I understand the basic of how work. But I can't find documentation to the below scenario:

I created a generic fixture that have the default mock values used in my project, and use this fixture in tests, it works fine. Something like:

#fixture
@pytest.fixture()
def generic_fixture(mocker):
    mocker.patch('project.some_class.url', "http://some_url:5002")

#test
def test_1(generic_fixture):
    do_something() # method that uses values from my generic fixture
    assert True

Now I want to know if have a way to pass a parameter in my test to my fixture call, to make some decision, something like:

#fixture
@pytest.fixture()
def generic_fixture(mocker, parameter_url):
    if parameter_url == None
        mocker.patch('project.some_class.url', "http://some_url:5002")
    else:
        mocker.patch('project.some_class.url', parameter_url)

#test
def test_1(generic_fixture(parameter_url)):
    do_something() # method that uses values from my generic fixture
    assert True

How I can do It properly? I looked at monkeypath, @pytest.mark.parametrize and some other structures, but none of them look to do what I want.

Upvotes: 3

Views: 1281

Answers (2)

WyllianNeo
WyllianNeo

Reputation: 363

The answer of D Malan help me a lot!

I'll put here my final solution, because I used what the above answer describe and other things, and I think it can be usefull for someone with similar structure, because at least for my was hard to figure it out (If is preferable, someone note me so I put this answer in the question):

conftest.py

def pytest_configure(config):
    # to avoid warnings
    config.addinivalue_line("markers", "my_fixture_url")

@pytest.fixture()
    def my_fixture(request):
        if request.node.get_closest_marker("my_fixture_url") and request.node.get_closest_marker("my_fixture_url").args[0]:
            something = request.node.get_closest_marker("my_fixture_url").args[0]
        else:
            something = 'www.google.com'
            ...

test.py

@pytest.mark.my_fixture_url({'url': 'www.stackoverflow.com'})
def test_1(my_fixture):
    ...

def test_2(my_fixture):
    ...

I used a dictionary in my mark because I have situations where I want send more than one parameter, and/or use each one to override some default value.

Note I have a second test using the fixture but without marker. I can do it and use the default values from fixture.

This way I can use the same fixture in cases where I want the default values and in cases where I need to override part of the fixture configuration.

I hope it help someone :D

Upvotes: 1

D Malan
D Malan

Reputation: 11484

You can use Pytest's marks for this.

#fixture
@pytest.fixture()
def generic_fixture(request, mocker):
    parameter_url = request.node.get_closest_marker("generic_fixture_url")
    ...

#test
@pytest.mark.generic_fixture_url("url")
def test_1(generic_fixture):
    ...

Other options are to turn your fixture into a factory or to set some attribute on the module of your test.

Upvotes: 3

Related Questions