This is basically the same as an older question but hoping there is a better solution now.
The problem: Given a parametrized fixture, how can one parametrize a test function with a subset of the fixtures objects?
Example:
import pytest
@pytest.fixture(params=range(7))
def square(request):
return request.param ** 2
def test_all_squares(square):
sqrt = square ** 0.5
assert sqrt == int(sqrt)
@pytest.fixture()
def odd_square(square):
if square % 2 == 1:
return square
pytest.skip()
def test_all_odd_squares(odd_square):
assert odd_square % 2 == 1
sqrt = odd_square ** 0.5
assert sqrt == int(sqrt)
Output:
$ pytest pytests.py -v =================================================================== test session starts =================================================================== ... collected 14 items pytests.py::test_all_squares[0] PASSED [ 7%] pytests.py::test_all_squares[1] PASSED [ 14%] pytests.py::test_all_squares[2] PASSED [ 21%] pytests.py::test_all_squares[3] PASSED [ 28%] pytests.py::test_all_squares[4] PASSED [ 35%] pytests.py::test_all_squares[5] PASSED [ 42%] pytests.py::test_all_squares[6] PASSED [ 50%] pytests.py::test_all_odd_squares[0] SKIPPED [ 57%] pytests.py::test_all_odd_squares[1] PASSED [ 64%] pytests.py::test_all_odd_squares[2] SKIPPED [ 71%] pytests.py::test_all_odd_squares[3] PASSED [ 78%] pytests.py::test_all_odd_squares[4] SKIPPED [ 85%] pytests.py::test_all_odd_squares[5] PASSED [ 92%] pytests.py::test_all_odd_squares[6] SKIPPED [100%] ============================================================== 10 passed, 4 skipped in 0.02s ==============================================================
Although this works, it's not ideal:
- It creates dummy test cases that are always skipped
- It requires test functions that use the filtered fixture to give a different name (
odd_square) to the parameter.
What I'd like instead is e.g. a filter_fixture(predicate, fixture) function that filters the original fixture's objects and can be passed to pytest.mark.parametrize, something like this:
@pytest.mark.parametrize("square", filter_fixture(lambda x: x % 2 == 1, square))
def test_all_odd_squares(square):
assert square % 2 == 1
sqrt = square ** 0.5
assert sqrt == int(sqrt)
Is this feasible somehow?