{"id":"39291be2ad38e34d","repo":"pytest-dev/pytest","slug":"runtest-must-be-implemented-by-item-subclass","errorCode":null,"errorMessage":"runtest must be implemented by Item subclass","messagePattern":"runtest must be implemented by Item subclass","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"critical","filePath":"src/_pytest/nodes.py","lineNumber":721,"sourceCode":"        if problems:\n            warnings.warn(\n                f\"{cls.__name__} is an Item subclass and should not be a collector, \"\n                f\"however its bases {problems} are collectors.\\n\"\n                \"Please split the Collectors and the Item into separate node types.\\n\"\n                \"Pytest Doc example: https://docs.pytest.org/en/latest/example/nonpython.html\\n\"\n                \"example pull request on a plugin: https://github.com/asmeurer/pytest-flakes/pull/40/\",\n                PytestWarning,\n            )\n\n    @abc.abstractmethod\n    def runtest(self) -> None:\n        \"\"\"Run the test case for this item.\n\n        Must be implemented by subclasses.\n\n        .. seealso:: :ref:`non-python tests`\n        \"\"\"\n        raise NotImplementedError(\"runtest must be implemented by Item subclass\")\n\n    def add_report_section(self, when: str, key: str, content: str) -> None:\n        \"\"\"Add a new report section, similar to what's done internally to add\n        stdout and stderr captured output::\n\n            item.add_report_section(\"call\", \"stdout\", \"report section contents\")\n\n        :param str when:\n            One of the possible capture states, ``\"setup\"``, ``\"call\"``, ``\"teardown\"``.\n        :param str key:\n            Name of the section, can be customized at will. Pytest uses ``\"stdout\"`` and\n            ``\"stderr\"`` internally.\n        :param str content:\n            The full contents as a string.\n        \"\"\"\n        if content:\n            self._report_sections.append((when, key, content))\n","sourceCodeStart":703,"sourceCodeEnd":739,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/nodes.py#L703-L739","documentation":"Item.runtest is abstract; the base implementation raises NotImplementedError to force every Item subclass to override it. Collection succeeds, but executing the item fails at runtest() because pytest has no way to run an arbitrary test object.","triggerScenarios":"Defining a custom Item subclass (non-python test plugin) and forgetting to implement runtest; collection succeeds then the item errors during the call phase.","commonSituations":"Writing a pytest plugin for a non-Python language/tests per the 'nonpython' example; incomplete subclass; copy of an example with runtest deleted.","solutions":["Implement def runtest(self) -> None: in your Item subclass with the actual test execution logic","If subclassing for collection only, inherit from Collector instead of Item"],"exampleFix":"// before\nclass MyItem(pytest.Item):\n    def collect(self): ...\n// after\nclass MyItem(pytest.Item):\n    def runtest(self):\n        # run the actual test\n        ...\n    def collect(self): ...","handlingStrategy":"validation","validationCode":"def assert_item_has_runtest(item_cls):\n    if 'runtest' not in item_cls.__dict__:\n        raise NotImplementedError(f\"{item_cls.__name__} must implement runtest()\")","typeGuard":"def implements_runtest(cls) -> bool:\n    return 'runtest' in cls.__dict__","tryCatchPattern":null,"preventionTips":["Implement runtest() in every Item subclass before running the suite","Add a unit test that instantiates your Item and calls runtest() to fail fast during plugin development"],"tags":["nodes","plugin-api","pytest","abstract","item"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}