60 from functools
import reduce
61 from queue
import Queue
62 from wx.lib.embeddedimage
import PyEmbeddedImage
82 from sys
import getfilesystemencoding, platform
88 OUTPUT_ENCODING = getfilesystemencoding()
89 encoding = {
'CONSOLE': CONSOLE_ENCODING,
90 'SYSTEM': SYSTEM_ENCODING,
91 'OUTPUT': OUTPUT_ENCODING}
93 ID_RUN = wx.NewIdRef()
94 ID_RUNDEBUG = wx.NewIdRef()
95 ID_STOP = wx.NewIdRef()
96 ID_PAUSE = wx.NewIdRef()
97 ID_CONTINUE = wx.NewIdRef()
98 ID_STEP_NEXT = wx.NewIdRef()
99 ID_STEP_OVER = wx.NewIdRef()
100 ID_OPEN_LOGS_DIR = wx.NewId()
101 ID_SHOW_REPORT = wx.NewIdRef()
102 ID_SHOW_LOG = wx.NewIdRef()
103 ID_AUTOSAVE = wx.NewIdRef()
104 ID_PAUSE_ON_FAILURE = wx.NewIdRef()
105 ID_SHOW_MESSAGE_LOG = wx.NewIdRef()
112 ATEXIT_LOCK = threading.RLock()
117 {
'name': name,
'get_command':
lambda self: run_prefix})
121 path = path
or os.path.curdir
122 path_dir = os.path.dirname(path)
if os.path.isfile(path)
else path
123 if os.path.exists(path_dir):
124 if platform ==
'win32':
127 os.startfile(
r"%s" % path_dir,
'explore')
128 elif platform.startswith(
'linux'):
134 subprocess.Popen([
"nautilus",
"{}".format(path_dir)])
135 except OSError
or FileNotFoundError:
138 [
"dolphin",
"{}".format(path_dir)])
139 except OSError
or FileNotFoundError:
142 [
"konqueror",
"{}".format(path_dir)])
143 except OSError
or FileNotFoundError:
144 print(
"Could not launch explorer. Tried nautilus, "
145 "dolphin and konqueror.")
148 subprocess.Popen([
"finder",
"{}".format(path_dir)])
149 except OSError
or FileNotFoundError:
150 subprocess.Popen([
"open",
"{}".format(path_dir)])
155 defaults = {
"auto_save":
False,
157 "profile_name":
"robot",
158 "show_console_log":
True,
159 "show_message_log":
True,
160 "sash_position": 200,
162 [(
'jybot',
'jybot' + (
'.bat' if os.name ==
'nt' else '')),
163 (
'pybot',
'pybot' + (
'.bat' if os.name ==
'nt' else '')),
164 (
'robot 3.1',
'robot')],
166 "font face":
'Courier New',
167 "foreground":
'black',
168 "background":
'white',
171 "fail color":
'#FF8E8E',
172 "pass color":
'#9FCC9F',
173 "skip color":
'yellow'
176 report_regex = re.compile(
"^Report: {2}(.*\.html)$", re.MULTILINE)
177 log_regex = re.compile(
"^Log: {5}(.*\.html)$", re.MULTILINE)
181 Plugin.__init__(self, application, initially_enabled=
True,
182 default_settings=self.
defaultsdefaults)
186 "https://github.com/robotframework/RIDE/wiki/Test-Runner-Plugin"}
209 _names_to_run = property
213 map(
lambda ctrl: (ctrl.datafile_controller.longname, ctrl.longname),
218 self.register_shortcut(
'CtrlCmd-L', self.
OnShowLogOnShowLog)
219 self.register_shortcut(
'CtrlCmd-R', self.
OnShowReportOnShowReport)
220 if IS_WINDOWS
or IS_MAC:
224 if self.notebook.current_page_title != self.
titletitle:
229 if self.notebook.current_page_title != self.
titletitle:
238 self.tree.set_checkboxes_for_tests()
249 run_action_info = ActionInfo(
"Tools",
"Run Tests", self.
OnRunOnRun,
None,
250 "F8", ImageProvider().TOOLBAR_PLAY,
251 "Run the selected tests", position=10)
252 self.
_run_action_run_action = self.register_action(run_action_info)
253 run_action_debug = ActionInfo(
"Tools",
"Run Tests with Debug",
256 "Run the selected tests with Debug",
258 self.
_run_action_run_action = self.register_action(run_action_debug)
259 stop_action_info = ActionInfo(
"Tools",
"Stop Test Run", self.
OnStopOnStop,
261 ImageProvider().TOOLBAR_STOP,
262 "Stop a running test", position=11)
272 for name, run_prefix
in
277 self.
_test_runner_test_runner.add_profile(profile.name, profile(plugin=self))
281 for sub_class
in class_.__subclasses__():
287 RideTestSelectedForRunningChanged)
292 section, setting = message.keys
294 if section ==
'Test Run':
297 self.
defaultsdefaults.setdefault(setting, message.new)
298 self.save_setting(setting, message.new)
306 self.unsubscribe_all()
307 self.unregister_actions()
381 if self.__getattr__(
'confirm run') \
388 self.
use_colorsuse_colors = self.__getattr__(
'use colors')
394 command = self.
_create_command_create_command(profile.get_command(), args_file)
404 except Exception
as e:
406 error, log_message = self.
get_current_profileget_current_profile().format_error(str(e),
None)
409 log_message.publish()
412 return CommandArgs().with_existing_args(profile_command_args) \
413 .with_log_level(log_level) \
415 .with_python_path(self.global_settings.get(
'pythonpath',
None)) \
417 .without_console_color(
not use_colors) \
423 FileWriter.write(arg_file, args,
'wb')
427 return Command().with_prefix(profile_command) \
428 .with_args_file(args_file) \
429 .with_listener(self.
_test_runner_test_runner.get_listener_port(),
431 .with_tests_suite_file(self.model.suite.source) \
439 ArgsParser.get_message_log_level(args)
445 SettingsParser.get_console_log_name(profile_settings)
447 else os.path.join(self.
_logs_directory_logs_directory, console_log_name)
450 if profile.name == runprofiles.CustomScriptProfile.name:
451 return profile.get_cwd()
452 if os.path.isdir(self.model.suite.source):
453 return self.model.suite.source
454 return os.path.dirname(self.model.suite.source)
457 if self.
_running_running
or self.model.suite
is None:
459 if not self.is_unsaved_changes():
462 self.save_all_unsaved_changes()
468 ret = wx.MessageBox(
"""There are unsaved modifications.
469 Do you want to save all changes and run the tests?""",
470 "Unsaved Modifications",
471 wx.ICON_QUESTION | wx.YES_NO)
479 ret = wx.MessageBox(
'No tests selected. \n'
482 wx.ICON_QUESTION | wx.YES_NO)
488 self.
_local_toolbar_local_toolbar.EnableTool(ID_OPEN_LOGS_DIR,
False)
489 self.
_local_toolbar_local_toolbar.EnableTool(ID_SHOW_REPORT,
False)
500 text_ctrl.SetReadOnly(
False)
502 text_ctrl.SetReadOnly(
True)
514 wx.LaunchDefaultBrowser(
515 "file:%s" % os.path.abspath(self.
_report_file_report_file))
520 wx.LaunchDefaultBrowser(
"file:%s" % os.path.abspath(self.
_log_file_log_file))
523 output, errors, log_message = self.
_test_runner_test_runner.get_output_and_errors(
533 now = datetime.datetime.now().timetuple()
535 .format(robottime.format_time(now)))
538 log_message.publish()
539 self.
_local_toolbar_local_toolbar.EnableTool(ID_OPEN_LOGS_DIR,
True)
547 self.
_local_toolbar_local_toolbar.EnableTool(ID_SHOW_REPORT,
True)
555 res = regex.search(output)
556 return res.group(1)
if res
and os.path.isfile(res.group(1))
else None
568 self.
_maxmemmsg_maxmemmsg =
'\n' +
"Messages log exceeded 80% of " \
569 "process memory, stopping for now..."
574 out_buffer, err_buffer, log_message = \
576 if len(out_buffer) > 0:
578 if len(err_buffer) > 0:
601 if not self.
panelpanel:
604 self.show_tab(self.
panelpanel)
615 FileWriter.write(self.
_console_log_console_log, [text],
"ab",
"a")
619 if not self.
panelpanel
or not text_ctrl:
624 text_ctrl.update_scroll_width(text)
626 new_text_start = text_ctrl.GetLength()
627 line_count = text_ctrl.GetLineCount()
628 last_visible_line = \
629 text_ctrl.GetFirstVisibleLine() + text_ctrl.LinesOnScreen() - 1
631 text_ctrl.SetReadOnly(
False)
632 pos=text_ctrl.GetLastPosition()
634 text_ctrl.AppendText(text)
635 new_text_end = text_ctrl.GetLength()
637 if wx.VERSION < (4, 1, 0):
638 text_ctrl.StartStyling(new_text_start, 0x1f)
640 text_ctrl.StartStyling(new_text_start)
641 text_ctrl.SetStyling(0, STYLE_DEFAULT)
642 if source ==
"stderr" and not self.
use_colorsuse_colors:
643 text_ctrl.SetStyling(new_text_end - new_text_start, STYLE_STDERR)
647 previous_start =
None
649 previous_style = style
652 elif item[1] ==
'GREEN':
654 elif item[1] ==
'YELLOW':
656 elif item[1]
is None:
657 style = STYLE_DEFAULT
659 if wx.VERSION < (4, 1, 0):
660 text_ctrl.StartStyling(pos + item[0], 0x1f)
662 text_ctrl.StartStyling(pos + item[0])
663 previous_start = item[0]
664 if previous_style
and style == STYLE_DEFAULT:
665 text_ctrl.SetStyling(item[0] - previous_start, previous_style)
666 if previous_start
and style:
667 text_ctrl.SetStyling(item[0] - previous_start, STYLE_DEFAULT)
669 text_ctrl.SetReadOnly(
True)
670 if last_visible_line >= line_count - 4:
671 line_count = text_ctrl.GetLineCount()
672 text_ctrl.ScrollToLine(line_count)
683 if txt[idx + 1:idx+5] == b
'[34m':
687 if txt[idx + 1:idx+5] == b
'[33m':
691 if txt[idx+1:idx+5] == b
'[32m':
695 if txt[idx+1:idx+5] == b
'[31m':
699 if txt[idx+1:idx+4] == b
'[0m':
702 txt = txt[:idx] + txt[idx+4:]
705 txt = txt[:idx] + txt[idx+5:]
717 self.
_color_map_color_map.append((idx, color))
724 char_width = self.__getattr__(
"font size")
725 return str(
int(out_width / char_width) - 10)
732 self.notebook.allow_closing(self.
panelpanel)
733 self.notebook.delete_tab(self.
panelpanel)
736 toolbar = wx.ToolBar(parent, wx.ID_ANY,
737 style=wx.TB_HORIZONTAL | wx.TB_HORZ_TEXT | wx.TB_NODIVIDER)
738 toolbar.SetBackgroundColour(self.
_mysettings_mysettings.color_background)
739 toolbar.SetForegroundColour(self.
_mysettings_mysettings.color_foreground)
740 toolbar.AddTool(ID_RUN,
"Start", ImageProvider().TOOLBAR_PLAY,
741 wx.NullBitmap, wx.ITEM_NORMAL, shortHelp=
"Start robot",
742 longHelp=
"Start running the robot test suite")
744 wx.ITEM_NORMAL, shortHelp=
"Start robot",
745 longHelp=
"Start running the robot test suite "
746 "with DEBUG loglevel")
747 toolbar.AddTool(ID_STOP,
"Stop", ImageProvider().TOOLBAR_STOP,
748 wx.NullBitmap, wx.ITEM_NORMAL,
749 shortHelp=
"Stop a running test",
750 longHelp=
"Stop a running test")
751 toolbar.AddTool(ID_PAUSE,
"Pause", ImageProvider().TOOLBAR_PAUSE,
752 wx.NullBitmap, wx.ITEM_NORMAL,
753 shortHelp=
"Pause test execution",
754 longHelp=
"Pause test execution")
755 toolbar.AddTool(ID_CONTINUE,
"Continue",
756 ImageProvider().TOOLBAR_CONTINUE,
757 wx.NullBitmap, wx.ITEM_NORMAL,
758 shortHelp=
"Continue test execution",
759 longHelp=
"Continue test execution")
760 toolbar.AddTool(ID_STEP_NEXT,
"Next", ImageProvider().TOOLBAR_NEXT,
761 wx.NullBitmap, wx.ITEM_NORMAL, shortHelp=
"Step next",
762 longHelp=
"Step next")
763 toolbar.AddTool(ID_STEP_OVER,
"Step over", ImageProvider().TOOLBAR_NEXT,
764 wx.NullBitmap, wx.ITEM_NORMAL, shortHelp=
"Step over",
765 longHelp=
"Step over")
771 for event, callback, id
in (
772 (wx.EVT_TOOL, self.
OnRunOnRun, ID_RUN),
773 (wx.EVT_TOOL, self.
OnRunDebugOnRunDebug, ID_RUNDEBUG),
774 (wx.EVT_TOOL, self.
OnStopOnStop, ID_STOP),
775 (wx.EVT_TOOL, self.
OnPauseOnPause, ID_PAUSE),
776 (wx.EVT_TOOL, self.
OnContinueOnContinue, ID_CONTINUE),
777 (wx.EVT_TOOL, self.
OnStepNextOnStepNext, ID_STEP_NEXT),
778 (wx.EVT_TOOL, self.
OnStepOverOnStepOver, ID_STEP_OVER)):
779 toolbar.Bind(event, callback, id=id)
782 toolbar = wx.ToolBar(parent, wx.ID_ANY,
783 style=wx.TB_HORIZONTAL | wx.TB_HORZ_TEXT | wx.TB_NODIVIDER | wx.TB_DOCKABLE)
785 toolbar.SetOwnBackgroundColour(self.
_mysettings_mysettings.color_background)
786 toolbar.SetOwnForegroundColour(self.
_mysettings_mysettings.color_foreground)
787 profile_label = Label(toolbar, label=
"Execution Profile: ")
788 choices = self.
_test_runner_test_runner.get_profile_names()
789 self.
choicechoice = wx.Choice(toolbar, wx.ID_ANY, choices=choices)
790 self.
choicechoice.SetToolTip(wx.ToolTip(
"Choose which method to use for "
791 "running the tests"))
792 toolbar.AddControl(profile_label)
793 toolbar.AddControl(self.
choicechoice)
794 toolbar.AddSeparator()
797 toolbar.AddTool(ID_OPEN_LOGS_DIR,
"Open Logs Directory",
798 ImageProvider().DATADIRIMG,
799 shortHelp=
"View All Logs in Explorer")
800 toolbar.AddTool(ID_SHOW_REPORT,
" Report", report_image,
802 "Browser (CtrlCmd-R)"))
803 toolbar.AddTool(ID_SHOW_LOG,
" Log", log_image,
805 " Browser (CtrlCmd-L)"))
806 toolbar.AddSeparator()
812 self.auto_save,
"Automatically save all "
813 "changes before running")
818 " Pause after failure ",
False,
819 "Automatically pause after failing keyword")
822 toolbar.EnableTool(ID_OPEN_LOGS_DIR,
False)
823 toolbar.EnableTool(ID_SHOW_LOG,
False)
824 toolbar.EnableTool(ID_SHOW_REPORT,
False)
825 for i
in toolbar.GetChildren():
826 i.SetBackgroundColour(self.
_mysettings_mysettings.color_background)
827 i.SetForegroundColour(self.
_mysettings_mysettings.color_foreground)
834 for event, callback, id
in (
836 (wx.EVT_TOOL, self.
OnShowReportOnShowReport, ID_SHOW_REPORT),
837 (wx.EVT_TOOL, self.
OnShowLogOnShowLog, ID_SHOW_LOG)):
838 toolbar.Bind(event, callback, id=id)
840 for event, handler, source
in (
846 toolbar.Bind(event, handler, source)
852 self.save_setting(
"auto_save", evt.IsChecked())
856 self.
_test_runner_test_runner.send_pause_on_failure(evt.IsChecked())
859 self.save_setting(
"profile_name", event.GetString())
866 items = self.
choicechoice.GetItems()
867 if profile_name
not in items:
869 choice_index = items.index(profile_name)
870 self.
choicechoice.Select(choice_index)
877 profile = self.
_test_runner_test_runner.get_profile(profile_name)
882 sizer.ShowItems(
False)
885 sizer.ShowItems(
True)
889 return self.
_test_runner_test_runner.get_profile(self.
choicechoice.GetStringSelection())
892 self.
panelpanel = wx.Panel(self.notebook)
894 self.
panelpanel.SetBackgroundColour(self.
_mysettings_mysettings.color_background)
895 self.
panelpanel.SetForegroundColour(self.
_mysettings_mysettings.color_foreground)
900 sizer = wx.BoxSizer(wx.VERTICAL)
901 sizer.Add(self.
_local_toolbar_local_toolbar, 0, wx.EXPAND | wx.LEFT | wx.TOP | wx.RIGHT, 5)
902 sizer.Add(wx.StaticLine(self.
panelpanel), 0, wx.EXPAND | wx.BOTTOM | wx.TOP, 7)
903 sizer.Add(self.
_runner_toolbar_runner_toolbar, 0, wx.EXPAND | wx.ALL, 5)
904 sizer.Add(wx.StaticLine(self.
panelpanel), 0, wx.EXPAND | wx.BOTTOM | wx.TOP, 4)
906 sizer.Add(wx.StaticLine(self.
panelpanel), 0, wx.EXPAND | wx.BOTTOM | wx.TOP, 4)
908 sizer.Add(self.
_output_panel_output_panel, 1, wx.EXPAND | wx.TOP, 5)
909 self.
panelpanel.SetSizer(sizer)
913 self.
panelpanel.Bind(wx.EVT_WINDOW_DESTROY, self.
OnCloseOnClose)
915 self.add_tab(self.
panelpanel, self.
titletitle, allow_closing=
False)
921 panel = wx.Panel(parent, wx.ID_ANY,
922 style=wx.BORDER_NONE | wx.TAB_TRAVERSAL)
923 panel.SetBackgroundColour(self.
_mysettings_mysettings.color_background)
924 panel.SetForegroundColour(self.
_mysettings_mysettings.color_foreground)
925 vertical_sizer = wx.BoxSizer(wx.VERTICAL)
926 panel.SetSizer(vertical_sizer)
930 panel = wx.Panel(parent)
931 panel.SetBackgroundColour(self.
_mysettings_mysettings.color_background)
932 panel.SetForegroundColour(self.
_mysettings_mysettings.color_foreground)
936 self.show_console_log,
940 self.show_message_log,
943 panel_sizer = wx.BoxSizer(wx.VERTICAL)
944 panel_sizer.Add(self.
_progress_bar_progress_bar, 0, wx.EXPAND | wx.BOTTOM, 10)
945 panel_sizer.Add(self._console_log_panel,
int(self.show_console_log), wx.EXPAND)
946 panel_sizer.Add(self._message_log_panel,
int(self.show_message_log), wx.EXPAND)
947 panel.SetSizer(panel_sizer)
951 self.save_setting(
"show_console_log",
not evt.Collapsed)
953 self._console_log_panel,
954 int(
not evt.Collapsed))
958 self.save_setting(
"show_message_log",
not evt.Collapsed)
960 self._message_log_panel,
961 int(
not evt.Collapsed))
966 sizer = panel.GetSizer()
967 children = sizer.GetChildren()
968 for itemIndex
in range(len(children)):
969 if item == children[itemIndex].Window:
971 sizer.Insert(itemIndex, item, proportion, wx.EXPAND)
975 pane_changed_handler):
976 collapsible_pane = wx.CollapsiblePane(
977 parent, wx.ID_ANY, title,
978 style=wx.CP_DEFAULT_STYLE | wx.CP_NO_TLW_RESIZE)
979 collapsible_pane.SetBackgroundColour(self.
_mysettings_mysettings.color_background)
980 collapsible_pane.SetForegroundColour(self.
_mysettings_mysettings.color_foreground)
982 collapsible_pane.Expand()
983 collapsible_pane.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED,
984 pane_changed_handler,
987 pane = collapsible_pane.GetPane()
988 pane.SetBackgroundColour(self.
_mysettings_mysettings.color_background)
989 pane.SetForegroundColour(self.
_mysettings_mysettings.color_foreground)
991 text_ctrl.SetBackgroundColour(self.
_mysettings_mysettings.color_background)
992 text_ctrl.SetForegroundColour(self.
_mysettings_mysettings.color_foreground)
993 vertical_sizer = wx.BoxSizer(wx.VERTICAL)
994 vertical_sizer.Add(text_ctrl, 1, wx.EXPAND)
995 pane.SetSizer(vertical_sizer)
996 return collapsible_pane, text_ctrl
1000 text_ctrl.SetScrollWidth(100)
1002 text_ctrl.SetReadOnly(
True)
1007 cb = wx.CheckBox(parent, id, label)
1008 cb.SetToolTip(wx.ToolTip(tooltip))
1014 out.SetMarginLeft(10)
1015 out.SetMarginWidth(0, 0)
1016 out.SetMarginWidth(1, 0)
1017 out.SetMarginWidth(2, 0)
1018 out.SetMarginWidth(3, 0)
1029 if not self.
panelpanel:
1034 if event ==
'start_test':
1037 if event ==
'end_test':
1040 if event ==
'report_file':
1043 if event ==
'log_file':
1046 if event ==
'start_keyword':
1049 if event ==
'end_keyword':
1052 if event ==
'log_message':
1055 if event ==
'paused':
1058 if event ==
'continue':
1062 longname = args[1][
'longname'].encode(
'utf-8')
1064 f
"Starting test: {longname.decode(encoding['OUTPUT'], 'backslashreplace')}")
1067 longname = args[1][
'longname'].encode(
'utf-8')
1069 f
"Ending test: {longname.decode(encoding['OUTPUT'], 'backslashreplace')}\n")
1070 if args[1][
'status'] ==
'PASS':
1072 elif args[1][
'status'] ==
'SKIP':
1074 elif args[1][
'status'] ==
'FAIL':
1077 self.
_log_message_queue_log_message_queue.put(f
"UNKNOWN STATUS: {args[1]['status']}\n")
1081 wx.CallAfter(self.
_local_toolbar_local_toolbar.EnableTool, ID_SHOW_REPORT,
True)
1085 wx.CallAfter(self.
_local_toolbar_local_toolbar.EnableTool, ID_SHOW_LOG,
True)
1088 self.
_progress_bar_progress_bar.set_current_keyword(args[0])
1096 prefix =
'%s : %s : ' % (a[
'timestamp'], a[
'level'].rjust(5))
1097 message = a[
'message']
1099 message =
'\n' + message
1137 debug = stop
and not paused
1138 for id, enabled
in ((ID_RUN, run),
1142 (ID_CONTINUE, debug),
1143 (ID_STEP_NEXT, debug),
1144 (ID_STEP_OVER, debug)):
1149 wx.MessageBox(
"There isn't logs directory. \n"
1150 "Please, run the tests and try again",
1151 "No logs directory",
1152 wx.ICON_INFORMATION | wx.OK)
1158 def __init__(self, parent, fail_color='#FF8E8E', pass_color="#9FCC9F", skip_color='yellow'):
1159 wx.Panel.__init__(self, parent, wx.ID_ANY)
1160 self.
_sizer_sizer = wx.BoxSizer(wx.HORIZONTAL)
1161 self.
_gauge_gauge = wx.Gauge(self, size=(100, 10))
1163 self.
_sizer_sizer.Add(self.
_label_label, 1, wx.EXPAND | wx.LEFT, 10)
1164 self.
_sizer_sizer.Add(self.
_gauge_gauge, 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, 10)
1165 self.
_sizer_sizer.Layout()
1166 self.SetSizer(self.
_sizer_sizer)
1174 self.Bind(wx.EVT_TIMER, self.
OnTimerOnTimer)
1193 self.
_gauge_gauge.Pulse()
1201 self.
_sizer_sizer.Layout()
1213 self.
_pass_pass += 1
1217 self.
_fail_fail += 1
1221 self.
_skip_skip += 1
1224 color_diff = wx.Colour.GetRGBA(wx.Colour(color)) - wx.Colour.GetRGBA(self.
_foreground_colour_foreground_colour)
1228 if wx.Colour.GetRGBA(wx.Colour(color)) > wx.Colour.GetRGBA(self.
_foreground_colour_foreground_colour) > wx.Colour.GetRGBA(wx.Colour(
'gray')):
1229 if color_diff > wx.Colour.GetRGBA(wx.Colour(
'gray')):
1231 return wx.Colour(
'black')
1238 elapsed = time.time() - self.
_start_time_start_time
1239 message =
"elapsed time: %s pass: %s skip: %s fail: %s" % (
1242 self.
_label_label.SetLabel(message)
1243 if self.
_fail_fail > 0:
1245 self.SetBackgroundColour(self.
fail_colorfail_color)
1246 elif self.
_skip_skip > 0:
1248 self.SetBackgroundColour(self.
skip_colorskip_color)
1249 elif self.
_pass_pass > 0:
1251 self.SetBackgroundColour(self.
pass_colorpass_color)
1259 return ' current keyword: ' + \
1264 if len(text) <= max_length:
1266 return '...' + text[3 - max_length:]
1274 return "%d:%02d:%02d" % \
1275 reduce(
lambda ll, b: divmod(ll[0], b) + ll[1:], [(t,), 60, 60])
1281 wx.stc.StyledTextCtrl.__init__(self, parent, wx.ID_ANY,
1282 style=wx.SUNKEN_BORDER)
1288 if isinstance(string, bytes):
1292 string_max_len = max(len(s)
for s
in string.split(linesep))
1297 width, _ = self.GetTextExtent(string)
1298 if self.GetScrollWidth() < width + 50:
1299 self.SetScrollWidth(width + 50)
1300 except UnicodeDecodeError:
1307 raise ValueError(
'Value does not contain NoteBook as parent')
1308 if isinstance(parent, NoteBook):
1309 return parent._app.settings
1310 parent = parent.GetParent()
1316 self.
settingssettings = settings._config_obj[
'Plugins'][
'Test Runner']
1319 PUBLISHER.subscribe(self.
OnSettingsChangedOnSettingsChanged, RideSettingsChanged)
1323 section, setting = message.keys
1324 if section ==
'Test Runner':
1331 background = self.
settingssettings.get(
'background',
'white')
1332 font_size = self.
settingssettings.get(
'font size', 10)
1333 font_face = self.
settingssettings.get(
'font face',
'Courier New')
1339 fore=self.
settingssettings.get(
'foreground',
'black'), back=background,
1340 size=font_size, face=font_face)
1342 fore=self.
settingssettings.get(
'error',
'red'), back=background,
1343 size=font_size, face=font_face)
1344 fail_style = self.
_get_style_string_get_style_string(fore=self.
fail_colorfail_color, back=background, size=font_size, face=font_face)
1345 pass_style = self.
_get_style_string_get_style_string(fore=self.
pass_colorpass_color, back=background, size=font_size, face=font_face)
1346 skip_style = self.
_get_style_string_get_style_string(fore=self.
skip_colorskip_color, back=background, size=font_size, face=font_face)
1348 self.
editoreditor.StyleSetSpec(STYLE_DEFAULT, default_style)
1349 self.
editoreditor.StyleSetSpec(STYLE_STDERR, error_style)
1350 self.
editoreditor.StyleSetSpec(STYLE_FAIL, fail_style)
1351 self.
editoreditor.StyleSetSpec(STYLE_PASS, pass_style)
1352 self.
editoreditor.StyleSetSpec(STYLE_SKIP, skip_style)
1353 self.
editoreditor.StyleSetSpec(7, error_style)
1354 self.
editoreditor.StyleSetBackground(wx.stc.STC_STYLE_DEFAULT, background)
1355 self.
editoreditor.Refresh()
1359 return ','.join(
'%s:%s' % (name, value)
1360 for name, value
in locals().items()
if value)
1366 default_font = self.
settingssettings.get(
'font face')
1368 sys_font = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT)
1369 self.
settingssettings[
'font face'] = sys_font.GetFaceName()
1372 Robot = PyEmbeddedImage(
1373 "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAnNJ"
1374 "REFUOI2Vkb1Pk3EQxz/PW6EvUN6sEQFBIwUlMBgTMZFZJzcXEzeJiXE1MXFi4g8gGhjcHDA4"
1375 "iFGDKNFojBoJaqQItgrlpYUW0ZZSaJ/ndw5INQZIvMttd5/73vcQEbYrpRSPes5K7NsrUaK2"
1376 "7RERdHaJnLeV4tL9u7XsDNA0qKhrw19erf0nQABBRBEeGyT86YUgIKjtF4nIP+PC0tsRGb11"
1377 "g+hcnAqvl6ZjrQQ7r664ygIV/8opAATIpr53fui53psZfoqsZcn5TEyXjlrPQcNBvMdO0XG5"
1378 "S4M/GPNvWnQ23Ptg4hW1xxsxLAssE0MHHIWgM/f+Me35a1iWmy1IASCOw+f+XhwMQuML/Eik"
1379 "WVA6mlLU6A7+AwEqKxSjN7vlxJUubUtEwcTJ8XF5PfAA23ZIJTMkppdoathLS7CO5EyS1M8M"
1380 "GjpDdwcR/vhWUHAo2KjtaWmWeWeJtlNH0DqamPwSxTQtTl88g21nWUlG6bhwficThWQsKpfO"
1381 "tWMkBFGQXc9j6RYuw8F0WXgOe+i7F9LQTLZu0Au/V8Lzh32UFBfjK3dRWlVEoMaDf59JSbUH"
1382 "d5ULv7uI+7e7RZT9+2+gC5sZ/Tom4U/P8PgMViVHWjZYNxxsl7Bh2uDTCFT7+Dw2ROjdw9/C"
1383 "BfN7fEp+LLxkMrxIKp0mGDxAc8s6dXvrQRc0TUfTYSocxs7rxBOrfHxzh3J/Tvz7TmImYhMs"
1384 "Rl4zG1lDicOT4RBHWyr5GBrH0DcvdGxFWUme+Zk0tY2lzM3NshyfxHDXo0fCEQb6R4hMx3Bs"
1385 "hTiCKMFtpsmoLHl7Ga8fRATHEcRRrCxnGBocIR6L8Qu2hlAKJu0L3QAAAABJRU5ErkJggg==")
1386 getRobotBitmap = Robot.GetBitmap
1388 MenuButton = PyEmbeddedImage(
1389 "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAKxJ"
1390 "REFUOI3t0jEKg0AUBNAxhmXX9QD2adLnJt7E2luIeB/PkCoQCG5lK8ifdZtNHyQRLGwy5Yd5"
1391 "/GKSGCP25LSr/QcAAOfPQ9/3MYSAZVngvQdJiAhEhFVVZT8BkpKmaZbnOZRS0FojhIBpmh6b"
1392 "Ppjn+ULyqZSyxhiM44hhGEiyXAOStSG1bVuIyMtaq51zJHltmsZtBgCgruuC5N17f+u6brX8"
1393 "Fdia43dwPPAGncZYbvceeuMAAAAASUVORK5CYII=")
1394 getMenuButtonBitmap = MenuButton.GetBitmap
1396 ProcessStop = PyEmbeddedImage(
1397 "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0"
1398 "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJJSURBVDjLpZNNbxJRFIb7A/wF"
1399 "/A5YunRDovsmRk3cmLAxcdG0uiFuXDSmkBlLFNOmtYFKgibUtqlJG6UjiGksU0oZPgQs0KEw"
1400 "Mw4Dw8dQjnPuMCNq48abvJub87zn4547BQBTk7q2CDZdDl1OXdNjOcd3tj/jJ8Eruuxzb2RX"
1401 "+NMpHT/MMUfHJwKbSgv7Bxnm9YciPRMSXRiDsb8ZjOGrwWjNzZ4UOL4pg6IOQLsYEbU6fajW"
1402 "RYgdpLilnYIbY00T08COcCrzTen2NMCj9ocgKgMQdLV7Q3KnqH3YTyQV/1YWTezEAPvCsjGz"
1403 "CTfkPtR/9IGXDNWkHlTFnmWysxfj7q/x2I4NDRxh5juNZf8LPm12ifBkimdAheI0smjgjH3N"
1404 "MtgzlmqCNx5tGnq4Abe9LIHLjS7IHQ3OJRWW1zcYZNFgOnl0LOCwmq0BgTEjgqbQoHSuQrGu"
1405 "EqO+dgFrgXUBWWJwyKaIAZaPcEXoWvD1uQjc8rBQ4FUio4oBLK+8sgycH7+kGUnpQUvVrF4x"
1406 "K4KomwuGQf6sQ14mV5GA8gesFhyB3TxdrjZhNAKSwSzXzIpgrtaBbLUDg+EI9j6nwe3btIZo"
1407 "exBsuHajCU6QjSlfBmaqbZIgr2f3Pl/l7vpyxjOai0S9Zd2R91GFF41Aqa1Z1eAyYeZcRQSP"
1408 "P6jMUlu/FmlylecDCfdqKMLFk3ko8zKZCfacLgmwHWVhnlriZrzv/l7lyc9072XJ9fjFNv10"
1409 "cYWhnvmEBS8tPPH4mVlPmL5DZy7/TP/znX8C6zgR9sd1gukAAAAASUVORK5CYII=")
1410 getProcessStopBitmap = ProcessStop.GetBitmap
1413 ReportIcon = PyEmbeddedImage(
1414 "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0"
1415 "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAC4SURBVCjPdZFbDsIgEEWnrsMm"
1416 "7oGGfZrohxvU+Iq1TyjU60Bf1pac4Yc5YS4ZAtGWBMk/drQBOVwJlZrWYkLhsB8UV9K0BUrP"
1417 "Gy9cWbng2CtEEUmLGppPjRwpbixUKHBiZRS0p+ZGhvs4irNEvWD8heHpbsyDXznPhYFOyTjJ"
1418 "c13olIqzZCHBouE0FRMUjA+s1gTjaRgVFpqRwC8mfoXPPEVPS7LbRaJL2y7bOifRCTEli3U7"
1419 "BMWgLzKlW/CuebZPAAAAAElFTkSuQmCC")
1420 getReportIconBitmap = ReportIcon.GetBitmap
1423 LogIcon = PyEmbeddedImage(
1424 "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAABGdBTUEAAK/INwWK6QAAABl0"
1425 "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADoSURBVBgZBcExblNBGAbA2cee"
1426 "gTRBuIKOgiihSZNTcC5LUHAihNJR0kGKCDcYJY6D3/77MdOinTvzAgCw8ysThIvn/VojIyMj"
1427 "IyPP+bS1sUQIV2s95pBDDvmbP/mdkft83tpYguZq5Jh/OeaYh+yzy8hTHvNlaxNNczm+la9O"
1428 "Tlar1UdA/+C2A4trRCnD3jS8BB1obq2Gk6GU6QbQAS4BUaYSQAf4bhhKKTFdAzrAOwAxEUAH"
1429 "+KEM01SY3gM6wBsEAQB0gJ+maZoC3gI6iPYaAIBJsiRmHU0AALOeFC3aK2cWAACUXe7+AwO0"
1430 "lc9eTHYTAAAAAElFTkSuQmCC")
1431 getLogIconBitmap = LogIcon.GetBitmap
1434 BugIcon = PyEmbeddedImage(
1435 "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0"
1436 "RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKYSURBVDjLnZPJT1NRFMb5G1wD"
1437 "HV5boNiqdHrvFYolCAtsGSSWKpMFKhYqlDI6oAEKaVJwCIgSphaKtLYWCgSNBgRjMNHoxsSF"
1438 "S3cmJmA0NMTw+R6JKKZl4eJL7sm953fOd3JPHIC4WMpcppG5SGnZc8ZjVVF6QLn975sDgfaZ"
1439 "mvg71oRJZIRUYcuAnq/2KWroGfm3QwEn2YpLVPPvOD2oiqj9yq/mGznegl56mx6T7ZbY1M6Y"
1440 "AM0CuZkxT0b2Wg6QW/SsApRXDsotR+d6E9Y/h9DuqoCuJq0lKoDxqU1/pITGR27mBU4h+GEc"
1441 "Tz5OY+ClA5JbyahYzof/9TBO9B/FcWcqpA4xU3We3GJ87ntnfO5meinMvruNnqcmXA2XoDVc"
1442 "Cc0wCYkzBaZpA7ILRJ/2O2B87jA+QT9UeDRe8svZYAG8b/txc6kc9mA+yqayYPQXwvdmBEOr"
1443 "A5B2p0BtFIYOWKCm5RukWwZyXIbA+0F0LpaiKaBHmVsLw4we99ccsM8a8GClF5JOMcQdou8p"
1444 "rULrgRmQo7KI0VcE13MrGv06lE5kodhzGvdWu2GdKkTVWC4DcELcJkKyXbCb1EhAVM//M0DV"
1445 "UNqP2qAJd1baUDaZjTMTeXAttsPi0cM0mgvHvA0NkxYk2QRIrieOsDmEmXttH0DfVfSluSTo"
1446 "WmpD8bgOroUOWNw6VI7koGfOBuq6EqLLTNU6ojrmP5D1HVsjmrkYezGIrlA9LjKgnrlGXJlp"
1447 "gbCOD0EtD0QNN8I3cZqjAlhJr4rXpB1iNLhrYffUQWoT7yUKzbxqJlHLq0jc5JYmgHMunogK"
1448 "YJVqF7mTrPyfgktMRTMX/CrOq1gLF3fYNrLiX+Bs8MoTwT2fQPwXgBXHGL+TaIjfinb3C7cs"
1449 "cRMIcYL6AAAAAElFTkSuQmCC")
1450 getBugIconBitmap = BugIcon.GetBitmap
Base class for all test runner profiles.
A runner profile which uses robot.
def update_scroll_width(self, string)
def _get_app_settings(parent)
def __init__(self, parent)
def _set_styles(self)
Sets plugin styles.
def _get_style_string(back, fore, size, face)
def _ensure_default_font_is_valid(self)
Checks if default font is installed.
def OnSettingsChanged(self, message)
Redraw colors and font if settings are modified.
def __init__(self, editor, settings)
A progress bar for the test runner plugin.
def empty_current_keyword(self)
def Start(self)
Signals the start of a test run; initialize progressbar.
def get_visible_color(self, color)
def add_pass(self)
Add one to the passed count.
def Stop(self)
Signals the end of a test run.
def OnTimer(self, event)
A handler for timer events; it updates the statusba.
def set_current_keyword(self, name)
def _get_current_keyword_text(self)
def _fix_size(text, max_length)
def add_fail(self)
Add one to the failed count.
def _seconds_to_string(t)
Convert a number of seconds to a string of the form HH:MM:SS.
def __init__(self, parent, fail_color='#FF8E8E', pass_color="#9FCC9F", skip_color='yellow')
def _update_message(self)
Update the displayed elapsed time, passed and failed counts.
def add_skip(self)
Add one to the skipped count.
def _initialize_state(self)
A plugin for running tests from within RIDE.
def _subscribe_to_events(self)
def _clear_log_ctrls(self)
def get_current_profile(self)
def _tests_selected(self)
def _on_autosave_cb(self, evt)
Called when the user clicks on the "Auto Save" checkbox.
def _show_notebook_tab(self)
Show the Run notebook ta.
def _read_run_profiles_from_config(self)
def OnTimer(self, evt)
Get process output.
def OnSettingsChanged(self, message)
Updates settings.
def _can_start_running_tests(self)
def __init__(self, application=None)
def _remove_from_notebook(self)
Remove the tab for this plugin from the notebook.
def OnShowLog(self, evt)
Called when the user clicks on the "Log" button.
_currently_executing_keyword
def _initialize_ui_for_running(self)
def _handle_paused(self, args)
def OnStepNext(self, event)
def _enable_runner_toolbar(self, run, paused)
def _read_run_profiles_from_classes(self)
_profile_classes_from_config
def OnTestSelectedForRunningChanged(self, message)
def OnClose(self, event)
Shut down the running services and processes.
def _clear_text_ctrl(text_ctrl)
def _get_report_or_log(output, regex)
def _read_run_profiles(self)
def _build_local_toolbar(self, parent)
def _handle_log_message(self, args)
def _create_temporary_directory(self)
def _get_last_output_char(self)
Return the last character in the output window.
def OnRunDebug(self, event)
Called when the user clicks or presses the F9, Run Tests with Debug It can still be overwritten in RI...
def OnProcessEnded(self, evt)
def _get_current_working_dir(self, profile)
def _ask_user_to_run_anyway()
def OnContinue(self, event)
def _ask_user_to_save_before_running()
def _create_collapsible_pane(self, parent, title, expand, pane_changed_handler)
def _handle_log_file(self, args)
def _read_report_and_log_from_stdout_if_needed(self)
def _delete_pressed(self, event)
def _on_profile_selection(self, event)
def OnMessageLogPaneChanged(self, evt)
def _initialize_variables_for_running(self, profile_settings, args)
def _save_command_args_in_file(self, args)
def _run_tests(self, log_level='INFO')
def _register_actions(self)
def _bind_local_toolbar_events(self, toolbar)
def _handle_continue(self, args)
def _create_text_ctrl(self, parent)
def _handle_end_test(self, args)
def _remove_temporary_directory(self)
def _test_runner_events_handler(self, event, *args)
Endpoint of the listener interface.
def _set_profile(self, profile_name)
Set the profile to be used to run tests.
def _append_text(self, text_ctrl, text, source="stdout")
def _bind_runner_toolbar_events(self, toolbar)
def _handle_end_keyword(self)
def _build_runner_toolbar(self, parent)
def _create_check_box(parent, id, label, value, tooltip)
def OnStop(self, event)
Called when the user clicks the "Stop" button.
def _copy_from_log_ctrls(self, event)
def _register_shortcuts(self)
def _create_command_args(self, profile_command_args, log_level='INFO', use_colors=False)
def parse_colors(self, txt)
def _append_to_message_log(self, text, source="stdout")
def _reset_memory_calc(self)
def OnOpenLogsDirectory(self, evt)
Called when the user clicks on the "Open Logs Directory" button.
def _handle_report_file(self, args)
def _build_config_panel(self, parent)
Builds the configuration panel for this plugin.
def _handle_start_keyword(self, args)
def OnShowReport(self, evt)
Called when the user clicks on the "Report" button.
def _get_all_subclasses(self, class_)
def OnStepOver(self, event)
def _get_console_width(self)
def store_color(self, idx, color)
def _notify_user_no_logs_directory()
def _build_output_panel(self, parent)
def _append_to_console_log(self, text, source="stdout")
Put output to the text control.
def _change_item_proportion(panel, item, proportion)
def _handle_start_test(self, args)
def OnRun(self, event)
Called when the user clicks or presses the F8, Run Tests.
def _create_command(self, profile_command, args_file)
def _add_tab_to_notebook(self)
def _on_pause_on_failure_cb(self, evt)
def _init_profile_choice(self, profile_name)
First installation of the profile to be used to run tests.
def OnConsoleLogPaneChanged(self, evt)
def localize_shortcuts(string)
def _RunProfile(name, run_prefix)
def open_filemanager(path=None)
def get_system_encoding()
def get_console_encoding()
def ReadFonts(fixed=False)
Returns list with fixed width fonts.