pytest-dev/pytest · error · RuntimeError
function definitions are not supposed to be run as tests
Error message
function definitions are not supposed to be run as tests
What it means
Thrown by FunctionDefinition.runtest() (and setup, which aliases runtest). FunctionDefinition represents a function collected as a definition node (e.g. for metafunc inspection) that is not meant to be executed as a test. Attempting to run it indicates a collection/handler mismatch.
Solutions
- Do not call runtest() on FunctionDefinition nodes; use Function items for execution.
- Check isinstance(node, Function) and not FunctionDefinition before running.
- Use the standard pytest_runtest_call hook pathway instead of invoking runtest directly.
Example fix
// before
for node in session.items:
node.runtest()
// after
for node in session.items:
if isinstance(node, FunctionDefinition):
continue
node.runtest() Defensive patterns
Strategy: type-guard
Validate before calling
from _pytest.python import Function, FunctionDefinition
for node in session.items:
if isinstance(node, FunctionDefinition):
continue
node.runtest() Type guard
from _pytest.python import FunctionDefinition
def is_runnable_function(node) -> bool:
return not isinstance(node, FunctionDefinition) Prevention
- Skip FunctionDefinition nodes when iterating collection items.
- Use the standard pytest_runtest_call hook for execution.
- Do not call runtest() directly on definition nodes.
When it happens
Trigger: A plugin or hook calling node.runtest() on a FunctionDefinition node directly; a custom item subclass that delegates to FunctionDefinition; misuse of the internal stop-gap API.
Common situations: Writing pytest plugins that walk the collection tree and invoke runtest; test frameworks built on pytest internals; version differences where Function vs FunctionDefinition handling changed.
Related errors
- Can't find module at location
- cannot delete key in keywords dict
- Could not resolve for
- directory argument cannot contain :: selection parts
- Expected a float string for option
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/122c9a5fe1b0fe1d.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/python.py:1833
return excinfo.traceback
# TODO: Type ignored -- breaks Liskov Substitution.
def repr_failure( # type: ignore[override]
self,
excinfo: ExceptionInfo[BaseException],
) -> str | TerminalRepr:
style = self.config.getoption("tbstyle", "auto")
if style == "auto":
style = "long"
return self._repr_failure_py(excinfo, style=style)
class FunctionDefinition(Function):
"""This class is a stop gap solution until we evolve to have actual function
definition nodes and manage to get rid of ``metafunc``."""
def runtest(self) -> None:
raise RuntimeError("function definitions are not supposed to be run as tests")
setup = runtest
def __getattr__(name: str) -> object:
if name == "CallSpec2":
warnings.warn(CALLSPEC2_RENAMED, stacklevel=2)
return CallSpec
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
View on GitHub (pinned to 0d6fbdeffa)