Skip to content
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

(fixtures): Replace fixture represenation with a class #12473

Open
wants to merge 26 commits into
base: main
Choose a base branch
from

Conversation

Glyphack
Copy link

@Glyphack Glyphack commented Jun 18, 2024

Closes #11525

During the sprint we discussed fixing the above issue and thought maybe it's a better idea to add a better represenation to fixtures. To do this without patching the object more, this PR refactors fixtures to have a class with attributes.
The main rational behind that is:

  • Now we have a type for fixtures makes it easier to check for fixture types and no need to perform cast on objects. Removed monkey patching.
  • They are no longer functions that carry a class within them.
  • When you decorate a function with a fixture it's not possible to call it anymore. So it makes more sense for it to not be a function or method.

Example

Previously we had:

===================================== short test summary info ======================================
FAILED tmp31nzhe4b.py::test_something - assert fixt == 42
======================================== 1 failed in 0.03s =========================================

where fixt is a pytest fixture function that is not replaced by it's value(directly used)

Now we print:

===================================== short test summary info ======================================
FAILED tmp31nzhe4b.py::test_something - assert pytest_fixture(<function fixt at *>) == 42 
======================================== 1 failed in 0.03s =========================================

assert src == " @pytest.fixture\n def deco_fixture():\n assert False\n"
# currently Source does not unwrap decorators, testing the
# existing behavior here for explicitness, but perhaps we should revisit/change this
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was introduced in https://github.com/pytest-dev/pytest/pull/6840/files and I updated it to work with the new code. Please let me know what you think.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i wonder if it is a fair hack to set the __wrapped__ attribute to a property that triggers a deprecationwarning

@Glyphack Glyphack changed the title (assertion): Use repr for pytest fixtures and set repr for pytest fixtures (fixtures): Replace fixture represenation with a class Jun 20, 2024
@psf-chronographer psf-chronographer bot added the bot:chronographer:provided (automation) changelog entry is part of PR label Jun 20, 2024
@Glyphack Glyphack force-pushed the reprs-assert-callable branch 3 times, most recently from bf90fca to d25a8d9 Compare June 20, 2024 13:51
@@ -52,8 +51,8 @@ def __getattr__(self, attr):
with pytest.raises(
ValueError,
match=(
"could not find real function of <Evil left=800>\n"
"stopped at <Evil left=800>"
"could not find real function of <Evil left=900>\n"
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

explanation: previously we were doing 2 get attributes but it's now replaced by isinstance check. So left is 100 more.

@Glyphack Glyphack marked this pull request as ready for review June 20, 2024 15:19
@Glyphack
Copy link
Author

Glyphack commented Jul 4, 2024

Hey @The-Compiler @RonnyPfannschmidt I rebased the PR could you please take a look?

changelog/11525.improvement.rst Outdated Show resolved Hide resolved
def get_real_func(obj):
"""Get the real function object of the (possibly) wrapped object by
functools.wraps or functools.partial."""
functools.wraps or functools.partial or pytest.fixture"""
from _pytest.fixtures import FixtureFunctionDefinition
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to have this import at the top?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is cyclic if I remember correctly. I will try to move it to a another file and try to resolve it

src/_pytest/compat.py Outdated Show resolved Hide resolved
src/_pytest/fixtures.py Outdated Show resolved Hide resolved
src/_pytest/fixtures.py Outdated Show resolved Hide resolved
@@ -478,12 +478,13 @@ def deco_mark():
def deco_fixture():
assert False

src = inspect.getsource(deco_fixture)
# Since deco_fixture is now an instance of FixtureFunctionDef the getsource function will not work on it.
with pytest.raises(Exception):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you assert against a more specific exception? As I understand, this is not testing that something went wrong but it's not clear what exactly. Also, it's usually a good idea to use the match= regex with this helper.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes will apply. This tries to document the behavior more than testing anything. Before introducing the FixtureFunctionDefinition it was possible to run inspect.getsource on fixtures but now it's not. This is just describing the behavior. I'm open to removing it as well.

Glyphack and others added 5 commits July 4, 2024 14:16
Co-authored-by: Sviatoslav Sydorenko (Святослав Сидоренко) <wk.cvs.github@sydorenko.org.ua>
Co-authored-by: Sviatoslav Sydorenko (Святослав Сидоренко) <wk.cvs.github@sydorenko.org.ua>
Co-authored-by: Sviatoslav Sydorenko (Святослав Сидоренко) <wk.cvs.github@sydorenko.org.ua>
Co-authored-by: Sviatoslav Sydorenko (Святослав Сидоренко) <wk.cvs.github@sydorenko.org.ua>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bot:chronographer:provided (automation) changelog entry is part of PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Show repr for callables used in an assert directly
3 participants