Open madhadron opened 1 year ago
That is intentional
If you want the parent fixture to run, take it as a parameter
Should you at least provide a warning that it is being shadowed?
Introduction of a marker to indicate whether a fixture should be overridden seems like a good ida, there is a number of cases where its intentional
If you want the parent fixture to run, take it as a parameter
(you accidentally posted twice, I deleted the redundant comment)
Looks like even that doesn't always work. I didn't try with conftest.py
files, but if you have two plugins, depending on plugin order, the "overriding" fixture will actually be loaded first, and then be shadowed by the to-be-overridden one. While the overriding one has an (unresolved) dependency on the to-be-overridden one, it's never actually called, so there is no failure.
Here is a reproducer:
import pytest
pytest_plugins = ["pytester"]
class Plugin1:
@pytest.fixture
def fixt(self):
pass
class Plugin2:
@pytest.fixture
def fixt(self, fixt):
1/0 # never gets called
def test_override(pytester):
pytester.makepyfile("""
def test_fixt(fixt):
pass
""")
res = pytester.runpytest("--setup-show", plugins=[Plugin2(), Plugin1()]) # change plugin order to make override work
print(res.stdout)
assert False
While here it's trivial to change the plugin order, for conftest.py
files (or installed plugins), that's not going to work.
I had a few discussions here with @lovetheguitar about this, but we didn't really get anywhere. The gist of it is that overriding fixtures is both done accidentally (as in the OP or my comment above), as well as intentionally (e.g. many plugins let you override a fixture in your conftest.py
to configure some aspect of it).
I like the idea that @RonnyPfannschmidt had mentioned above, and would imagine that as a @pytest.fixture(override=True)
, with pytest emitting a warning if an override happens without override=True
being given.
Open questions:
def fixt(fixt):
where it's quite clear we're explicitly overriding and extending fixt
, rather than just shadowing it?this has some special edge cases - some fixutres are intended to be replaced (like the webdriver ones for selenium, others are not, but may or may not end up overtwritten depending on known plugins
When there is a conftest.py in a subdirectory that contains a pytest.fixture of the same name as one in a conftest.py file in a parent directory, the fixture in the subdirectory runs for tests in the subdirectory, but the one in the parent does not.
Repro
Create a directory. Put in:
conftest.py
conftest.py
test_hello.py
submod/__init__.py
(empty file)submod/test_hello.py
with the same contents as test_hello.py above.submod/conftest.py
with the same contents as test_hello.py above, but with "file" changed to "file2".Run pytest in the root directory with
--junitxml=output.xml
. The output will be:instead of having a
file
property on both.pytest version 6.2.5