How to disable skipping a test in pytest without modifying the code?
Create a conftest.py with the following contents:
import pytest
import _pytest.skipping
def pytest_addoption(parser):
parser.addoption(
"--no-skips",
action="store_true",
default=False, help="disable skip marks")
@pytest.hookimpl(tryfirst=True)
def pytest_cmdline_preparse(config, args):
if "--no-skips" not in args:
return
def no_skip(*args, **kwargs):
return
_pytest.skipping.skip = no_skip
the use --no-skip
in command line to run all testcases even if some testcases with pytest.mark.skip
decorator
Ok the implementation does not allow for this with zero modifications. You’ll need a custom marker. Add the following to your conftest.py
then change all skipif
marks to custom_skipif
. Use pytest --no-skips
.
import pytest
from _pytest.mark.evaluate import MarkEvaluator
def pytest_addoption(parser):
parser.addoption(
"--no-skips", action="store_true", default=False, help="disable custom_skip marks"
)
@hookimpl(tryfirst=True)
def pytest_runtest_setup(item):
if item.config.getoption('--no-skips'):
return
# Check if skip or skipif are specified as pytest marks
item._skipped_by_mark = False
eval_skipif = MarkEvaluator(item, "custom_skipif")
if eval_skipif.istrue():
item._skipped_by_mark = True
pytest.skip(eval_skipif.getexplanation())
for skip_info in item.iter_markers(name="custom_skip"):
item._skipped_by_mark = True
if "reason" in skip_info.kwargs:
pytest.skip(skip_info.kwargs["reason"])
elif skip_info.args:
pytest.skip(skip_info.args[0])
else:
pytest.skip("unconditional skip")
item._evalxfail = MarkEvaluator(item, "xfail")
check_xfail_no_run(item)
The implementation is copied and modified from pytest itself in skipping.py.
An easy workaround is to monkeypatch pytest.mark.skipif
in your conftest.py
:
import pytest
old_skipif = pytest.mark.skipif
def custom_skipif(*args, **kwargs):
return old_skipif(False, reason='disabling skipif')
pytest.mark.skipif = custom_skipif
A workaround to ignore skip marks is to remove them programmatically. Create a conftest.py
with the following contents:
def pytest_collection_modifyitems(items):
for item in items:
for node in reversed(item.listchain()):
node.own_markers = [m for m in node.own_markers if m.name not in ('skip', 'skipif')]
However, this messes with pytest
internals and can easily break on pytest
updates; the proper way of ignoring skips should be defining your custom skipping mechanism, for example:
@pytest.hookimpl(tryfirst=True)
def pytest_runtest_setup(item):
mark = item.get_closest_marker(name='myskip')
if mark:
condition = next(iter(mark.args), True)
reason = mark.kwargs.get('reason', 'custom skipping mechanism')
item.add_marker(pytest.mark.skipif(not os.getenv('PYTEST_RUN_FORCE_SKIPS', False) and condition, reason=reason), append=False)
Annotate the tests with @pytest.mark.myskip
instead of @pytest.mark.skip
and @pytest.mark.myskip(condition, reason)
instead of @pytest.mark.skipif(condition, reason)
:
@pytest.mark.myskip
def test_skip():
assert True
@pytest.mark.myskip(1 == 1, reason='my skip')
def test_skipif():
assert True
On a regular run, myskip
will behave same way as pytest.mark.skip
/pytest.mark.skipif
. Setting PYTEST_RUN_FORCE_SKIPS
will disable it:
$ PYTEST_RUN_FORCE_SKIPS=1 pytest -v
...
test_spam.py::test_skip PASSED
test_spam.py::test_skipif PASSED
...
Of course, you shouldn't use pytest.mark.skip
/pytest.mark.skipif
anymore as they are won't be influenced by the PYTEST_RUN_FORCE_SKIPS
env var.