Reputation: 1587
I have a test fixture with session
scope which is parametrized, e.g.
@pytest.fixture(scope="session", params=["one", "two", "three"])
def myfixture():
...
In my directory, I have files which use pytest.mark.usefixtures("myfixture")
and one file which contains tests should be run only for myfixture
with "two"
parameter and py.test should skip it otherwise.
Are there any ways to achieve this in py.test or do I need to set a special variable in some class in myfixture()
function?
Upvotes: 11
Views: 7230
Reputation: 4685
I have ended up writing my own decorator, which I think is reasonably easy and clean:
import functools
def skip_targets(excluded_values):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
paramA = kwargs['paramA']
if paramA in excluded_values:
pytest.skip('Param A "{}" currently not supported'.format(paramA))
func(*args, **kwargs)
return wrapper
return decorator
To deactivate a test that uses a fixture for paramA
, you can exclude the value X
like this:
@skip_targets(['X'])
def test_param(self, paramA):
pass
Upvotes: 0
Reputation: 1
The clean way to do this is to use the pytest_collection_modifyitems
hook to modify your test collection before they are run
Given your fixture as described:
@pytest.fixture(scope="session", params=["one", "two", "three"])
def myfixture(request):
...
Add a custom mark to your tests:
@pytest.mark.restriction("two")
def test_smth(self, myfixture):
...
Then modify your test collection with custom deselection logic:
def pytest_collection_modifyitems(items, config):
""" deselect test items which do not match the fixture restriction """
deselection_items = []
for item in items:
# There may be a better way than regex to get the parameter
passed_param = re.search(r'\[(.+?)\]', item.name).group(1)
restrictions = set([mark.args[0] for mark in item.iter_markers(name='restriction')])
if len(restrictions) > 0:
if passed_param not in restrictions:
deselection_items.append(item)
items[:] = [item for item in items if item not in deselection_items]
config.hook.pytest_deselected(items=deselection_items)
Upvotes: 0
Reputation: 758
I came across this question while trying to solve a similar use case. My solution, in case it helps anyone avoid couple of hours. It's an easy way to override the parameterisation of a fixture from a test:
@pytest.fixture(scope="session", params=["one", "two", "three"])
def myfixture():
...
@pytest.mark.parameterize('myfixture', ['two'], indirect=True)
def test1(myfixture):
...
def test2(myfixture):
...
Thanks to https://hackebrot.github.io/pytest-tricks/mark_parametrize_with_indirect/ for explaining the use of indirect!
Upvotes: 1
Reputation: 1587
Found solution myself, one can define function in conftest.py
:
def pytest_namespace():
return {"param": None}
And in fixture function we can do:
@pytest.fixture(scope="session", params=["one", "two", "three"])
def myfixture():
pytest.param = request.param
# ...
So we can wrap test class with:
@pytest.mark.skipif("pytest.param == 'value'")
class TestSmth(object):
...
Upvotes: 15