pytest-dev / pytest-dev/pytest

`FixtureLookupError.formatrepr` uses `_pyfuncitem.obj`, which is not part of the `pytest.Item` interface

Open
#12,804 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
14.5k
Forks
3.4k
Avg merge
2d 9h
Merged PRs (30d)
35

Description

Sybil's pytest integration allows users to request pytest fixtures.

Currently, if you typo a fixture name, you get this horrible internal error:

E       ============================= test session starts ==============================
E       platform darwin -- Python 3.10.7, pytest-8.0.0, pluggy-1.4.0 -- /Users/chris/virtualenvs/sybil_310/bin/python
E       cachedir: .pytest_cache
E       rootdir: /private/var/folders/m6/tsd59qsj7pd_lldh4mhwh6kh0000gn/T/pytest-of-chris/pytest-71/test_request_missing_fixtures0
E       plugins: cov-4.0.0
E       collecting ... collected 1 item
E       
E       ../../../../../private/var/folders/m6/tsd59qsj7pd_lldh4mhwh6kh0000gn/T/pytest-of-chris/pytest-71/test_request_missing_fixtures0/test.rst::line:1,column:1 
E       INTERNALERROR> Traceback (most recent call last):
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/main.py", line 272, in wrap_session
E       INTERNALERROR>     session.exitstatus = doit(config, session) or 0
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/main.py", line 326, in _main
E       INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_hooks.py", line 501, in __call__
E       INTERNALERROR>     return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_manager.py", line 119, in _hookexec
E       INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 138, in _multicall
E       INTERNALERROR>     raise exception.with_traceback(exception.__traceback__)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 121, in _multicall
E       INTERNALERROR>     teardown.throw(exception)  # type: ignore[union-attr]
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/logging.py", line 796, in pytest_runtestloop
E       INTERNALERROR>     return (yield)  # Run all the tests.
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 102, in _multicall
E       INTERNALERROR>     res = hook_impl.function(*args)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/main.py", line 351, in pytest_runtestloop
E       INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_hooks.py", line 501, in __call__
E       INTERNALERROR>     return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_manager.py", line 119, in _hookexec
E       INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 138, in _multicall
E       INTERNALERROR>     raise exception.with_traceback(exception.__traceback__)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 121, in _multicall
E       INTERNALERROR>     teardown.throw(exception)  # type: ignore[union-attr]
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/warnings.py", line 109, in pytest_runtest_protocol
E       INTERNALERROR>     return (yield)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 121, in _multicall
E       INTERNALERROR>     teardown.throw(exception)  # type: ignore[union-attr]
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/assertion/__init__.py", line 174, in pytest_runtest_protocol
E       INTERNALERROR>     return (yield)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 121, in _multicall
E       INTERNALERROR>     teardown.throw(exception)  # type: ignore[union-attr]
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/unittest.py", line 408, in pytest_runtest_protocol
E       INTERNALERROR>     res = yield
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 121, in _multicall
E       INTERNALERROR>     teardown.throw(exception)  # type: ignore[union-attr]
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/faulthandler.py", line 85, in pytest_runtest_protocol
E       INTERNALERROR>     return (yield)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 102, in _multicall
E       INTERNALERROR>     res = hook_impl.function(*args)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/runner.py", line 114, in pytest_runtest_protocol
E       INTERNALERROR>     runtestprotocol(item, nextitem=nextitem)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/runner.py", line 127, in runtestprotocol
E       INTERNALERROR>     rep = call_and_report(item, "setup", log)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/runner.py", line 228, in call_and_report
E       INTERNALERROR>     report: TestReport = hook.pytest_runtest_makereport(item=item, call=call)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_hooks.py", line 501, in __call__
E       INTERNALERROR>     return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_manager.py", line 119, in _hookexec
E       INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 138, in _multicall
E       INTERNALERROR>     raise exception.with_traceback(exception.__traceback__)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 121, in _multicall
E       INTERNALERROR>     teardown.throw(exception)  # type: ignore[union-attr]
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/tmpdir.py", line 316, in pytest_runtest_makereport
E       INTERNALERROR>     rep = yield
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 121, in _multicall
E       INTERNALERROR>     teardown.throw(exception)  # type: ignore[union-attr]
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/skipping.py", line 269, in pytest_runtest_makereport
E       INTERNALERROR>     rep = yield
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/pluggy/_callers.py", line 102, in _multicall
E       INTERNALERROR>     res = hook_impl.function(*args)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/runner.py", line 372, in pytest_runtest_makereport
E       INTERNALERROR>     return TestReport.from_item_and_call(item, call)
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/reports.py", line 366, in from_item_and_call
E       INTERNALERROR>     longrepr = item._repr_failure_py(
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/nodes.py", line 464, in _repr_failure_py
E       INTERNALERROR>     return excinfo.value.formatrepr()
E       INTERNALERROR>   File "/Users/chris/virtualenvs/sybil_310/lib/python3.10/site-packages/_pytest/fixtures.py", line 822, in formatrepr
E       INTERNALERROR>     stack = [self.request._pyfuncitem.obj]
E       INTERNALERROR> AttributeError: 'SybilItem' object has no attribute 'obj'
E       
E       ============================ no tests ran in 0.01s =============================

This is because FixtureLookupError.formatrepr uses _pyfuncitem.obj, which is not part of the pytest.Item interface.

It's been years now, and I really wish pytest could sort out a stable API for things that provided other types of item to request fixtures :-/

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read src/_pytest/fixtures.py at FixtureLookupError.formatrepr and review the pytest.Item interface. Reproduce the missing-fixture case through Sybil's pytest integration, then verify that a typo produces a useful fixture error instead of an AttributeError while remaining compatible with pytest.Item implementations.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
testing-qa
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.