1+ import html
12import os
23import random
34import re
@@ -397,7 +398,7 @@ def run_test(
397398
398399 self .results .accumulate_result (result , runtests )
399400 if runtests .github_annotations :
400- result .print_github_crash_annotation (runtests . fail_env_changed )
401+ result .print_github_annotation (runtests )
401402
402403 return result
403404
@@ -487,34 +488,35 @@ def finalize_tests(self, coverage: trace.CoverageResults | None) -> None:
487488
488489 def write_github_summary (self ) -> None :
489490 filename = os .environ .get ("GITHUB_STEP_SUMMARY" )
491+ # Tests which failed in the last run (the re-run, if any)
492+ failed = self .results .rerun_results
490493 # Only write a summary on failure: a CI run has many test jobs
491494 exitcode = self .results .get_exitcode (self .fail_env_changed ,
492495 self .fail_rerun )
493- if not filename or not exitcode :
496+ if not filename or not failed or not exitcode :
494497 return
495- # Tests which failed in the last run (the re-run, if any)
496- failed = self .results .rerun_results
497498 cases = [(result .errors or []) + (result .failures or [])
498499 for result in failed ]
499- ncase = sum (map (len , cases ))
500+ ncases = sum (map (len , cases ))
500501 with open (filename , "a" , encoding = "utf-8" ) as fp :
501502 def write (text : str ) -> None :
502503 # Separate Markdown blocks with an empty line
503504 print (text , end = "\n \n " , file = fp )
504505
505506 write (f"## { decolor (self .get_state ())} : "
506507 f"{ count (len (failed ), 'test file' )} and "
507- f"{ count (ncase , 'test case' )} failed" )
508+ f"{ count (ncases , 'test case' )} failed" )
508509 for result , result_cases in zip (failed , cases ):
509510 write (f"### { decolor (str (result ))} " )
510511 if result .env_changed_reasons :
511512 write ("\n " .join (f"- { reason } "
512513 for reason in result .env_changed_reasons ))
513514 for name , traceback in result_cases :
514- # Expand short tracebacks when there are only a few
515- is_open = ncase <= 5 and traceback .count ("\n " ) < 30
515+ # Expand the tracebacks if they fit on a screen: up to 5
516+ # test cases with a traceback of less than 30 lines
517+ is_open = ncases <= 5 and traceback .count ("\n " ) < 30
516518 write (f"<details{ ' open' if is_open else '' } >"
517- f"<summary>{ name } </summary>" )
519+ f"<summary>{ html . escape ( name ) } </summary>" )
518520 write (f"```pytb\n { decolor (traceback ).rstrip ()} \n ```" )
519521 write ("</details>" )
520522
@@ -538,6 +540,12 @@ def display_summary(self) -> None:
538540 print (f"Result: { state } " )
539541
540542 def create_run_tests (self , tests : TestTuple ) -> RunTests :
543+ # Annotate test failures in the GitHub Actions job log of the last
544+ # run (the re-run, if any), if it reports failures
545+ will_rerun = self .want_rerun and not self .python_cmd
546+ github_annotations = (bool (os .environ .get ("GITHUB_STEP_SUMMARY" ))
547+ and not will_rerun
548+ and bool (self .verbose or self .output_on_failure ))
541549 return RunTests (
542550 tests ,
543551 fail_fast = self .fail_fast ,
@@ -555,10 +563,7 @@ def create_run_tests(self, tests: TestTuple) -> RunTests:
555563 hunt_refleak = self .hunt_refleak ,
556564 test_dir = self .test_dir ,
557565 use_junit = (self .junit_filename is not None ),
558- # Only annotate failures of the last run: the re-run, if any
559- github_annotations = (bool (os .environ .get ("GITHUB_STEP_SUMMARY" ))
560- and not (self .want_rerun
561- and not self .python_cmd )),
566+ github_annotations = github_annotations ,
562567 coverage = self .coverage ,
563568 memory_limit = self .memory_limit ,
564569 gc_threshold = self .gc_threshold ,
0 commit comments