I'm writing a pytest plugin with a fixture that has a side effect of setting up some desirable mocks. I'd like to write a simple mark that will allow the user to call this fixture setup before the test runs, without having to include the fixture in the test function parameters -- essentially, "injecting" the fixture using a mark. My reasoning is that the user may want the mocked setup without needing the return value of the fixture itself, in which case it seems more intuitive to me to use a mark than to require that they declare a fixture they won't be using.
How might I use a mark to require a fixture in pytest? Looking at the docs, it seems like I want to hook into something like pytest_collection_modifyitems
, check for the relevant mark on each item using Item.iter_markers
, and then somehow update the list of fixtures. Reading the code, however, I'm having trouble figuring out how exactly to trigger that fixture setup.
Here's a simplified example of what the fixture in question looks like:
@pytest.fixture
def mocks(mocker):
ret_val = 10
mocker.patch('path.to.patch', return_value=ret_val)
return ret_val
Here's what the user can do to set up the mocks now:
def test_mocks(mocks):
# 'path.to.patch' will be mocked in this test
# ... test code ...
But here's what the test might look like if the fixture could be triggered via a mark instead:
@pytest.mark.mocks
def test_mocks():
# 'path.to.patch' will be mocked in this test, too
# ... test code ...
I was able to implement this by using the pytest_collection_modifyitems
hook to adjust the list of fixtures on the test item after collection:
@pytest.hookimpl(trylast=True)
def pytest_collection_modifyitems(items):
'''
Check if any tests are marked to use the mock.
'''
for item in items:
if item.get_closest_marker('mocks'):
item.fixturenames.append('mocks')
Adjusting the Item.fixturenames
list after collection appears to trigger the fixture setup in the way I was hoping.
If you don't care about using a custom mark, however, @hoefling's recommendation to use the built-in usefixtures
mark would be a good solution, too.