How to skip a pytest using an external fixture?
The Solution from Bruno Oliveira is working, but for new pytest (>= 3.5.0) you need to add the pytest_configure:
# conftest.py
import pytest
@pytest.fixture
def platform():
return "ios"
@pytest.fixture(autouse=True)
def skip_by_platform(request, platform):
if request.node.get_closest_marker('skip_platform'):
if request.node.get_closest_marker('skip_platform').args[0] == platform:
pytest.skip('skipped on this platform: {}'.format(platform))
def pytest_configure(config):
config.addinivalue_line(
"markers", "skip_by_platform(platform): skip test for the given search engine",
)
Use:
@pytest.mark.skip_platform('ios')
def test_ios(platform, request):
assert 0, 'should be skipped'
It seems py.test doesn't use the test fixtures when evaluating the expression for skipif
. By your example, test_ios
is actually successful because it is comparing the function platform
found in the module's namespace to the "ios"
string, which evaluates to False
hence the test is executed and succeeds. If pytest was inserting the fixture for evaluation as you expect, that test should have been skipped.
A solution to your problem (not to your question though) would be to implement a fixture that inspects marks into the tests, and skips them accordingly:
# conftest.py
import pytest
@pytest.fixture
def platform():
return "ios"
@pytest.fixture(autouse=True)
def skip_by_platform(request, platform):
if request.node.get_closest_marker('skip_platform'):
if request.node.get_closest_marker('skip_platform').args[0] == platform:
pytest.skip('skipped on this platform: {}'.format(platform))
A key point is the autouse
parameter, which would make that fixture to be automatically included by all tests. Then your tests can mark which platforms to skip like this:
@pytest.mark.skip_platform('ios')
def test_ios(platform, request):
assert 0, 'should be skipped'
Hope that helps!
Using inspiration from this answer to another SO question, I am using this approach to this problem which works well:
import pytest
@pytest.fixture(scope='session')
def requires_something(request):
something = 'a_thing'
if request.param != something:
pytest.skip(f"Test requires {request.param} but environment has {something}")
@pytest.mark.parametrize('requires_something',('something_else',), indirect=True)
def test_indirect(requires_something):
print("Executing test: test_indirect")