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

Bug with Callable type for duplicate fixture detection #47

Open
Sanchoyzer opened this issue Apr 1, 2024 · 0 comments
Open

Bug with Callable type for duplicate fixture detection #47

Sanchoyzer opened this issue Apr 1, 2024 · 0 comments

Comments

@Sanchoyzer
Copy link

Sanchoyzer commented Apr 1, 2024

It seems that the plugin doesn't fully support the Callable type for duplicate fixture detection. For all fixtures with Callable return type, the plugin displays a warning that there are duplicate fixtures.

Source code

from collections.abc import Callable

import pytest
from faker import Faker


class A:
    x: int

    def __init__(self, x: int) -> None:
        self.x = x


class B:
    y: str

    def __init__(self, y: str) -> None:
        self.y = y


@pytest.fixture(scope='session')
def faker() -> Faker:
    return Faker()


@pytest.fixture
def factory_A(faker: Faker) -> Callable[[], A]:
    def inner() -> A:
        return A(x=faker.pyint())

    return inner


@pytest.fixture
def factory_B(faker: Faker) -> Callable[[], B]:
    def inner() -> B:
        return B(y=faker.pystr())

    return inner


def test_factories(factory_A: Callable[[], A], factory_B: Callable[[], B]) -> None:
    object_a = factory_A()
    object_b = factory_B()
    assert object_a.x != object_b.y

Run

pytest test_1.py --dup-fixtures

You may have some duplicate fixtures:
Fixture name: factory_B, location: test_1.py:35
Fixture name: factory_A, location: test_1.py:27

Versions

pytest==8.1.1
pytest-deadfixtures==2.2.1

Maybe the same_fixture function should be changed. From

def same_fixture(one, two):
    def result_same_type(a, b):
        return isinstance(a.result, type(b.result))

    def same_result(a, b):
        if not a.result or not b.result:
            return False
        if hasattr(a.result, "__dict__") or hasattr(b.result, "__dict__"):
            return a.result.__dict__ == b.result.__dict__
        return a.result == b.result

    def same_loc(a, b):
        return a.relpath == b.relpath

    return result_same_type(one, two) and same_result(one, two) and not same_loc(one, two)

to

def same_fixture(one, two):
    def result_same_type(a, b):
        return isinstance(a.result, type(b.result))

    def same_result(a, b):
        if not a.result or not b.result:
            return False
        if getattr(a.result, "__dict__", None) and getattr(b.result, "__dict__", None):  # here
            return a.result.__dict__ == b.result.__dict__
        return a.result == b.result

    def same_loc(a, b):
        return a.relpath == b.relpath

    return result_same_type(one, two) and same_result(one, two) and not same_loc(one, two)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant