pytest: Main and 8.0.x (not released yet): cannot find fixture when using --pyargs
- a detailed description of the bug or problem you are having
- output of
pip list
from the virtual environment you are using - pytest and operating system versions
- minimal example if possible
While adding a comment to https://github.com/pytest-dev/pytest/issues/9765#issuecomment-1891056936 to reproduce that issue, I noticed another problem (not released yet, only the main
and 8.0.x
branches).
Reproduce the issue
python -m pip install "ewokscore[test]==0.7.1" git+https://github.com/pytest-dev/pytest.git@main
python -m pytest -v --pyargs ewokscore.tests
or also
python -m pip install "ewokscore[test]==0.7.1" git+https://github.com/pytest-dev/pytest.git@8.0.x
python -m pytest -v --pyargs ewokscore.tests
Released pytest versions do not show the problem. For example this works find:
python -m pip install "ewokscore[test]==0.7.1" "pytest==7.4.4"
python -m pytest -v --pyargs ewokscore.tests
Os and python version
- Ubuntu 20.04, python 3.10.12: works
- Windows 11, python 3.8.10: fails
Error message
The error says it cannot find the varinfo
dependency which is defined in the module ewokscore.tests.conftest
.
@pytest.mark.parametrize("value", VALUES)
def test_variable_references(value, varinfo):
E fixture 'varinfo' not found
> available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory
> use 'pytest --fixtures [testpath]' for help on them.
About this issue
- Original URL
- State: closed
- Created 6 months ago
- Comments: 15 (15 by maintainers)
The issue is here:
https://github.com/pytest-dev/pytest/blob/348e6de102c5a5ccdaab88c860d57b1f49f7b1d2/src/_pytest/fixtures.py#L1486-L1506
A bit dense technical explanation, hopefully you manage to follow đ
When a conftest plugin (and any other plugin) is registered, pytest calls the
pytest_plugin_registered
hook. The fixtures code implements this hook to register the fixtures defined in the plugin.When you register a fixture, you need to define its âvisibilityâ AKA
baseid
. Thebaseid
is a nodeid, and a test can only âseeâ a fixture if thebaseid
is the nodeid of one of its parents (seematchfactories
function).When a fixture is defined in e.g. some test file, the visibility is the specific node itâs defined in, e.g. the
Module
node (runpytest --collect-only
to see the collection tree).When a fixture is defined in a conftest plugin (the relevant case for this issue), the visibility logically is supposed to be the conftestâs directory. In practice this is done in the code above â the
baseid
(thenodeid
variable in the code above) is synthesized from theplugin.__file__
.As weâve already learned from #9765, relying on both
__file__
and user-input paths is problematic. @woutdenolf solution in PR #11821 is to go back to relying on__file__
for registration and normalizing it more. But in #9765 the solution weâve decided on is the opposite, that is, avoid relying on__file__
as much as possible.Therefore, the PR I would like to see instead is to change the
fixtures.py
pytest_plugin_registered
hook impl to not rely onplugin.__file__
. Some ways I can think to do this:Instead of using
plugin.__file__
, use the registration name, which for conftest plugins is the original conftest path as we registered it. The hookimpl can doplugin_name = manager.get_name(plugin)
then use that instead of__file__
.Internally in pluggy (pytestâs plugin system),
get_name(plugin)
is currently a linear search, which might get somewhat slow with many plugins. Maybe we donât care about it, but if we do, can do one of these instead:plugin_name
parameter to thepytest_plugin_registered
hook.Longer term, I really think we should tie conftests to
Directory
nodes (new in pytest 8.0), this is something Iâm working toward but itâs speculative and not applicable for the short term.@woutdenolf @lesteve Itâd be great if one of you could try this and see if it indeed fixes the issue.