johnw
johnw

Reputation: 51

How to pass a value to a Pytest fixture

I am using Pytest to test an executable. This .exe file reads a configuration file on startup.

I have written a fixture to spawn this .exe file at the start of each test and closes it down at the end of the test. However, I cannot work out how to tell the fixture which configuration file to use. I want the fixture to copy a specified config file to a directory before spawning the .exe file.

    @pytest.fixture
    def session(request):
        copy_config_file(specific_file) # how do I specify the file to use?
        link = spawn_exe()
        def fin():
            close_down_exe()
        return link 

    # needs to use config file foo.xml
    def test_1(session):  
        session.talk_to_exe()

    # needs to use config file bar.xml
    def test_2(session):
        session.talk_to_exe()

How do I tell the fixture to use foo.xml for test_1 function and bar.xml for test_2 function?

Thanks John

Upvotes: 3

Views: 1536

Answers (1)

Bruno Oliveira
Bruno Oliveira

Reputation: 15335

One solution is to use pytest.mark for that:

import pytest


@pytest.fixture
def session(request):
    m = request.node.get_closest_marker('session_config')
    if m is None:
        pytest.fail('please use "session_config" marker')
    specific_file = m.args[0]
    copy_config_file(specific_file) 
    link = spawn_exe()
    yield link
    close_down_exe(link)    

@pytest.mark.session_config("foo.xml")
def test_1(session):  
    session.talk_to_exe()

@pytest.mark.session_config("bar.xml")
def test_2(session):
    session.talk_to_exe()

Another approach would be to just change your session fixture slightly to delegate the creation of the link to the test function:

import pytest


@pytest.fixture
def session_factory(request):
    links = []

    def make_link(specific_file):
        copy_config_file(specific_file) 
        link = spawn_exe()
        links.append(link)
        return link 

    yield make_link

    for link in links:
        close_down_exe(link)

def test_1(session_factory):  
    session = session_factory('foo.xml')
    session.talk_to_exe()

def test_2(session):
    session = session_factory('bar.xml')
    session.talk_to_exe()

I prefer the latter as its simpler to understand and allows for more improvements later, for example, if you need to use @parametrize in a test based on the config value. Also notice the latter allows to spawn more than one executable in the same test.

Upvotes: 8

Related Questions