user3715648
user3715648

Reputation: 1588

Possible to skip a test depending on fixture value?

I have a lot of tests broken into many different files. In my conftest.py I have something like this:

@pytest.fixture(scope="session",
                params=["foo", "bar", "baz"])
def special_param(request):
    return request.param

While the majority of the tests work with all values, some only work with foo and baz. This means I have this in several of my tests:

def test_example(special_param):
    if special_param == "bar":
        pytest.skip("Test doesn't work with bar")

I find this a little ugly and was hoping for a better way to do it. Is there anyway to use the skip decorator to achieve this? If not, is it possible to right my own decorator that can do this?

Upvotes: 3

Views: 1967

Answers (2)

Yu Chen
Yu Chen

Reputation: 7460

You can, as one of the comments from @abarnert, write a custom decorator using functools.wraps for this purpose exactly. In my example below, I am skipping a test if a fixture configs (some configuration dictionary) value for report type is enhanced, versus standard (but it could be whatever condition you want to check).

For example, here's an example of a fixture we'll use to determine whether to skip a test or not:

@pytest.fixture
def configs()-> Dict:
   return {"report_type": "enhanced", "some_other_fixture_params": 123}

Now we write a decorator that will skip the test by inspecting the fixture configs contents for its report_type key value:

def skip_if_report_enhanced(test_function: Callable) -> Callable:
    @wraps(test_function)
    def wrapper(*args, **kwargs):
        configs = kwargs.get("configs") # configs is a fixture passed into the pytest function
        report_type = configs.get("report_type", "standard")
        if report_type is ReportType.ENHANCED: 
            return pytest.skip(f"Skipping {test_function.__name__}") # skip!
        return test_function(*args, **kwargs) # otherwise, run the pytest
    return wrapper # return the decorated callable pytest

Note here that I am using kwargs.get("configs") to pull the fixture out here.

Below the test itself, the logic of which is irrelevant, just that the test runs or not:

@skip_if_report_enhanced
def test_that_it_ran(configs):
   print("The test ran!") # shouldn't get here if the report type is set to enhanced

The output from running this test:

============================== 1 skipped in 0.55s ==============================

Process finished with exit code 0 SKIPPED
[100%] Skipped: Skipping test_that_it_ran

Upvotes: 2

Code-Apprentice
Code-Apprentice

Reputation: 83527

One solution is to override the fixture with @pytest.mark.parametrize. For example

@pytest.mark.parametrize("special_param", ["foo"])
def test_example(special_param):
    # do test

Another possibility is to not use the special_param fixture at all and explicitly use the value "foo" where needed. The downside is that this only works if there are no other fixtures that also rely on special_param.

Upvotes: 0

Related Questions