{"id":"122c9a5fe1b0fe1d","repo":"pytest-dev/pytest","slug":"function-definitions-are-not-supposed-to-be-run-as","errorCode":null,"errorMessage":"function definitions are not supposed to be run as tests","messagePattern":"function definitions are not supposed to be run as tests","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/python.py","lineNumber":1833,"sourceCode":"        return excinfo.traceback\n\n    # TODO: Type ignored -- breaks Liskov Substitution.\n    def repr_failure(  # type: ignore[override]\n        self,\n        excinfo: ExceptionInfo[BaseException],\n    ) -> str | TerminalRepr:\n        style = self.config.getoption(\"tbstyle\", \"auto\")\n        if style == \"auto\":\n            style = \"long\"\n        return self._repr_failure_py(excinfo, style=style)\n\n\nclass FunctionDefinition(Function):\n    \"\"\"This class is a stop gap solution until we evolve to have actual function\n    definition nodes and manage to get rid of ``metafunc``.\"\"\"\n\n    def runtest(self) -> None:\n        raise RuntimeError(\"function definitions are not supposed to be run as tests\")\n\n    setup = runtest\n\n\ndef __getattr__(name: str) -> object:\n    if name == \"CallSpec2\":\n        warnings.warn(CALLSPEC2_RENAMED, stacklevel=2)\n        return CallSpec\n    raise AttributeError(f\"module {__name__!r} has no attribute {name!r}\")\n","sourceCodeStart":1815,"sourceCodeEnd":1843,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/python.py#L1815-L1843","documentation":"Raised by FunctionDefinition.runtest (and its alias setup) when pytest attempts to execute a FunctionDefinition node as a test. FunctionDefinition is a placeholder node representing a function *definition* collected for introspection (e.g. a non-test function or a fixture-bearing function) that must never be run. Seeing this means the collection tree is misconfigured such that a definition node reached the runtest phase.","triggerScenarios":"A plugin or hook that forces runtest on a FunctionDefinition; manually invoking item.runtest() on a FunctionDefinition item; an internal collection inconsistency where a def-only node is treated as a test item.","commonSituations":"Custom collection plugins that subclass Function incorrectly; calling pytest internals directly in a test; a stale plugin incompatible with the current pytest version where FunctionDefinition semantics changed.","solutions":["Do not call runtest() on FunctionDefinition nodes; only runtest concrete Function test items.","Check item.__class__ is Function (not FunctionDefinition) before invoking runtest in plugin code.","Update the custom collection plugin to produce proper test Function nodes.","Report a bug to the plugin if it forces execution of definition nodes."],"exampleFix":"// before\nfor item in session.items:\n    item.runtest()  # may include FunctionDefinition\n// after\nfrom _pytest.python import Function\nfor item in session.items:\n    if isinstance(item, Function):\n        item.runtest()","handlingStrategy":"type-guard","validationCode":"from _pytest.python import Function, FunctionDefinition\n\ndef is_runnable(item) -> bool:\n    return isinstance(item, Function) and not isinstance(item, FunctionDefinition)\n\nfor item in items:\n    if is_runnable(item):\n        item.runtest()","typeGuard":"from _pytest.python import Function, FunctionDefinition\n\ndef is_test_function(item) -> bool:\n    return isinstance(item, Function) and not isinstance(item, FunctionDefinition)","tryCatchPattern":null,"preventionTips":["Never call runtest on FunctionDefinition nodes.","Check item type before invoking runtest in plugins.","Keep collection plugins updated with the installed pytest version."],"tags":["internal","collection","runtest"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}