I see that there are some questions about conditionally skipping tests with certain fixtures: Is there a way to skip a pytest fixture? and Skip tests using a particular pytest fixture.
However I am looking for a straightforward way to select or deselect tests that use a particular fixture. I'd like to avoid manually marking all such tests, because the fixture might be used indirectly, and this is generally error-prone and not scalable.
Ideally, I'd like to be able to run something like pytest -m 'not uses_foo'
, and all tests that require the foo
fixture would be deselected.
Again, this question is not about skipping the tests. I am specifically asking about a way to make them (de-)selectable as one might normally be able to do with marks.
I'm not aware of a builtin mechanism, but you can easily implement it yourself.
The pytest_collection_modifyitems hook is run after test collection, at which point all fixtures have been resolved. The names of all fixtures requested by a test can be retrieved via the fixturenames
attribute. In the same hook, you can mark the tests with a skip
marker or remove the tests you don't want to run entirely. If you want them to appear as deselected
, you can call the pytest_deselected
hook from this hook.
To make it configurable from the command line, you can use the pytest_addoption hook.
Example conftest.py:
import pytest
def pytest_addoption(parser):
parser.addoption("--skip-fixtures", default=None)
def pytest_collection_modifyitems(config, items):
skip_fixtures_opt = config.option.skip_fixtures
if not skip_fixtures_opt:
return
skipped_fixtures = skip_fixtures_opt.split(",")
selected = list(items)
deselected = []
for test_item in items:
for fixture in skipped_fixtures:
if fixture in test_item.fixturenames:
selected.remove(test_item)
deselected.append(test_item)
items[:] = selected
config.hook.pytest_deselected(items=deselected)
If you run pytest --skip-fixtures "foo,bar"
, all tests using foo
or bar
will be deselected. If you want to skip them instead, add a skip marker via test_item.add_marker(pytest.mark.skip("reason..."))