Robot Framework
errors.py
Go to the documentation of this file.
1 # Copyright 2008-2015 Nokia Networks
2 # Copyright 2016- Robot Framework Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 
20 
21 # Return codes from Robot and Rebot.
22 # RC below 250 is the number of failed critical tests and exactly 250
23 # means that number or more such failures.
24 INFO_PRINTED = 251 # --help or --version
25 DATA_ERROR = 252 # Invalid data or cli args
26 STOPPED_BY_USER = 253 # KeyboardInterrupt or SystemExit
27 FRAMEWORK_ERROR = 255 # Unexpected error
28 
29 
30 
35 
36  def __init__(self, message='', details=''):
37  super().__init__(message)
38  self.detailsdetails = details
39 
40  @property
41  message = property
42 
43  def message(self):
44  return str(self)
45 
46 
47 
54 
55 
56 
61 class DataError(RobotError):
62  def __init__(self, message='', details='', syntax=False):
63  super().__init__(message, details)
64  self.syntaxsyntax = syntax
65 
66 
67 
73  def __init__(self, message='', details=''):
74  super().__init__(message, details)
75 
76 
77 
83  def __init__(self, message='', details=''):
84  super().__init__(message, details)
85 
86 
87 
94 
95  def __init__(self, message='', test_timeout=True):
96  super().__init__(message)
97  self.test_timeouttest_timeout = test_timeout
98 
99  @property
100  keyword_timeout = property
101 
102  def keyword_timeout(self):
103  return not self.test_timeouttest_timeout
104 
105 
106 
108 
109 
110 
111 class ExecutionStatus(RobotError):
112 
113  def __init__(self, message, test_timeout=False, keyword_timeout=False,
114  syntax=False, exit=False, continue_on_failure=False,
115  skip=False, return_value=None):
116  if '\r\n' in message:
117  message = message.replace('\r\n', '\n')
118  from robot.utils import cut_long_message
119  super().__init__(cut_long_message(message))
120  self.test_timeouttest_timeout = test_timeout
121  self.keyword_timeoutkeyword_timeout = keyword_timeout
122  self.syntaxsyntax = syntax
123  self.exitexit = exit
124  self._continue_on_failure_continue_on_failure = continue_on_failure
125  self.skipskip = skip
126  self.return_valuereturn_value = return_value
127 
128  @property
129  timeout = property
130 
131  def timeout(self):
132  return self.test_timeouttest_timeout or self.keyword_timeoutkeyword_timeout
133 
134  @property
135  dont_continue = property
136 
137  def dont_continue(self):
138  return self.timeouttimeouttimeout or self.syntaxsyntax or self.exitexit
139 
140  @property
141  continue_on_failure = property
142 
144  return self._continue_on_failure_continue_on_failure
145 
146  @continue_on_failure.setter
147 
148  def continue_on_failure(self, continue_on_failure):
149  self._continue_on_failure_continue_on_failure = continue_on_failure
150  for child in getattr(self, '_errors', []):
151  if child is not self:
152  child.continue_on_failure = continue_on_failure
153 
154  def can_continue(self, context, templated=False):
155  if context.dry_run:
156  return True
157  if self.syntaxsyntax or self.exitexit or self.skipskip or self.test_timeouttest_timeout:
158  return False
159  if templated:
160  return context.continue_on_failure(default=True)
161  if self.keyword_timeoutkeyword_timeout:
162  if context.in_teardown:
163  self.keyword_timeoutkeyword_timeout = False
164  return False
165  return self.continue_on_failurecontinue_on_failurecontinue_on_failurecontinue_on_failure or context.continue_on_failure()
166 
167  def get_errors(self):
168  return [self]
169 
170  @property
171  status = property
172 
173  def status(self):
174  return 'FAIL' if not self.skipskip else 'SKIP'
175 
176 
177 
179 
180 
181 class HandlerExecutionFailed(ExecutionFailed):
182 
183  def __init__(self, details):
184  error = details.error
185  timeout = isinstance(error, TimeoutError)
186  test_timeout = timeout and error.test_timeout
187  keyword_timeout = timeout and error.keyword_timeout
188  syntax = isinstance(error, DataError) and error.syntax
189  exit_on_failure = self._get_get(error, 'EXIT_ON_FAILURE')
190  continue_on_failure = self._get_get(error, 'CONTINUE_ON_FAILURE')
191  skip = self._get_get(error, 'SKIP_EXECUTION')
192  super().__init__(details.message, test_timeout, keyword_timeout, syntax,
193  exit_on_failure, continue_on_failure, skip)
194 
195  def _get(self, error, attr):
196  return bool(getattr(error, 'ROBOT_' + attr, False))
197 
198 
200 
201  def __init__(self, errors, message=None):
202  super().__init__(message or self._format_message_format_message(errors),
203  **self._get_attrs_get_attrs(errors))
204  self._errors_errors = errors
205 
206  def _format_message(self, errors):
207  messages = [e.message for e in errors]
208  if len(messages) == 1:
209  return messages[0]
210  prefix = 'Several failures occurred:'
211  if any(msg.startswith('*HTML*') for msg in messages):
212  html_prefix = '*HTML* '
213  messages = [self._html_format_html_format(msg) for msg in messages]
214  else:
215  html_prefix = ''
216  if any(e.skip for e in errors):
217  skip_idx = errors.index([e for e in errors if e.skip][0])
218  skip_msg = messages[skip_idx]
219  messages = messages[:skip_idx] + messages[skip_idx+1:]
220  if len(messages) == 1:
221  return '%s%s\n\nAlso failure occurred:\n%s' \
222  % (html_prefix, skip_msg, messages[0])
223  prefix = '%s\n\nAlso failures occurred:' % skip_msg
224  return '\n\n'.join(
225  [html_prefix + prefix] +
226  ['%d) %s' % (i, m) for i, m in enumerate(messages, start=1)]
227  )
228 
229  def _html_format(self, msg):
230  from robot.utils import html_escape
231  if msg.startswith('*HTML*'):
232  return msg[6:].lstrip()
233  return html_escape(msg)
234 
235  def _get_attrs(self, errors):
236  return {
237  'test_timeout': any(e.test_timeout for e in errors),
238  'keyword_timeout': any(e.keyword_timeout for e in errors),
239  'syntax': any(e.syntax for e in errors),
240  'exit': any(e.exit for e in errors),
241  'continue_on_failure': all(e.continue_on_failure for e in errors),
242  'skip': any(e.skip for e in errors)
243  }
244 
245  def get_errors(self):
246  return self._errors_errors
247 
248 
250 
251  def __init__(self, run_errors=None, teardown_errors=None):
252  super().__init__(self._get_errors_get_errors(run_errors, teardown_errors),
253  self._get_message_get_message(run_errors, teardown_errors))
254  if run_errors and not teardown_errors:
255  self._errors_errors_errors = run_errors.get_errors()
256  else:
257  self._errors_errors_errors = [self]
258 
259  def _get_errors(self, *errors):
260  return [err for err in errors if err]
261 
262  def _get_message(self, run_errors, teardown_errors):
263  run_msg = run_errors.message if run_errors else ''
264  td_msg = teardown_errors.message if teardown_errors else ''
265  if not td_msg:
266  return run_msg
267  if not run_msg:
268  return 'Keyword teardown failed:\n%s' % td_msg
269  return '%s\n\nAlso keyword teardown failed:\n%s' % (run_msg, td_msg)
270 
271 
272 
277 
278  def __init__(self, message=None, **kwargs):
279  super().__init__(message, **kwargs)
280  self._earlier_failures_earlier_failures = []
281 
282  def set_earlier_failures(self, failures):
283  if failures:
284  self._earlier_failures_earlier_failures = list(failures) + self._earlier_failures_earlier_failures
285 
286  @property
287  earlier_failures = property
288 
289  def earlier_failures(self):
290  if not self._earlier_failures_earlier_failures:
291  return None
292  return ExecutionFailures(self._earlier_failures_earlier_failures)
293 
294  @property
295  status = property
296 
297  def status(self):
298  return 'PASS' if not self._earlier_failures_earlier_failures else 'FAIL'
299 
300 
301 
303 
304  def __init__(self, message):
305  super().__init__(message)
306 
307 
308 
310 
311  def __init__(self):
312  super().__init__("Invalid 'CONTINUE' usage.")
313 
314 
315 
317 
318  def __init__(self):
319  super().__init__("Invalid 'BREAK' usage.")
320 
321 
322 
324 
325  def __init__(self, return_value=None, failures=None):
326  super().__init__("Invalid 'RETURN' usage.", return_value=return_value)
327  if failures:
328  self.set_earlier_failuresset_earlier_failures(failures)
329 
330 
331 
333 
334  def __init__(self, message='', details='', fatal=False, continuable=False):
335  super().__init__(message, details)
336  self.ROBOT_EXIT_ON_FAILUREROBOT_EXIT_ON_FAILURE = fatal
337  self.ROBOT_CONTINUE_ON_FAILUREROBOT_CONTINUE_ON_FAILURE = continuable
Used by BREAK statement.
Definition: errors.py:316
def __init__(self)
Definition: errors.py:318
Used by CONTINUE statement.
Definition: errors.py:309
def __init__(self, message='', details='', syntax=False)
Definition: errors.py:62
Used for communicating failures in test execution.
Definition: errors.py:178
def _format_message(self, errors)
Definition: errors.py:206
def _get_attrs(self, errors)
Definition: errors.py:235
def __init__(self, errors, message=None)
Definition: errors.py:201
def _html_format(self, msg)
Definition: errors.py:229
Base class for all exceptions communicating that execution passed.
Definition: errors.py:276
def set_earlier_failures(self, failures)
Definition: errors.py:282
def __init__(self, message=None, **kwargs)
Definition: errors.py:278
def can_continue(self, context, templated=False)
Definition: errors.py:154
def continue_on_failure(self)
Definition: errors.py:143
def continue_on_failure(self, continue_on_failure)
Definition: errors.py:148
def __init__(self, message, test_timeout=False, keyword_timeout=False, syntax=False, exit=False, continue_on_failure=False, skip=False, return_value=None)
Definition: errors.py:115
Can be used when the core framework goes to unexpected state.
Definition: errors.py:53
def _get(self, error, attr)
Definition: errors.py:195
def __init__(self, details)
Definition: errors.py:183
Used by argument parser with –help or –version.
Definition: errors.py:107
Used when no keyword is found or there is more than one match.
Definition: errors.py:82
def __init__(self, message='', details='')
Definition: errors.py:83
Used by 'Pass Execution' keyword.
Definition: errors.py:302
def __init__(self, message)
Definition: errors.py:304
Used by Remote library to report remote errors.
Definition: errors.py:332
def __init__(self, message='', details='', fatal=False, continuable=False)
Definition: errors.py:334
Used by 'RETURN' statement.
Definition: errors.py:323
def __init__(self, return_value=None, failures=None)
Definition: errors.py:325
Base class for Robot Framework errors.
Definition: errors.py:34
def __init__(self, message='', details='')
Definition: errors.py:36
Used when a test or keyword timeout occurs.
Definition: errors.py:93
def __init__(self, message='', test_timeout=True)
Definition: errors.py:95
def __init__(self, run_errors=None, teardown_errors=None)
Definition: errors.py:251
def _get_message(self, run_errors, teardown_errors)
Definition: errors.py:262
Used when variable does not exist.
Definition: errors.py:72
def __init__(self, message='', details='')
Definition: errors.py:73
def html_escape(text, linkify=True)
Definition: markuputils.py:44
def cut_long_message(msg)
Definition: text.py:43