Skip to content

Commit c2e037a

Browse files
better parsing for pytest stdout
1 parent 1120d64 commit c2e037a

File tree

1 file changed

+41
-27
lines changed

1 file changed

+41
-27
lines changed

codeflash/verification/parse_test_output.py

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -512,44 +512,58 @@ def merge_test_results(
512512
return merged_test_results
513513

514514

515+
FAILURES_HEADER_RE = re.compile(r"=+ FAILURES =+")
516+
TEST_HEADER_RE = re.compile(r"_{3,}\s*(.*?)\s*_{3,}$")
517+
518+
515519
def parse_test_failures_from_stdout(test_results: TestResults, stdout: str) -> TestResults:
516-
stdout_lines = stdout.splitlines()
517-
start_line = end_line = None
518-
519-
for i, line in enumerate(stdout_lines):
520-
stripped_line = line.strip()
521-
if start_line is None and stripped_line[0] == "=" and "FAILURES" in stripped_line:
522-
start_line = i
523-
# exclude last summary line
524-
elif start_line is not None and end_line is None and "short test summary info" in stripped_line:
525-
end_line = i
520+
"""Extract individual pytest test failures from stdout grouped by test case qualified name, and add them to the test results."""
521+
lines = stdout.splitlines()
522+
start = end = None
523+
524+
for i, line in enumerate(lines):
525+
if FAILURES_HEADER_RE.search(line.strip()):
526+
start = i
526527
break
527528

528-
if start_line is None or end_line is None:
529+
if start is None:
529530
return test_results
530531

531-
complete_failure_output_lines = stdout_lines[start_line:end_line]
532+
for j in range(start + 1, len(lines)):
533+
stripped = lines[j].strip()
534+
if "short test summary info" in stripped:
535+
end = j
536+
break
537+
# any new === section === block
538+
if stripped.startswith("=") and stripped.count("=") > 3:
539+
end = j
540+
break
541+
542+
# If no clear "end", just grap the rest of the string
543+
if end is None:
544+
end = len(lines)
532545

533-
test_case_to_failure: dict[str, str] = {}
546+
failure_block = lines[start:end]
534547

535-
current_test_case: str | None = None
536-
current_failure_lines: list[str] = []
548+
failures: dict[str, str] = {}
549+
current_name = None
550+
current_lines: list[str] = []
537551

538-
underline_prefix = "_______"
552+
for line in failure_block:
553+
m = TEST_HEADER_RE.match(line.strip())
554+
if m:
555+
if current_name is not None:
556+
failures[current_name] = "".join(current_lines)
539557

540-
for line in complete_failure_output_lines:
541-
if line and line[0] == "_" and line.startswith(underline_prefix):
542-
if current_test_case:
543-
test_case_to_failure[current_test_case] = "".join(current_failure_lines)
544-
current_test_case = line.strip("_ ").strip()
545-
current_failure_lines.clear()
546-
elif current_test_case:
547-
current_failure_lines.append(line + "\n")
558+
current_name = m.group(1)
559+
current_lines = []
560+
elif current_name:
561+
current_lines.append(line + "\n")
548562

549-
if current_test_case:
550-
test_case_to_failure[current_test_case] = "".join(current_failure_lines)
563+
if current_name:
564+
failures[current_name] = "".join(current_lines)
551565

552-
test_results.test_failures = test_case_to_failure
566+
test_results.test_failures = failures
553567
return test_results
554568

555569

0 commit comments

Comments
 (0)