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

Fixture with scope=package have incorrect request object #10993

Open
TheoGoudout opened this issue May 12, 2023 · 1 comment
Open

Fixture with scope=package have incorrect request object #10993

TheoGoudout opened this issue May 12, 2023 · 1 comment
Labels
topic: fixtures anything involving fixtures directly or indirectly type: enhancement new feature or API change, should be merged into features branch

Comments

@TheoGoudout
Copy link

When using a fixuture with the package scope, the request object is not of the expected type. To be accurate, the request.node is of type Session when one could expect it to be of type Package.

Versions:

  • python 3.7.16
  • pytest 7.3.1

Example:

import pytest


@pytest.fixture(scope="package")
def package_fixture(request):
    assert False, (type(request.node), request.node)

def test_fixture(package_fixture):
    pass
@bluetech
Copy link
Member

I started working on a fix for this, but ran out of time, so I'll just describe what I believe is the cause.

The problem is in the get_scope_package function:

def get_scope_package(node, fixturedef: "FixtureDef[object]"):
import pytest
cls = pytest.Package
current = node
fixture_package_name = "{}/{}".format(fixturedef.baseid, "__init__.py")
while current and (
type(current) is not cls or fixture_package_name != current.nodeid
):
current = current.parent
if current is None:
return node.session
return current

This function is used by the request.node property when the scope is package. The function assumes that the fixturedef.baseid will be the package's directory. This is true when the package fixture is defined in a conftest.py file. But is wrong when the fixture is defined in a module; in this case the baseid is the module's nodeid (e.g. pkg/test_foo.py), and then fixture_package_name becomes e.g pkg/test_foo.py/__init__.py which is nonsense.

Some non-solutions:

  1. Change the baseid of package fixture defined in a module to the package directory, same as package fixtures defined in a conftest. Doesn't work because the real job of baseid is to determine the fixture's visibility, and for that it's correct -- if a package fixture is defined in pkg/test_foo.py then it shouldn't be visible in pkg/test_bar.py.

  2. Change Package nodeid to package directory instead of the __init__.py file, e.g pkg instead of pkg/__init__.py. This is possible, but causes all sort of hard-to-diagnose breakage, and IMO if we do this then we also need to change the Package.path to the directory, which causes further breakage. It also somewhat breaks Liskov substitution, because currently Package is a subclass of Module.

So what is the solution? I can see why the original author used fixturedef.baseid here, even though it's meant for something else. There is no other info in FixtureDef to pinpoint exactly which Package the fixture belongs to. So I think this information will need to be added in some way to FixtureDef.

Any solution should also consider the similar case of nested classes #5148.

@Zac-HD Zac-HD added type: enhancement new feature or API change, should be merged into features branch topic: fixtures anything involving fixtures directly or indirectly labels May 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: fixtures anything involving fixtures directly or indirectly type: enhancement new feature or API change, should be merged into features branch
Projects
None yet
Development

No branches or pull requests

3 participants