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.