@@ -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+
515519def 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