I want pytest to collect all tests and then, using the pytest_collection_modifyitems
hook, skip certain tests based on a condition retrieved from a database.
The common solution involves accessing a protected member (_request
) like this:
def pytest_collection_modifyitems(items, config):
# get skip condition from database
for item in items:
if skip_condition:
item._request.applymarker(pytest.mark.skipif(True, reason='Put any reason here'))
Accessing _request
feels unsafe. Is there a cleaner or recommended way to mark tests as skipped during collection using pytest_collection_modifyitems
?
Hey! I’ve tackled this before, and you’re right, accessing _request
feels a bit hacky.
I found a cleaner approach is to directly apply a marker to the item without touching protected members:
import pytest
def pytest_collection_modifyitems(items, config):
for item in items:
if skip_condition: # check your DB or other condition
item.add_marker(pytest.mark.skip(reason="Condition met, skipping test"))
Using add_marker
keeps it safe and readable, and pytest
will honor the skip during test execution.
This approach worked well for me when skipping tests dynamically based on DB values.
I ran into the same issue, and what helped me was avoiding _request entirely. The trick is that pytest_collection_modifyitems
runs after collection, so you can just use item.add_marker()
to mark tests as skipped:
def pytest_collection_modifyitems(items, config):
for item in items:
if some_condition_from_db(item.name):
item.add_marker(pytest.mark.skip(reason="Skipped based on DB condition"))
It feels much safer and is officially supported. I liked this because it keeps the code future-proof and avoids fragile internals.
From my experience, using _request
is usually unnecessary. I use add_marker
to mark tests dynamically:
def pytest_collection_modifyitems(items, config):
for item in items:
if should_skip(item):
item.add_marker(pytest.mark.skip(reason="Skipping dynamically"))
This way, pytest
handles the skip cleanly during test execution. I found it also makes debugging easier since the skipped tests show up clearly in the report instead of being silently ignored.