[TIL] Using Fixtures with pytest `parametrize`

[TIL] Using Fixtures with pytest `parametrize`

For longer than I care to admit, I was running my end to end tests in only Firefox. I thought it would be trivial to add a fixture to have my tests run using multiple browsers. Unfortunately, there isn't an easy way in pytest to use fixtures as parametrized values*. Here is the solution I landed on:

@pytest.fixture(scope="session")
def firefox():
    return webdriver.Firefox(options=options)

@pytest.fixture(scope="session")
def chrome():
    return webdriver.Chrome()

@pytest.mark.parametrize("browser", ["firefox", "chrome"])
def test_e2e_report(
    browser, request
):
    browser = request.getfixturevalue( # required to use firefox and chrome fixtures
        browser
    )

We are passing string values (["firefox", "chrome"]) into the test with parametrize, then we retrieve the fixture (object) with that name using request.getfixturevalue(browser) built into pytest (link that helped me find this). It's hacky and I don't like it because an IDE won't be able to trace it, but it works!

Related: This doubled the number of tests I was running which started giving me failures because too many connections were open. Running my local server with python manage.py runserver --nothreading stopped those errors from popping up.

*H/T to Jeff Triplett for suggesting pytest-lazy-fixture as an alernative. If I end up doing this in more places in the future, I'd consider using this library.