From a9738fb1647dc77fd7e1139b0212fb8f4e094f32 Mon Sep 17 00:00:00 2001 From: Oliver Eickmeyer Date: Thu, 5 Apr 2018 10:20:16 +0200 Subject: [PATCH 1/3] Issue #216: Run current test at cursor position Integrated our previous stand-alone prototype into the Robot Framework Assistant PlugIn. Still alpha status. --- commands/__init__.py | 4 +- commands/start_current_robot_test.py | 132 +++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 commands/start_current_robot_test.py diff --git a/commands/__init__.py b/commands/__init__.py index bfe5bd9..f1a7ab1 100644 --- a/commands/__init__.py +++ b/commands/__init__.py @@ -11,6 +11,7 @@ from .setting_import_helper import InsertImport from .setting_import_helper import SettingImporter from .show_documentation import ShowKeywordDocumentation +from .start_current_robot_test import StartCurrentRobotTestCommand __all__ = [ 'IndexOpenTabCommand', @@ -25,5 +26,6 @@ 'ScanIndexCommand', 'ScanOpenTabCommand', 'SettingImporter', - 'ShowKeywordDocumentation' + 'ShowKeywordDocumentation', + 'StartCurrentRobotTestCommand' ] diff --git a/commands/start_current_robot_test.py b/commands/start_current_robot_test.py new file mode 100644 index 0000000..6a1a74d --- /dev/null +++ b/commands/start_current_robot_test.py @@ -0,0 +1,132 @@ +import json +import re +import os +import platform +import sublime, sublime_plugin +import subprocess + +class StartCurrentRobotTestCommand(sublime_plugin.TextCommand): + """ Run the current test case with Robot. + + The current test case is found by checking the position of the first selection region. + The algorithm will first check that the position is in the Testcase-table and will then + look backwards line by line for the next line which matches the definition of a Testcase-name. + + Uses settings from Robot Framework Assistant (Robot.sublime-settings): + "robot_framework_workspace": "path_were_to_run_Robot" + "robot_framework_output_path": "path_where_to_put_the_files_generated_by_Robot" + "robot_framework_keep_console": [true|false] (only Windows, default: false) + "robot_framework_consolewidth": + + Example how to bind the function to a key: + { "keys": ["f8"], + "command": "start_current_robot_test" + }, + { "keys": ["shift+f8"], + "command": "start_current_robot_test", + "args": {"repeat": true} + } + """ + + table_regex = re.compile(r'^\s{0,1}\*+\s{0,1}(.+?)\s{0,1}\*') + keyword_regex = re.compile(r'^(\|\s)?(?P[^\s\|]+[^\|]*?)(\s*|\s*\|)?$') + prev_test_file = 'previousTest.json' + + def run(self, edit, repeat=False): + """ Runs current test with Robot, or repeats last test. + + Arguments: + repeat -- if true, the last test will be repeated, instead of running current test + """ + if repeat: + self.repeat_previous_started_test() + else: + self.run_current_test() + + def run_current_test(self): + line = self.get_current_line() + table_name = self.get_table_name(line) + if self.is_table_testcase(table_name): + testcase_name = self.get_keyword_name(line) + suite_name = self.get_suite_name() + self.start_robot(testcase_name, suite_name) + previous_started_test = {'testcase': testcase_name, 'suite': suite_name} + with open(self.prev_test_file, 'w') as jsonfile: + json.dump(previous_started_test, jsonfile) + else: + self.print_and_send('no testcase') + + def repeat_previous_started_test(self): + self.print_and_send('repeating') + with open(self.prev_test_file, 'r') as jsonfile: + previous_started_test = json.load(jsonfile) + testcase_name = previous_started_test['testcase'] + suite_name = previous_started_test['suite'] + self.start_robot(testcase_name, suite_name) + + def start_robot(self, testcase, suite): + settings = sublime.load_settings('Robot.sublime-settings') + self.print_and_send("starting Test '{}' in Suite '{}'".format(testcase, suite)) + work_path = settings.get('robot_framework_workspace') + output_path = settings.get('robot_framework_output_path') + consolewidth = settings.get('robot_framework_consolewidth') + if platform.system() == 'Windows': + cmd = 'cmd ' + cmd += '/k ' if settings.get('robot_framework_keep_console') else '/c ' + cmd += 'pybot ' + else: + cmd = 'python -m robot.run ' + if consolewidth: + cmd += '--consolewidth %s ' % consolewidth + cmd += '--test "%s" ' % testcase + cmd += '--suite "%s" ' % suite + cmd += '--outputdir %s ' % output_path + cmd += '--debugfile debug.txt ' + cmd += '.' + subprocess.Popen(cmd, cwd=work_path) + + def print_and_send(self, message): + print(message) + sublime.status_message(message) + + def get_current_line(self): + first_region = self.view.sel()[0] + return self.view.line(first_region.begin()) + + def row_to_line(self, row): + point = self.view.text_point(row, 0) + return self.view.line(point) + + def get_table_name(self, line): + row, _ = self.view.rowcol(line.begin()) + found = None + while not found and row >= 0: + line_str = self.view.substr(self.row_to_line(row)) + match = self.table_regex.search(line_str) + if match: + found = match.group(1) + row -= 1 + return found + + def is_table_testcase(self, table_name): + return table_name.upper() in ['TEST CASES', 'TEST CASE', 'TESTCASES', 'TESTCASE'] + + def get_keyword_name(self, line): + row, _ = self.view.rowcol(line.begin()) + found = None + while not found and row >= 0: + line_str = self.view.substr(self.row_to_line(row)) + match = self.keyword_regex.search(line_str) + if match: + found = match.group('keyword') + row -= 1 + return found + + def get_suite_name(self): + file_name = self.view.file_name() + suite_name = None + if file_name.endswith('.robot') or file_name.endswith('.txt'): + p_stop = file_name.rfind('.') + p_start = file_name.rfind(os.sep) + 1 + suite_name = file_name[p_start:p_stop] + return suite_name From 59cfb59398d1d8db7ec672fefffaababf9e9390b Mon Sep 17 00:00:00 2001 From: oeick Date: Fri, 6 Apr 2018 11:13:46 +0200 Subject: [PATCH 2/3] Issue #216: updated documentation, made algorithm robust against missing output dir and missing testsuite name --- Default (Linux).sublime-keymap | 4 +++- Default (OSX).sublime-keymap | 4 +++- Default (Windows).sublime-keymap | 5 +++-- README.md | 21 +++++++++++++++++++++ commands/start_current_robot_test.py | 13 +++++++++++-- 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Default (Linux).sublime-keymap b/Default (Linux).sublime-keymap index fbcc251..6abdaf1 100644 --- a/Default (Linux).sublime-keymap +++ b/Default (Linux).sublime-keymap @@ -4,5 +4,7 @@ { "keys": ["ctrl+alt+a"], "command": "scan_index" }, { "keys": ["ctrl+alt+s"], "command": "scan" }, { "keys": ["ctrl+alt+i"], "command": "scan_and_index_open_tab" }, - { "keys": ["ctrl+alt+r"], "command": "setting_importer" } + { "keys": ["ctrl+alt+r"], "command": "setting_importer" }, + { "keys": ["f8"], "command": "start_current_robot_test" }, + { "keys": ["shift+f8"], "command": "start_current_robot_test", "args": {"repeat": true}} ] \ No newline at end of file diff --git a/Default (OSX).sublime-keymap b/Default (OSX).sublime-keymap index fbcc251..6abdaf1 100644 --- a/Default (OSX).sublime-keymap +++ b/Default (OSX).sublime-keymap @@ -4,5 +4,7 @@ { "keys": ["ctrl+alt+a"], "command": "scan_index" }, { "keys": ["ctrl+alt+s"], "command": "scan" }, { "keys": ["ctrl+alt+i"], "command": "scan_and_index_open_tab" }, - { "keys": ["ctrl+alt+r"], "command": "setting_importer" } + { "keys": ["ctrl+alt+r"], "command": "setting_importer" }, + { "keys": ["f8"], "command": "start_current_robot_test" }, + { "keys": ["shift+f8"], "command": "start_current_robot_test", "args": {"repeat": true}} ] \ No newline at end of file diff --git a/Default (Windows).sublime-keymap b/Default (Windows).sublime-keymap index f17f850..6abdaf1 100644 --- a/Default (Windows).sublime-keymap +++ b/Default (Windows).sublime-keymap @@ -4,6 +4,7 @@ { "keys": ["ctrl+alt+a"], "command": "scan_index" }, { "keys": ["ctrl+alt+s"], "command": "scan" }, { "keys": ["ctrl+alt+i"], "command": "scan_and_index_open_tab" }, - { "keys": ["ctrl+alt+r"], "command": "setting_importer" } - + { "keys": ["ctrl+alt+r"], "command": "setting_importer" }, + { "keys": ["f8"], "command": "start_current_robot_test" }, + { "keys": ["shift+f8"], "command": "start_current_robot_test", "args": {"repeat": true}} ] \ No newline at end of file diff --git a/README.md b/README.md index 8f68a8a..5aa1491 100644 --- a/README.md +++ b/README.md @@ -172,6 +172,24 @@ Such prefixes are testcase specific and must be ignored when looking up a keywor Configuration for typical Gherkin stories: "robot_framework_keyword_prefixes" : ["Given","When","Then","And","But"] +## Special settings for the `start_current_robot_test` command + +### robot_framework_output_path +Where to save output, report, log and debug files produced while running Robot tests. + +By default those files will be saved in `robot_framework_workspace`. + +### robot_framework_keep_console +If set to true, the console will stay open after running a test. + +By default the console is closed immediately after the test has finished. + +Works only on Windows. + +### robot_framework_consolewidth +Defines the width of the console output when running a test. + + # Syntax definitions By default this plugin will be used with files which extension is `.robot` and plugin will use four spaces as cell separator. The @@ -228,6 +246,9 @@ menu is only displayed if cursor is in settings table and line contains `Librari The usage of the `Ctrl + Alt + a/s/i` commands is explained in the [Internal database for keywords and variables](https://github.com/andriyko/sublime-robot-framework-assistant/wiki/Internal-database-for-keywords-and-variables) wiki page +* Pressing `F8` will run the current test (where the [first] cursor is) +* Pressing `Shift+F8` will repeat the last test which was run by `F8` + # Snippets [Snippets](http://docs.sublimetext.info/en/latest/extensibility/snippets.html?highlight=snippets) are a Sublime Text feature to provide commonly used text templates diff --git a/commands/start_current_robot_test.py b/commands/start_current_robot_test.py index 6a1a74d..016bf0d 100644 --- a/commands/start_current_robot_test.py +++ b/commands/start_current_robot_test.py @@ -70,19 +70,28 @@ def start_robot(self, testcase, suite): work_path = settings.get('robot_framework_workspace') output_path = settings.get('robot_framework_output_path') consolewidth = settings.get('robot_framework_consolewidth') + if platform.system() == 'Windows': cmd = 'cmd ' cmd += '/k ' if settings.get('robot_framework_keep_console') else '/c ' cmd += 'pybot ' else: cmd = 'python -m robot.run ' + if consolewidth: cmd += '--consolewidth %s ' % consolewidth + cmd += '--test "%s" ' % testcase - cmd += '--suite "%s" ' % suite - cmd += '--outputdir %s ' % output_path + + if suite: + cmd += '--suite "%s" ' % suite + + if output_path: + cmd += '--outputdir %s ' % output_path + cmd += '--debugfile debug.txt ' cmd += '.' + subprocess.Popen(cmd, cwd=work_path) def print_and_send(self, message): From 258187d0be9c9cbdfde19f7cba833ec03cd4e7c2 Mon Sep 17 00:00:00 2001 From: oeick Date: Mon, 9 Apr 2018 17:07:06 +0200 Subject: [PATCH 3/3] Issue #216: Added a small feature: Save all open views, when running the current test can be configured, and will also work when repeating a test --- README.md | 3 +++ commands/start_current_robot_test.py | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/README.md b/README.md index 5aa1491..fe5bf0d 100644 --- a/README.md +++ b/README.md @@ -189,6 +189,9 @@ Works only on Windows. ### robot_framework_consolewidth Defines the width of the console output when running a test. +### robot_framework_save_before_running_test +If set to `true` all views will be saved, before starting the current test. + # Syntax definitions By default this plugin will be used with files which extension is diff --git a/commands/start_current_robot_test.py b/commands/start_current_robot_test.py index 016bf0d..ff946ce 100644 --- a/commands/start_current_robot_test.py +++ b/commands/start_current_robot_test.py @@ -17,6 +17,7 @@ class StartCurrentRobotTestCommand(sublime_plugin.TextCommand): "robot_framework_output_path": "path_where_to_put_the_files_generated_by_Robot" "robot_framework_keep_console": [true|false] (only Windows, default: false) "robot_framework_consolewidth": + "robot_framework_save_before_running_test": [true|false] (default false) Example how to bind the function to a key: { "keys": ["f8"], @@ -64,8 +65,14 @@ def repeat_previous_started_test(self): suite_name = previous_started_test['suite'] self.start_robot(testcase_name, suite_name) + def save_all_views(self): + for open_view in self.view.window().views(): + open_view.run_command('save') + def start_robot(self, testcase, suite): settings = sublime.load_settings('Robot.sublime-settings') + if settings.get('robot_framework_save_before_running_test'): + self.save_all_views() self.print_and_send("starting Test '{}' in Suite '{}'".format(testcase, suite)) work_path = settings.get('robot_framework_workspace') output_path = settings.get('robot_framework_output_path')