Propagating fixtures to test class attribute
See original GitHub issueIssue Description
Hi there.
I’d like to share my thought about using fixture in tests classes and maybe ask some advise. Current issue is related to two useful methods for newcomers from setuptools: (mark.usefixture and autouse - option for fixture) and using this stuff in Test classes.
First thing - (mark.usefixture) allows to define fixtures fro whole test class, but it does not provide ability to get access to this fixture from the test. For this purposes I have to define fixtures as parameters of test methods, like:
class TestExample():
def test_one(self, param):
param.return_value = 100
honestly it’s not a big deal, when you have couple of the test. However for huge numbers of the test, where I have the same fixtures, I’d like to hide avoid using fixture parameter. So I have to do it in the such way:
class TestExample():
@pytest.fixture(autouse=True)
def init_fixture(param1, param2):
self.param1 = param1
self.param2 = param2
def test_one(self):
self.param1.return_value = 100
self.param2.return_value = 200
So the main idea -to hide explicitly mentioned fixtures of the function and providing them as class attribute. It’s also can be useful, when you port some test from testscenario extension, where parameters are available as class attributes.
I suppose, that it can be done by improving “mark.usefixtures” decorator, where it allows to add fixtures as class attributes. So potentially decorator can have syntax, like: mark.usefixtures(*args, as_attrs=False), where *args - is list of fixtures, as previously and as_attrs is a flag (defailt is False), which save fixtures as class attributes. In case if function has not class it may be ignored or raise warning message.
Finally I suppose, that it can be done by adding minimal logic here: https://github.com/pytest-dev/pytest/blob/master/_pytest/python.py#L143
def pytest_pyfunc_call(pyfuncitem):
testfunction = pyfuncitem.obj
+ if pyfuncitem.cls:
+ for k, v in pyfuncitem.funcargs:
+ setattr(pyfuncitem.cls, k, v)
if pyfuncitem._isyieldedfunction():
testfunction(*pyfuncitem._args)
else:
funcargs = pyfuncitem.funcargs
testargs = {}
for arg in pyfuncitem._fixtureinfo.argnames:
testargs[arg] = funcargs[arg]
testfunction(**testargs)
return True
Please correct me if I wrong somewhere or share your opinion about such change in the project.
Issue Analytics
- State:
- Created 6 years ago
- Comments:26 (18 by maintainers)
@skraynev great, glad it worked out.
Can I persuade you to write a short post about this to the pytest-tricks blog? 😉
cc @hackebrot
Indeed it might be better to support this using something else other than
pytest.mark.usefixtures
, I don’t know for certain until we see some working code though.But not sure how much more transparent using something else other than
pytest.mark.usefixtures
would be, to be honest.Instead of:
It would be some other construct at the class level anyway, perhaps:
Why would be the first be more transparent than the second, from a user’s point of view?
Unless your point is that using marks for this would be problematic from an implementation POV, but that’s a different discussion.
I’m curious, was
@pytest.mark.usefixtures
added with the intent of making it easy for groups of tests to “auto use” fixtures without declaring them explicitly? Because for a single test case I don’t see much value inmark.usefixtures
as you can just declare that parameter there, but for marking tests in classes and modules it makes more sense. Just curious because I don’t know pytest for so long. 😁