-
-
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
Question regarding fixture visibility #2246
Comments
fixtures can be overridden by plugin order, by making them imported dependencies a major feature would be lost (namely being able to override/switch dependencies fixtures are a "dependency injection" system |
What I'm suggesting here is really not at odds with the current system of dependency injection. What is currently in place is a hierarchy of scopes used to resolve fixture requests. From the pytest documentation, the current hierarchy is:
I'm suggesting that for a given fixture declared in some module, the search should extend beyond the final third-party scope and into the module itself. It wouldn't break anything. One could always override it at any of the many scopes preceding it in the current hierarchy. |
Hi @TristenHayfield, Could you elaborate a bit? In your first message, you mention "package A" and "package B", and in your follow up you mention "the search should extend beyond the final third-party scope and into the module itself". I'm not sure I understand fully what you are proposing (one example or two would be helpful). |
Oops I meant the third-party plugin scope. Assume you have some test which is trying to make use of a fixture provided by another package : test.py: from important_package.fixtures import important_fixture
def test_thing(important_fixture):
pass important_package.fixtures: import pytest
@pytest.fixture
def another_important_fixture():
pass
@pytest.fixture
def important_fixture(another_important_fixture):
pass
Does that make sense? |
nope, the error you see is intentional, the main problem is actual importing of fixtures (that makes them seen as a new fixture at a different place) you either have to do that for all of them or none |
I understand that the error might be intentional, but I'm suggesting that extending the search to As it stands, the only way to use modular fixtures at scale involves using plug-ins, since it doesn't make sense for individual tests to import higher-order dependencies (i.e. the dependencies of dependencies). |
for a fixture a python import is a definition of an entirely new and different fixture so to begin with, it makes no sense to import a single fixture, as its not an import of a fixtur its a definition of a fixture |
FWIW, it is easy to turn any module into a plugin. Using the example you posted all you need is: test.py: pytest_plugins = ['important_package.fixtures']
def test_thing(important_fixture):
pass Also I really like how one can define a fixture in a test module, and when it becomes useful for other test modules the fixture can just be moved to a Also I'm not sure it would be possible to implement this in backward compatible way. As @RonnyPfannschmidt mentioned, in the current design when you import a fixture into a module, it is exactly as if you were defining a new fixture in that scope with the same name. This is actually a common source of errors for users, so much we have tried to figure out ways to warn about it (#1511). |
Thanks @RonnyPfannschmidt for the explanation and thanks @nicoddemus for the helpful example. I didn't realize that one could, in essence, baptize another module as a plugin (this is documented, but I guess I misunderstood it as only applying to plugins (i.e. modules with declared entry points)). It seems that this also recursively processes Imports acting as redefinitions of fixtures is most likely a common source of errors because it's not documented (at least in the fixtures documentation - the one thing that people might want to reuse between tests) and it runs contrary to the normal functioning of Python imports. I'm guessing it's being done for cleanup and isolation between tests. Anyhow, I can see a sane way forward now when it comes to sharing fixtures from other packages, so thank you. |
As discussed in pytest-dev#2246
Sure, glad we could help! Opened #2252 attempting to improve the docs a little. |
Let's say you you have a test in package A which requires a fixture from package B. Currently one can import the fixture into the test or conftest.py and that works just fine.
However if the fixture is a modular fixture (i.e. one which depends on other fixtures), it will only work:
Why doesn't pytest doesn't let modular fixtures use the import mechanism to gain access to their dependencies? My main gripes with having to use the plugin mechanism are:
Any thoughts about this? Or is there another way to go about this issue?
The text was updated successfully, but these errors were encountered: