-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Propagating fixtures to test class attribute #2618
Comments
from my pov a feature like that is absolutely unacceptable as it is a start to introduce hidden dependencies one point of fixtures is to show dependencies explicitly, so people make less of a mess, making them secretly be added into objects and just appear at a distance is the antithesis to this |
Ronny, thank you for the feedback. I agree, that it may confuse people if it be default. That's why I propose, to disable it by default and add ability to enable it by request. |
I like the idea FWIW. Usually, explicit is better than implicit, but this still strikes me as explicit enough and removes quite some boilerplate. |
IIRC, the new I'm +0, IMHO this is not much more implicit than Having said that are you still strictly opposed @RonnyPfannschmidt? |
yes, imho a explicit class level fixture that sets the attribute is waaaaay more transparent and already supported directly without anyhacks from my pov usefixtures is a unfortunate hack and we should completely remove the need to have it |
Indeed it might be better to support this using something else other than But not sure how much more transparent using something else other than Instead of: @pytest.mark.usefixtures('tmpdir', 'foobar', as_attrs=True)
class Test:
... It would be some other construct at the class level anyway, perhaps: @pytest.fixtures_as_attrs('tmpdir', 'foobar')
class Test:
... 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 |
is while a bit more verbose order of magnitude more simple to comprehend |
I see, that's what I do currently when I need something like this (except I make But I thought that's what @The-Compiler commented about being a little verbose? @skraynev were you aware of the above solution? |
@nicoddemus I read you message and understand, that I do the same right now :)
It really irritate to copy paste the same structure for each class. I tried to use some parent class, but I have not any idea how should look common fixture, which allow to pass any kind of named parameters. |
i believe its possible to use a mixin class (but i haven't tried yet) |
@RonnyPfannschmidt Could you try it? because I am not sure, which parent classes for such mixin you plan to use. |
nope |
I cooked up this solution using a class-decorator: from functools import partial
import pytest
def _inject(cls, names):
@pytest.fixture(autouse=True)
def auto_injector_fixture(self, request):
for name in names:
setattr(self, name, request.getfixturevalue(name))
cls._auto_injector_fixture = auto_injector_fixture
return cls
def auto_inject_fixtures(*names):
return partial(_inject, names=names)
@auto_inject_fixtures('tmpdir')
class Test:
def test_foo(self):
assert self.tmpdir.isdir() It also works for @auto_inject_fixtures('tmpdir')
class Test2(unittest.TestCase):
def test_foo(self):
self.assertTrue(self.tmpdir.isdir()) |
@nicoddemus Awesome. You are rock. I have not known about 'getfixturevalue' . I tried and it perfectly works for me. Also I a little bit modified it to apply for case, when you have one main Test class. So it looks like:
As you can see, it uses class attribute, (fixture_names) where user may define his fixtures for visibility. |
@skraynev thanks for the follow-up that includes your working solution, those follow-ups are rare and commendable 👍 |
@RonnyPfannschmidt np. Thank you all guys for the fast response and help. I forgot to ask, what do you think about adding some of these snippets to official doc? I suppose, that it can be mentioned near Fast port of testscenarios. Honestly I searched something like that there before starting this issue. |
personally i am biased a bit against it, @nicoddemus whats your oppinion? |
@skraynev great, glad it worked out. Can I persuade you to write a short post about this to the pytest-tricks blog? 😉 cc @hackebrot |
Oh sorry missed the last two comments. Hmm I'm not against adding it to the docs, we should only warn the user about the downsides (like we do anyway with |
@nicoddemus Honestly I have not heard about pytest-tricks blog. IMHO, it should be better, then docs. |
@skraynev sounds good, thanks! |
@nicoddemus I have one partially related question. Is it expected behavior, that for TestCase class method: pytest_generate_tests , will not be run ? |
@skraynev pytest_generate_tests is incompatible with unittest |
Hi @skraynev
Probably not. In general, pytest aims to support standard We probably should explicitly state what is supported in the |
Created #2626 to improve the docs regarding that topic. |
@RonnyPfannschmidt @nicoddemus Got it. Thank you guys for the clear explanation |
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:
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:
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
Please correct me if I wrong somewhere or share your opinion about such change in the project.
The text was updated successfully, but these errors were encountered: