Format a summary table of failed tests with re-run commands. Args: failed_tests: List of FailedTestEntry objects. Returns: Formatted string with failure summary table.
(
failed_tests: list[FailedTestEntry],
)
| 930 | |
| 931 | |
| 932 | def _format_failure_summary( |
| 933 | failed_tests: list[FailedTestEntry], |
| 934 | ) -> str: |
| 935 | """Format a summary table of failed tests with re-run commands. |
| 936 | |
| 937 | Args: |
| 938 | failed_tests: List of FailedTestEntry objects. |
| 939 | |
| 940 | Returns: |
| 941 | Formatted string with failure summary table. |
| 942 | """ |
| 943 | if not failed_tests: |
| 944 | return "" |
| 945 | |
| 946 | lines: list[str] = [] |
| 947 | lines.append("") |
| 948 | lines.append("\033[91m" + "=" * 60 + "\033[0m") |
| 949 | lines.append("\033[91mFAILED TESTS SUMMARY\033[0m") |
| 950 | lines.append("\033[91m" + "=" * 60 + "\033[0m") |
| 951 | |
| 952 | # Table header |
| 953 | max_name = max(len(ft.clean_name) for ft in failed_tests) |
| 954 | max_name = max(max_name, 4) # min width for "Test" |
| 955 | header = f" {'Test':<{max_name}} | {'Category':<8} | Re-run command" |
| 956 | sep = f" {'-' * max_name}-+-{'-' * 8}-+-{'-' * 30}" |
| 957 | lines.append(header) |
| 958 | lines.append(sep) |
| 959 | |
| 960 | for ft in failed_tests: |
| 961 | lines.append( |
| 962 | f" {ft.clean_name:<{max_name}} | {ft.category:<8} | {ft.rerun_cmd}" |
| 963 | ) |
| 964 | |
| 965 | lines.append("") |
| 966 | lines.append("To re-run failed tests:") |
| 967 | for ft in failed_tests: |
| 968 | lines.append(f" {ft.rerun_cmd}") |
| 969 | lines.append("") |
| 970 | |
| 971 | # Loud banner for debug re-run — this is critical for AI agents to notice |
| 972 | max_debug_show = 3 |
| 973 | lines.append("\033[93m" + "!" * 60 + "\033[0m") |
| 974 | lines.append( |
| 975 | "\033[93m!! AGENT ACTION REQUIRED: RE-RUN FAILED TESTS IN DEBUG !!\033[0m" |
| 976 | ) |
| 977 | lines.append("\033[93m" + "!" * 60 + "\033[0m") |
| 978 | lines.append("") |
| 979 | lines.append("Quick mode does NOT enable sanitizers (ASAN/LSAN/UBSAN).") |
| 980 | lines.append("You MUST re-run each failed test in --debug mode to get") |
| 981 | lines.append("full diagnostics (stack traces, memory errors, UB detection).") |
| 982 | lines.append("") |
| 983 | lines.append("\033[93mRun these commands NOW:\033[0m") |
| 984 | for ft in failed_tests[:max_debug_show]: |
| 985 | lines.append(f" \033[1m{ft.debug_cmd}\033[0m") |
| 986 | if len(failed_tests) > max_debug_show: |
| 987 | lines.append( |
| 988 | f" ... and {len(failed_tests) - max_debug_show} more failed tests" |
| 989 | ) |