Hi!
I have around 300 suites.
How to see in console amount of suites waiting to be run?
I am running cases with pabot.
For example I want to see in console something like 200 suites executed, 10 in process, 90 is not run?
Hello @Vitaly,
Pabot doesn’t show real-time suite progress by default, but you can enable it using the --verbose
flag. For more detailed tracking, use --pabotlib
and implement a custom listener to log suite states. Alternatively, this forum thread discusses community workarounds for tracking suite execution status dynamically. Hope that helps streamline your runs!.
Best Regards,
Amy Cross
I’m not sure if this does what you’re looking for and I probably over-engineered this a while back, but I wanted something similar so I could see what was going on in an Azure pipeline that runs for several hours. If a lot of things were failing, I could just abort, fix the problems, and run again rather than wait for the whole thing to complete with tons of failures. It is more Test-oriented than Suite-oriented, but maybe it is helpful enough for you as-is, or gives a starting point and you can hack away at it. I wrote a listener that would output the following before running anything (just as a sanity check).
- The name of each ‘Suite’ directory (single directory called Access in this example)
- The name of each Suite file within each Directory
- The name of each Test in each Suite file
Then it would output each…
- Suite Start
- Test Start
- Test End (Green for Pass, Red for Fail) with Test Duration
- Suite End with Counts of Pass and Fail
- Running Overall Test Stats with Total Duration, which shows how many Test remaining
import time
from datetime import datetime
from robot.libraries.BuiltIn import BuiltIn
class TestCaseCounterListener:
ROBOT_LISTENER_API_VERSION = 3 MAGENTA = '\\033\[95m' BLUE = '\\033\[94m' GREEN = '\\033\[92m' RED = '\\033\[91m' RESET = '\\033\[0m' def \__init_\_(self, filename='failedTests.md'): self.total_test_count = 0 self.executed_cases = 0 self.passed_cases = 0 self.failed_cases = 0 self.overall_start_time = 0 self.suite_start_time = {} self.suite_end_time = {} self.test_start_time = {} self.suite_test_counts = {} self.suite_passed_cases = {} self.suite_failed_cases = {} self.filename = filename self.fh = open(self.filename, 'w') self.fh.write("# Robot Framework Failed Test Report\\n") self.fh.write("|Test|Status|\\n") self.fh.write("|---|---|\\n") self.fh.close() def close(self): self.fh.close() def start_suite(self, data, result): \# Start timing the suite self.suite_start_time\[data.longname\] = time.time() self.suite_test_counts\[data.longname\] = len(data.tests) self.suite_passed_cases\[data.longname\] = 0 self.suite_failed_cases\[data.longname\] = 0 \# Print line with full coloring print(f"{self.\_get_colored_message(self.MAGENTA, 'Starting Suite: ' + data.name)}", flush=True) if data.parent is None: \# Overall start time for top-level suite self.overall_start_time = self.suite_start_time\[data.longname\] \# Count total test cases for all sub-suites self.total_test_count = self.\_count_test_cases(data) self.\_output_suite_structure(data) #input("\\nAbout to Begin Suite Execution. Please Confirm above tests and Press Enter to continue...") def start_test(self, data, result): \# Start timing the test self.test_start_time\[data.longname\] = time.time() \# Print line with full coloring print(f"\\n{self.\_get_colored_message(self.BLUE, 'Starting Test: ' + data.parent.name + ' - ' + data.name)}", flush=True) def end_test(self, data, result): \# End timing the test test_end_time = time.time() test_elapsed_time = test_end_time - self.test_start_time\[data.longname\] formatted_test_time = self.\_format_elapsed_time(test_elapsed_time) \# Track executed, passed, and failed cases self.executed_cases += 1 if result.passed: self.passed_cases += 1 self.suite_passed_cases\[data.parent.longname\] += 1 test_color = self.GREEN else: self.failed_cases += 1 self.suite_failed_cases\[data.parent.longname\] += 1 test_color = self.RED \# Print line with specific coloring for pass/fail print(f"{self.\_get_colored_message(test_color, 'Completed Test: ' + data.parent.name + ' - ' + data.name + ' (' + formatted_test_time + ')')}", flush=True) \# Write Failures to File in Append Mode if result.failed: self.fh = open(self.filename, 'a') self.fh.write(f"|{result.name}|{result.status}|\\n") self.fh.close() def end_suite(self, data, result): \# End timing the suite self.suite_end_time\[data.longname\] = time.time() \# Calculate suite elapsed time suite_elapsed_time = self.suite_end_time\[data.longname\] - self.suite_start_time\[data.longname\] formatted_suite_time = self.\_format_elapsed_time(suite_elapsed_time) \# Calculate total elapsed time from the start of the top-level suite total_elapsed_time = self.suite_end_time\[data.longname\] - self.overall_start_time formatted_total_time = self.\_format_elapsed_time(total_elapsed_time) remaining_cases = self.total_test_count - self.executed_cases suite_tests = self.suite_test_counts\[data.longname\] suite_passed = self.suite_passed_cases\[data.longname\] suite_failed = self.suite_failed_cases\[data.longname\] \# Conditional coloring for suite-level pass/fail counts suite_passed_color = self.GREEN if suite_passed > 0 else self.RESET suite_failed_color = self.RED if suite_failed > 0 else self.RESET \# Output summary after each suite print(f"\\n{self.\_get_colored_message(self.MAGENTA, 'Completed Suite: ' + data.name + ' (' + formatted_suite_time + ') - ' + str(suite_tests) + ' tests, ')}" f"{suite_passed_color}{suite_passed} passed{self.RESET}, {suite_failed_color}{suite_failed} failed{self.RESET}", flush=True) \# Conditional coloring for overall pass/fail counts overall_passed_color = self.GREEN if self.passed_cases > 0 else self.RESET overall_failed_color = self.RED if self.failed_cases > 0 else self.RESET \# Print overall stats with specific coloring for pass/fail print(f"{self.\_get_colored_message(self.MAGENTA, 'Overall Stats: ' + str(self.executed_cases) + ' (of ' + str(self.total_test_count) + ') tests executed after ' + formatted_total_time + ', ')}" f"{overall_passed_color}{self.passed_cases} passed{self.RESET}, {overall_failed_color}{self.failed_cases} failed{self.RESET}, {remaining_cases} remaining\\n", flush=True) def \_format_elapsed_time(self, total_seconds): """Format elapsed time as hours:mins:secs.""" hours = int(total_seconds // 3600) minutes = int((total_seconds % 3600) // 60) seconds = int(total_seconds % 60) return f"{hours:02}:{minutes:02}:{seconds:02}" def \_get_colored_message(self, color, message): """Return the message with the specified color.""" return f"{color}{message}{self.RESET}" def \_output_suite_structure(self, suite, indent=0): suite_indent = ' ' \* indent test_indent = ' ' \* (indent + 2) \# Print the suite name with the count of test cases in this suite and its subsuites suite_test_count = self.\_count_test_cases(suite) print(f"{suite_indent}- {suite.name} ({suite_test_count} test case{'s' if suite_test_count != 1 else ''})", flush=True) for test in suite.tests: print(f"{test_indent}- {test.name}", flush=True) for subsuite in suite.suites: self.\_output_suite_structure(subsuite, indent + 2) def \_count_test_cases(self, suite): """Recursively count the number of test cases in the suite and its subsuites.""" count = len(suite.tests) for subsuite in suite.suites: count += self.\_count_test_cases(subsuite) return count
Wow, thank you! I will take a look into it.
As already suggested, this can be accomplished with a listener. Enhancing Robot’s standard console output would be possible as well, but that requires someone to design how it should actually work.