Skip to content

Commit 52f4f9b

Browse files
committed
Return only needed information back to Robot.
Fixes #12. Unit test changes unfortunately contain also general cleanup. Should have done that separataly, but don't think separating changes is worth the effort anymore.
1 parent a1e674d commit 52f4f9b

File tree

2 files changed

+84
-32
lines changed

2 files changed

+84
-32
lines changed

src/robotremoteserver.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,26 +106,33 @@ def get_keyword_names(self):
106106

107107
def run_keyword(self, name, args, kwargs=None):
108108
args, kwargs = self._handle_binary_args(args, kwargs or {})
109-
result = {'status': 'FAIL', 'return': '', 'output': '',
110-
'error': '', 'traceback': ''}
109+
result = {'status': 'FAIL'}
111110
self._intercept_std_streams()
112111
try:
113112
return_value = self._get_keyword(name)(*args, **kwargs)
114113
except:
115114
exc_type, exc_value, exc_tb = sys.exc_info()
116-
result['error'] = self._get_error_message(exc_type, exc_value)
117-
result['traceback'] = self._get_error_traceback(exc_tb)
118-
result['continuable'] = self._get_error_attribute(exc_value, 'CONTINUE')
119-
result['fatal'] = self._get_error_attribute(exc_value, 'EXIT')
115+
self._add_to_result(result, 'error',
116+
self._get_error_message(exc_type, exc_value))
117+
self._add_to_result(result, 'traceback',
118+
self._get_error_traceback(exc_tb))
119+
self._add_to_result(result, 'continuable',
120+
self._get_error_attribute(exc_value, 'CONTINUE'),
121+
default=False)
122+
self._add_to_result(result, 'fatal',
123+
self._get_error_attribute(exc_value, 'EXIT'),
124+
default=False)
120125
else:
121126
try:
122-
result['return'] = self._handle_return_value(return_value)
127+
self._add_to_result(result, 'return',
128+
self._handle_return_value(return_value))
123129
except:
124130
exc_type, exc_value, _ = sys.exc_info()
125-
result['error'] = self._get_error_message(exc_type, exc_value)
131+
self._add_to_result(result, 'error',
132+
self._get_error_message(exc_type, exc_value))
126133
else:
127134
result['status'] = 'PASS'
128-
result['output'] = self._restore_std_streams()
135+
self._add_to_result(result, 'output', self._restore_std_streams())
129136
return result
130137

131138
def _handle_binary_args(self, args, kwargs):
@@ -136,6 +143,10 @@ def _handle_binary_args(self, args, kwargs):
136143
def _handle_binary_arg(self, arg):
137144
return arg if not isinstance(arg, Binary) else str(arg)
138145

146+
def _add_to_result(self, result, key, value, default=''):
147+
if value != default:
148+
result[key] = value
149+
139150
def get_keyword_arguments(self, name):
140151
kw = self._get_keyword(name)
141152
if not kw:

utest/test_robotremoteserver.py

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,51 @@
77

88

99
class NonServingRemoteServer(RobotRemoteServer):
10+
1011
def __init__(self, library):
1112
self._library = library
1213

14+
1315
class StaticLibrary:
16+
1417
def passing_keyword(self):
1518
pass
16-
def failing_keyword(self, exception, message='Hello, world!'):
17-
raise exception(message)
19+
20+
def failing_keyword(self, exception=AssertionError, message='Hello, world!',
21+
**kwargs):
22+
err = exception(message)
23+
for name, value in kwargs.items():
24+
setattr(err, name, value)
25+
raise err
26+
27+
def returning_keyword(self, value):
28+
return value
29+
1830
def logging_keyword(self, stdout, stderr):
1931
if stdout:
2032
sys.stdout.write(stdout)
2133
if stderr:
2234
sys.stderr.write(stderr)
2335
self.streams = (sys.stdout, sys.stderr)
36+
2437
def _not_included(self):
2538
"""Starts with an underscore"""
39+
2640
not_included = "Not a method or function"
2741
not_included_2 = NonServingRemoteServer # Callable but not method/function
2842

43+
2944
class HybridLibrary:
45+
3046
def __init__(self):
3147
self.library = StaticLibrary()
48+
3249
def get_keyword_names(self):
3350
return [n for n in dir(self.library) if n.endswith('_keyword')]
51+
3452
def __getattr__(self, name):
3553
return getattr(self.library, name)
54+
3655
def not_included(self):
3756
"""Not returned by get_keyword_names"""
3857

@@ -46,43 +65,65 @@ def setUp(self):
4665
def test_get_keyword_names(self):
4766
self.assertEquals(self.server.get_keyword_names(),
4867
['failing_keyword', 'logging_keyword',
49-
'passing_keyword', 'stop_remote_server'])
68+
'passing_keyword', 'returning_keyword',
69+
'stop_remote_server'])
5070

5171
def test_run_passing_keyword(self):
52-
self.assertEquals(self.server.run_keyword('passing_keyword', []),
53-
{'status': 'PASS', 'output': '', 'traceback': '',
54-
'return': '', 'error': ''})
72+
self.assertEquals(self._run('passing_keyword'), {'status': 'PASS'})
73+
74+
def test_returning_keyword(self):
75+
for ret in 'Hello, world!', 42, True:
76+
self.assertEquals(self._run('returning_keyword', ret),
77+
{'status': 'PASS', 'return': ret})
5578

5679
def test_run_failing_keyword(self):
57-
ret = self.server.run_keyword('failing_keyword', [ValueError])
58-
self.assertEquals(ret['status'], 'FAIL')
59-
self.assertEquals(ret['error'], 'ValueError: Hello, world!')
80+
ret = self._run('failing_keyword', ValueError)
81+
self._verify_failed(ret, 'ValueError: Hello, world!')
6082

6183
def test_strip_generic_exception_names_from_error_messages(self):
6284
for exception in AssertionError, Exception, RuntimeError:
63-
ret = self.server.run_keyword('failing_keyword', [exception])
64-
self.assertEquals(ret['status'], 'FAIL')
65-
self.assertEquals(ret['error'], 'Hello, world!')
85+
ret = self._run('failing_keyword', exception)
86+
self._verify_failed(ret, 'Hello, world!')
6687

6788
def test_return_only_exception_name_if_no_error_message(self):
6889
for exception in AssertionError, ValueError:
69-
ret = self.server.run_keyword('failing_keyword', [exception, ''])
70-
self.assertEquals(ret['status'], 'FAIL')
71-
self.assertEquals(ret['error'], exception.__name__)
90+
ret = self._run('failing_keyword', exception, '')
91+
self._verify_failed(ret, exception.__name__)
92+
93+
def test_continuable_error(self):
94+
ret = self._run('failing_keyword', ROBOT_CONTINUE_ON_FAILURE=True)
95+
self._verify_failed(ret, continuable=True)
96+
97+
def test_fatal_error(self):
98+
ret = self._run('failing_keyword', ROBOT_EXIT_ON_FAILURE='yes please')
99+
self._verify_failed(ret, fatal=True)
72100

73101
def test_logging_to_stdout(self):
74-
ret = self.server.run_keyword('logging_keyword', ['out', ''])
75-
self.assertEquals(ret['output'], 'out')
76-
self.assertTrue(all(s.closed for s in self.library.streams))
102+
ret = self._run('logging_keyword', 'out', '')
103+
self._verify_logged(ret, 'out')
77104

78105
def test_logging_to_stderr(self):
79-
ret = self.server.run_keyword('logging_keyword', ['', 'err'])
80-
self.assertEquals(ret['output'], 'err')
81-
self.assertTrue(all(s.closed for s in self.library.streams))
106+
ret = self._run('logging_keyword', '', 'err')
107+
self._verify_logged(ret, 'err')
82108

83109
def test_logging_to_stdout_and_stderr(self):
84-
ret = self.server.run_keyword('logging_keyword', ['out', 'err'])
85-
self.assertEquals(ret['output'], 'out\n*INFO* err')
110+
ret = self._run('logging_keyword', 'out', 'err')
111+
self._verify_logged(ret, 'out\n*INFO* err')
112+
113+
def _run(self, kw, *args, **kwargs):
114+
return self.server.run_keyword(kw, args, kwargs)
115+
116+
def _verify_failed(self, ret, error='Hello, world!', continuable=False,
117+
fatal=False):
118+
ret.pop('traceback')
119+
if continuable:
120+
self.assertEquals(ret.pop('continuable'), True)
121+
if fatal:
122+
self.assertEquals(ret.pop('fatal'), True)
123+
self.assertEquals(ret, {'error': error, 'status': 'FAIL'})
124+
125+
def _verify_logged(self, ret, output):
126+
self.assertEquals(ret, {'output': output, 'status': 'PASS'})
86127
self.assertTrue(all(s.closed for s in self.library.streams))
87128

88129

0 commit comments

Comments
 (0)