{"id":"9dd040c5d7725072","repo":"pytest-dev/pytest","slug":"pytest-terminal-summary-report-not-found","errorCode":null,"errorMessage":"Pytest terminal summary report not found","messagePattern":"Pytest terminal summary report not found","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/pytester.py","lineNumber":585,"sourceCode":"        return self.parse_summary_nouns(self.outlines)\n\n    @classmethod\n    def parse_summary_nouns(cls, lines) -> dict[str, int]:\n        \"\"\"Extract the nouns from a pytest terminal summary line.\n\n        It always returns the plural noun for consistency::\n\n            ======= 1 failed, 1 passed, 1 warning, 1 error in 0.13s ====\n\n        Will return ``{\"failed\": 1, \"passed\": 1, \"warnings\": 1, \"errors\": 1}``.\n        \"\"\"\n        for line in reversed(lines):\n            if rex_session_duration.search(line):\n                outcomes = rex_outcome.findall(line)\n                ret = {noun: int(count) for (count, noun) in outcomes}\n                break\n        else:\n            raise ValueError(\"Pytest terminal summary report not found\")\n\n        to_plural = {\n            \"warning\": \"warnings\",\n            \"error\": \"errors\",\n        }\n        return {to_plural.get(k, k): v for k, v in ret.items()}\n\n    def assert_outcomes(\n        self,\n        passed: int = 0,\n        skipped: int = 0,\n        failed: int = 0,\n        errors: int = 0,\n        xpassed: int = 0,\n        xfailed: int = 0,\n        warnings: int | None = None,\n        deselected: int | None = None,\n    ) -> None:","sourceCodeStart":567,"sourceCodeEnd":603,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/pytester.py#L567-L603","documentation":"Raised by RunResult.parse_summary_nouns when it scans the output lines in reverse looking for a line matching the session-duration regex (rex_session_duration) and finds none. Without that summary line it cannot extract the passed/failed/skipped counts, so assert_outcomes cannot proceed. This means the pytest run did not emit its normal terminal summary.","triggerScenarios":"Calling result.assert_outcomes() on a RunResult whose captured stdout lacks the trailing '===== N passed in X.XXs =====' summary line, because the run was killed, crashed, used a non-default reporter (e.g. -p no:terminal), or the output was truncated.","commonSituations":"A pytest subprocess that segfaulted or was killed by a timeout; running with '-q' plus a plugin that suppresses the summary; an internal error during session teardown; capturing only stderr instead of stdout; pexpect/spawn runs whose output was not flushed before assertion.","solutions":["Print/inspect result.stdout lines to see where the run stopped before the summary.","Ensure the terminal reporter plugin is enabled (avoid -p no:terminal).","Increase subprocess timeout if the run was killed mid-execution.","Re-run with -v / default options so the standard summary line is emitted."],"exampleFix":"// before\nresult = pytester.runpytest_subprocess(\"-p\", \"no:terminal\")\nresult.assert_outcomes(passed=1)  # no summary line exists\n// after\nresult = pytester.runpytest_subprocess()\nresult.assert_outcomes(passed=1)","handlingStrategy":"validation","validationCode":"import re\nsummary_present = any(re.search(r\"in \\d\\.\\d+s\", line) for line in result.stdout.lines)\nif not summary_present:\n    print(result.stdout.str())\n    raise AssertionError(\"no summary line; run likely crashed\")\nresult.assert_outcomes(passed=1)","typeGuard":null,"tryCatchPattern":"try:\n    result.assert_outcomes(passed=1)\nexcept ValueError:\n    # dump output for diagnosis\n    print(result.stdout.str())\n    raise","preventionTips":["Do not disable the terminal reporter (-p no:terminal) in runs you later assert on.","Ensure subprocess timeouts are large enough.","Capture and inspect stdout before calling assert_outcomes."],"tags":["pytester","output-parsing","assertion"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}