16 from collections
import OrderedDict
21 from robot.api import logger, SkipExecution
23 from robot.errors import (BreakLoop, ContinueLoop, DataError, ExecutionFailed,
24 ExecutionFailures, ExecutionPassed, PassExecution,
25 ReturnFromKeyword, VariableError)
29 from robot.utils import (DotDict, escape, format_assign_message, get_error_message,
30 get_time, html_escape, is_falsy, is_integer, is_list_like,
31 is_string, is_truthy, Matcher, normalize,
32 normalize_whitespace, parse_re_flags, parse_time, prepr,
33 plural_or_not
as s, RERAISED_EXCEPTIONS, safe_str,
34 secs_to_timestr, seq2str, split_from_equals,
35 timestr_to_secs, type_name)
38 is_list_variable, search_variable,
39 DictVariableTableValue, VariableTableValue)
47 def decorator(method):
48 RUN_KW_REGISTER.register_run_keyword(
'BuiltIn', method.__name__,
49 resolve, deprecation_warning=
False,
64 ctx = EXECUTION_CONTEXTS.current
if not top
else EXECUTION_CONTEXTS.top
81 def _matches(self, string, pattern, caseless=False):
83 matcher = Matcher(pattern, caseless=caseless, spaceless=
False)
84 return matcher.match(string)
88 condition = self.evaluate(condition)
89 return bool(condition)
95 msg = [
"Argument types are:"] + [self.
_get_type_get_type(a)
for a
in args]
96 self.log(
'\n'.join(msg), level)
135 item, base = self.
_get_base_get_base(orig, base)
140 raise RuntimeError(
"'%s' cannot be converted to an integer: %s"
147 if item.startswith((
'-',
'+')):
152 bases = {
'0b': 2,
'0o': 8,
'0x': 16}
153 if base
or not item.startswith(tuple(bases)):
154 return sign+item, base
155 return sign+item[2:], bases[item[:2]]
226 spec =
'x' if lowercase
else 'X'
232 prefix = prefix
or ''
234 prefix =
'-' + prefix
275 if precision
is not None:
287 raise RuntimeError(
"'%s' cannot be converted to a floating "
288 "point number: %s" % (item, error))
314 if item.upper() ==
'TRUE':
316 if item.upper() ==
'FALSE':
367 ordinals = getattr(self,
'_get_ordinals_from_%s' % input_type)
368 except AttributeError:
369 raise RuntimeError(
"Invalid input type '%s'." % input_type)
370 return bytes(bytearray(o
for o
in ordinals(input)))
376 ordinal = char
if is_integer(char)
else ord(char)
377 yield self.
_test_ordinal_test_ordinal(ordinal, char,
'Character')
380 if 0 <= ordinal <= 255:
382 raise RuntimeError(
"%s '%s' cannot be represented as a byte."
387 input = input.split()
390 for integer
in input:
392 yield self.
_test_ordinal_test_ordinal(ordinal, integer,
'Integer')
397 yield self.
_test_ordinal_test_ordinal(ordinal, token,
'Hex value')
402 yield self.
_test_ordinal_test_ordinal(ordinal, token,
'Binary value')
407 input =
''.join(input.split())
408 if len(input) % length != 0:
409 raise RuntimeError(
'Expected input to be multiple of %d.' % length)
410 return (input[i:i+length]
for i
in range(0, len(input), length))
425 @run_keyword_variant(resolve=0)
460 result.update(combined)
469 separate.append(item)
470 return separate, items[len(separate):]
474 if len(separate) % 2 != 0:
475 raise DataError(
'Expected even number of keys and values, got %d.'
477 return [separate[i:i+2]
for i
in range(0, len(separate), 2)]
483 set_tags = [tag
for tag
in tags
if not tag.startswith(
'-')]
484 remove_tags = [tag[1:]
for tag
in tags
if tag.startswith(
'-')]
486 self.remove_tags(*remove_tags)
488 self.set_tags(*set_tags)
512 def fail(self, msg=None, *tags):
526 error.ROBOT_EXIT_ON_FAILURE =
True
535 if self.
_is_true_is_true(condition):
536 raise AssertionError(msg
or "'%s' should not be true." % condition)
566 if not self.
_is_true_is_true(condition):
609 ignore_case=False, formatter='str', strip_spaces=False,
610 collapse_spaces=False):
614 first = first.lower()
615 second = second.lower()
618 second = self.
_strip_spaces_strip_spaces(second, strip_spaces)
622 self.
_should_be_equal_should_be_equal(first, second, msg, values, formatter)
626 formatter = self._get_formatter(formatter)
631 assert_equal(first, second, msg, include_values, formatter)
634 level =
'DEBUG' if type(first) ==
type(second)
else 'INFO'
638 first_lines = first.splitlines(
True)
639 second_lines = second.splitlines(
True)
640 if len(first_lines) < 3
or len(second_lines) < 3:
642 self.log(
"%s\n\n!=\n\n%s" % (first.rstrip(), second.rstrip()))
643 diffs = list(difflib.unified_diff(first_lines, second_lines,
644 fromfile=
'first', tofile=
'second',
646 diffs[3:] = [item[0] + formatter(item[1:]).rstrip()
for item
in diffs[3:]]
647 prefix =
'Multiline strings are different:'
649 prefix =
'%s: %s' % (msg, prefix)
653 return is_truthy(values)
and str(values).upper() !=
'NO VALUES'
659 return value.strip()
if strip_spaces
else value
660 if strip_spaces.upper() ==
'LEADING':
661 return value.lstrip()
662 if strip_spaces.upper() ==
'TRAILING':
663 return value.rstrip()
664 return value.strip()
if is_truthy(strip_spaces)
else value
667 return re.sub(
r'\s+',
' ', value)
if is_string(value)
else value
691 ignore_case=False, strip_spaces=False,
692 collapse_spaces=False):
696 first = first.lower()
697 second = second.lower()
700 second = self.
_strip_spaces_strip_spaces(second, strip_spaces)
720 values=True, base=None):
723 self._convert_to_integer(second, base),
742 self.
_should_be_equal_should_be_equal(self._convert_to_integer(first, base),
743 self._convert_to_integer(second, base),
757 values=True, precision=6):
759 first = self._convert_to_number(first, precision)
760 second = self._convert_to_number(second, precision)
797 first = self._convert_to_number(first, precision)
798 second = self._convert_to_number(second, precision)
826 ignore_case=False, strip_spaces=False,
827 collapse_spaces=False):
832 first = first.lower()
833 second = second.lower()
836 second = self.
_strip_spaces_strip_spaces(second, strip_spaces)
867 ignore_case=False, strip_spaces=False,
868 formatter='str', collapse_spaces=False):
873 first = first.lower()
874 second = second.lower()
877 second = self.
_strip_spaces_strip_spaces(second, strip_spaces)
881 self.
_should_be_equal_should_be_equal(first, second, msg, values, formatter)
890 ignore_case=False, strip_spaces=False,
891 collapse_spaces=False):
901 if str1.startswith(str2):
912 ignore_case=False, strip_spaces=False, collapse_spaces=False):
922 if not str1.startswith(str2):
924 'does not start with'))
933 ignore_case=False, strip_spaces=False,
934 collapse_spaces=False):
944 if str1.endswith(str2):
955 ignore_case=False, strip_spaces=False, collapse_spaces=False):
965 if not str1.endswith(str2):
967 'does not end with'))
996 ignore_case=False, strip_spaces=False,
997 collapse_spaces=False):
1003 orig_container = container
1007 container = container.lower()
1009 container = set(x.lower()
if is_string(x)
else x
for x
in container)
1013 container = self.
_strip_spaces_strip_spaces(container, strip_spaces)
1015 container = set(self.
_strip_spaces_strip_spaces(x, strip_spaces)
for x
in container)
1021 container = set(self.
_collapse_spaces_collapse_spaces(x)
for x
in container)
1022 if item
in container:
1024 values,
'contains'))
1058 ignore_case=False, strip_spaces=False, collapse_spaces=False):
1059 orig_container = container
1063 container = container.lower()
1065 container = set(x.lower()
if is_string(x)
else x
for x
in container)
1069 container = self.
_strip_spaces_strip_spaces(container, strip_spaces)
1071 container = set(self.
_strip_spaces_strip_spaces(x, strip_spaces)
for x
in container)
1077 container = set(self.
_collapse_spaces_collapse_spaces(x)
for x
in container)
1078 if item
not in container:
1080 values,
'does not contain'))
1104 msg = configuration.pop(
'msg',
None)
1105 values = configuration.pop(
'values',
True)
1106 ignore_case =
is_truthy(configuration.pop(
'ignore_case',
False))
1107 strip_spaces = configuration.pop(
'strip_spaces',
False)
1108 collapse_spaces =
is_truthy(configuration.pop(
'collapse_spaces',
False))
1110 raise RuntimeError(
"Unsupported configuration parameter%s: %s."
1111 % (s(configuration),
seq2str(sorted(configuration))))
1114 orig_container = container
1116 items = [x.lower()
if is_string(x)
else x
for x
in items]
1118 container = container.lower()
1120 container = set(x.lower()
if is_string(x)
else x
for x
in container)
1122 items = [self.
_strip_spaces_strip_spaces(x, strip_spaces)
for x
in items]
1124 container = self.
_strip_spaces_strip_spaces(container, strip_spaces)
1126 container = set(self.
_strip_spaces_strip_spaces(x, strip_spaces)
for x
in container)
1132 container = set(self.
_collapse_spaces_collapse_spaces(x)
for x
in container)
1133 if not any(item
in container
for item
in items):
1135 seq2str(items, lastsep=
' or '),
1137 'does not contain any of',
1162 msg = configuration.pop(
'msg',
None)
1163 values = configuration.pop(
'values',
True)
1164 ignore_case =
is_truthy(configuration.pop(
'ignore_case',
False))
1165 strip_spaces = configuration.pop(
'strip_spaces',
False)
1166 collapse_spaces =
is_truthy(configuration.pop(
'collapse_spaces',
False))
1168 raise RuntimeError(
"Unsupported configuration parameter%s: %s."
1169 % (s(configuration),
seq2str(sorted(configuration))))
1172 orig_container = container
1174 items = [x.lower()
if is_string(x)
else x
for x
in items]
1176 container = container.lower()
1178 container = set(x.lower()
if is_string(x)
else x
for x
in container)
1180 items = [self.
_strip_spaces_strip_spaces(x, strip_spaces)
for x
in items]
1182 container = self.
_strip_spaces_strip_spaces(container, strip_spaces)
1184 container = set(self.
_strip_spaces_strip_spaces(x, strip_spaces)
for x
in container)
1190 container = set(self.
_collapse_spaces_collapse_spaces(x)
for x
in container)
1191 if any(item
in container
for item
in items):
1193 seq2str(items, lastsep=
' or '),
1195 'contains one or more of',
1228 ignore_case=False, strip_spaces=False,
1229 collapse_spaces=False):
1230 count = self._convert_to_integer(count)
1231 orig_container = container
1236 container = container.lower()
1238 container = [x.lower()
if is_string(x)
else x
for x
in container]
1242 container = self.
_strip_spaces_strip_spaces(container, strip_spaces)
1244 container = [self.
_strip_spaces_strip_spaces(x, strip_spaces)
for x
in container]
1251 x = self.
get_countget_count(container, item)
1253 msg =
"%r contains '%s' %d time%s, not %d time%s." \
1254 % (orig_container, item, x, s(x), count, s(count))
1267 if not hasattr(container,
'count'):
1269 container = list(container)
1271 raise RuntimeError(
"Converting '%s' to list failed: %s"
1273 count = container.count(item)
1274 self.log(
'Item found from container %d time%s.' % (count, s(count)))
1291 if self.
_matches_matches(string, pattern, caseless=ignore_case):
1310 if not self.
_matches_matches(string, pattern, caseless=ignore_case):
1312 values,
'does not match'))
1356 values,
'does not match'))
1357 match = res.group(0)
1358 groups = res.groups()
1360 return [match] + list(groups)
1368 if re.search(pattern, string, flags=
parse_re_flags(flags))
is not None:
1394 self.log(
'Length is %d' % length)
1400 except RERAISED_EXCEPTIONS:
1404 return item.length()
1405 except RERAISED_EXCEPTIONS:
1410 except RERAISED_EXCEPTIONS:
1415 except RERAISED_EXCEPTIONS:
1418 raise RuntimeError(
"Could not get length of '%s'." % item)
1426 length = self._convert_to_integer(length)
1428 if actual != length:
1429 raise AssertionError(msg
or "Length of '%s' should be %d but is %d."
1430 % (item, length, actual))
1448 raise AssertionError(msg
or "'%s' should not be empty." % (item,))
1451 delimiter, quote_item1=True, quote_item2=True):
1452 if custom_message
and not self.
_include_values_include_values(include_values):
1453 return custom_message
1456 default_message =
'%s %s %s' % (item1, delimiter, item2)
1457 if not custom_message:
1458 return default_message
1459 return '%s: %s' % (custom_message, default_message)
1492 @keyword(types=None)
1493 @run_keyword_variant(resolve=0)
1512 name = self.
_get_var_name_get_var_name(name, require_assign=
False)
1514 except VariableError:
1520 for name
in sorted(variables, key=
lambda s: s[2:-1].lower()):
1523 self.log(msg, level)
1526 value = variables[name]
1531 value = OrderedDict(value)
1532 except RERAISED_EXCEPTIONS:
1535 name =
'$' + name[1:]
1538 @run_keyword_variant(resolve=0)
1554 except VariableError:
1556 if msg
else "Variable '%s' does not exist." % name)
1558 @run_keyword_variant(resolve=0)
1574 except VariableError:
1578 if msg
else "Variable '%s' exists." % name)
1619 if len(values) == 0:
1621 elif len(values) == 1:
1626 @run_keyword_variant(resolve=0)
1663 @run_keyword_variant(resolve=0)
1689 @run_keyword_variant(resolve=0)
1698 @run_keyword_variant(resolve=0)
1749 if values
and is_string(values[-1])
and values[-1].startswith(
'children='):
1752 values = values[:-1]
1759 @run_keyword_variant(resolve=0)
1791 except VariableError:
1799 valid = match.is_assign()
if require_assign
else match.is_variable()
1801 raise DataError(
"Invalid variable name '%s'." % name)
1805 if name.startswith(
'\\'):
1807 if len(name) < 2
or name[0]
not in '$@&':
1810 name =
'%s{%s}' % (name[0], name[1:])
1813 if not match.is_assign():
1826 raise DataError(
"Setting list value to scalar variable '%s' "
1827 "is not supported anymore. Create list "
1828 "variable '@%s' instead." % (name, name[1:]))
1844 @run_keyword_variant(resolve=0, dry_run=True)
1858 kw = Keyword(name, args=args)
1864 if hasattr(runner,
'embedded_args'):
1872 raise DataError(f
'Keyword name missing: Given arguments {name_and_args} '
1873 f
'resolved to an empty list.')
1874 return resolved[0], resolved[1:]
1876 @run_keyword_variant(resolve=0, dry_run=True)
1912 for kw, args
in iterable:
1915 except ExecutionPassed
as err:
1916 err.set_earlier_failures(errors)
1918 except ExecutionFailed
as err:
1919 errors.extend(err.get_errors())
1926 if 'AND' not in keywords:
1932 raise DataError(
'AND must have keyword before and after.')
1933 yield kw_call[0], kw_call[1:]
1940 for name
in keywords:
1942 for n
in replace_list([name], ignore_errors=ignore_errors):
1948 while 'AND' in keywords:
1949 index = keywords.index(
'AND')
1950 yield keywords[:index]
1951 keywords = keywords[index+1:]
1954 @run_keyword_variant(resolve=1, dry_run=True)
2015 if self.
_is_true_is_true(condition):
2020 if 'ELSE IF' in args:
2021 args, branch = self.
_split_branch_split_branch(args,
'ELSE IF', 2,
2022 'condition and keyword')
2025 args, branch = self.
_split_branch_split_branch(args,
'ELSE', 1,
'keyword')
2026 return args,
lambda: self.
run_keywordrun_keyword(*branch)
2027 return args,
lambda:
None
2030 index = list(args).index(control_word)
2032 if len(branch) < required:
2033 raise DataError(
'%s requires %s.' % (control_word, required_error))
2034 return args[:index], branch
2036 @run_keyword_variant(resolve=1, dry_run=True)
2045 if not self.
_is_true_is_true(condition):
2048 @run_keyword_variant(resolve=0, dry_run=True)
2068 return 'PASS', self.
run_keywordrun_keyword(name, *args)
2069 except ExecutionFailed
as err:
2070 if err.dont_continue
or err.skip:
2072 return 'FAIL', str(err)
2074 @run_keyword_variant(resolve=0, dry_run=True)
2089 if status ==
'FAIL':
2090 logger.warn(
"Executing keyword '%s' failed:\n%s" % (name, message))
2091 return status, message
2093 @run_keyword_variant(resolve=0, dry_run=True)
2112 return status ==
'PASS'
2114 @run_keyword_variant(resolve=0, dry_run=True)
2129 except ExecutionFailed
as err:
2130 if not err.dont_continue:
2131 err.continue_on_failure =
True
2134 @run_keyword_variant(resolve=1, dry_run=True)
2186 except ExecutionFailed
as err:
2187 if err.dont_continue
or err.skip:
2195 % (expected_error, error))
2200 matchers = {
'GLOB': glob,
2201 'EQUALS':
lambda s, p: s == p,
2202 'STARTS':
lambda s, p: s.startswith(p),
2203 'REGEXP':
lambda s, p: re.match(p +
r'\Z', s)
is not None}
2204 prefixes = tuple(prefix +
':' for prefix
in matchers)
2205 if not expected_error.startswith(prefixes):
2206 return glob(error, expected_error)
2207 prefix, expected_error = expected_error.split(
':', 1)
2208 return matchers[prefix](error, expected_error.lstrip())
2210 @run_keyword_variant(resolve=1, dry_run=True)
2239 except RuntimeError
as err:
2250 if times.endswith(
'times'):
2252 elif times.endswith(
'x'):
2254 elif require_postfix:
2256 return self._convert_to_integer(times)
2272 self.log(
"Keyword '%s' repeated zero times." % name)
2273 for i
in range(count):
2274 self.log(
"Repeating keyword, round %d/%d." % (i + 1, count))
2279 self.log(
"Keyword '%s' repeated zero times." % name)
2281 maxtime = time.time() + timeout
2282 while time.time() < maxtime:
2284 self.log(
"Repeating keyword, round %d, %s remaining."
2289 @run_keyword_variant(resolve=2, dry_run=True)
2333 maxtime = count = -1
2338 maxtime = time.time() + timeout
2342 raise ValueError(
'Retry count %d is not positive.' % count)
2343 message =
'%d time%s' % (count, s(count))
2345 retry_interval = retry_interval.split(
':', 1)[1].strip()
2346 strict_interval =
True
2348 strict_interval =
False
2351 start_time = time.time()
2354 except ExecutionFailed
as err:
2355 if err.dont_continue
or err.skip:
2358 if time.time() > maxtime > 0
or count == 0:
2360 "The last error was: %s" % (name, message, err))
2363 keyword_runtime = time.time() - start_time
2364 sleep_time = retry_interval - keyword_runtime
2366 logger.warn(
"Keyword execution time %s is longer than retry "
2369 self._sleep_in_parts(sleep_time)
2371 @run_keyword_variant(resolve=1)
2412 if self.
_is_true_is_true(condition):
2415 if len(values) == 1:
2417 return self.
run_keywordrun_keyword(
'BuiltIn.Set Variable If', *values[0:])
2429 @run_keyword_variant(resolve=0, dry_run=True)
2443 @run_keyword_variant(resolve=0, dry_run=True)
2457 @run_keyword_variant(resolve=0, dry_run=True)
2473 if ctx.test
and ctx.in_test_teardown:
2475 raise RuntimeError(f
"Keyword '{kwname}' can only be used in test teardown.")
2477 @run_keyword_variant(resolve=0, dry_run=True)
2488 if suite.statistics.failed == 0:
2491 @run_keyword_variant(resolve=0, dry_run=True)
2502 if suite.statistics.failed > 0:
2507 raise RuntimeError(
"Keyword '%s' can only be used in suite teardown."
2519 def skip(self, msg='Skipped with Skip keyword.'):
2531 if self.
_is_true_is_true(condition):
2566 raise DataError(
"'Continue For Loop' can only be used inside a loop.")
2567 self.log(
"Continuing for loop from the next iteration.")
2597 raise DataError(
"'Continue For Loop If' can only be used inside a loop.")
2598 if self.
_is_true_is_true(condition):
2633 raise DataError(
"'Exit For Loop' can only be used inside a loop.")
2634 self.log(
"Exiting for loop altogether.")
2664 raise DataError(
"'Exit For Loop If' can only be used inside a loop.")
2665 if self.
_is_true_is_true(condition):
2668 @run_keyword_variant(resolve=0)
2730 self.log(
'Returning from the enclosing user keyword.')
2733 @run_keyword_variant(resolve=1)
2769 if self.
_is_true_is_true(condition):
2772 @run_keyword_variant(resolve=0, dry_run=True)
2792 ret = self.run_keyword(name, *args)
2793 except ExecutionFailed
as err:
2798 @run_keyword_variant(resolve=1, dry_run=True)
2814 if self.
_is_true_is_true(condition):
2860 message = message.strip()
2863 self._set_and_remove_tags(tags)
2864 log_message, level = self._get_logged_test_message_and_level(message)
2865 self.log(
'Execution passed with message:\n%s' % log_message, level)
2868 @run_keyword_variant(resolve=1)
2883 if self.
_is_true_is_true(condition):
2924 endtime = time.time() + float(seconds)
2926 remaining = endtime - time.time()
2929 time.sleep(min(remaining, 0.01))
2949 items = [str(item)
for item
in items]
2950 if items[0].startswith(
'SEPARATOR='):
2951 sep = items[0][len(
'SEPARATOR='):]
2955 return sep.join(items)
3008 def log(self, message, level='INFO', html=False, console=False,
3009 repr='DEPRECATED', formatter='str'):
3011 if repr ==
'DEPRECATED':
3014 logger.warn(
"The 'repr' argument of 'BuiltIn.Log' is deprecated. "
3015 "Use 'formatter=repr' instead.")
3017 message = formatter(message)
3018 logger.write(message, level, html)
3020 logger.console(message)
3024 return {
'str': safe_str,
3028 'type':
lambda x:
type(x).__name__}[formatter.lower()]
3030 raise ValueError(
"Invalid formatter '%s'. Available "
3031 "'str', 'repr', 'ascii', 'len', and 'type'." % formatter)
3033 @run_keyword_variant(resolve=0)
3050 for msg
in messages:
3053 if match.is_list_variable():
3056 elif match.is_dict_variable():
3057 for name, value
in value.items():
3058 yield '%s=%s' % (name, value)
3091 format =
"{:" + format +
"}"
3092 message = format.format(message)
3093 logger.console(message, newline=
is_falsy(no_newline), stream=stream)
3095 @run_keyword_variant(resolve=0)
3119 except DataError
as err:
3122 self.
loglog(
'Log level changed from %s to %s.' % (old, level.upper()))
3136 self.
loglog(
'Reloaded library %s with %s keywords.' % (library.name,
3139 @run_keyword_variant(resolve=0)
3167 except DataError
as err:
3172 return args[:-2], args[-1]
3175 @run_keyword_variant(resolve=0)
3197 except DataError
as err:
3200 @run_keyword_variant(resolve=0)
3220 except DataError
as err:
3278 except DataError
as error:
3280 if isinstance(runner, UserErrorHandler):
3415 def evaluate(self, expression, modules=None, namespace=None):
3419 except DataError
as err:
3443 method = getattr(object, method_name)
3444 except AttributeError:
3445 raise RuntimeError(f
"{type(object).__name__} object does not have "
3446 f
"method '{method_name}'.")
3448 return method(*args, **kwargs)
3449 except Exception
as err:
3451 raise RuntimeError(f
"Calling method '{method_name}' failed: {msg}")
from err
3465 if len(patterns) == 0:
3467 if len(patterns) == 1:
3468 return re.escape(patterns[0])
3469 return [re.escape(p)
for p
in patterns]
3496 raise RuntimeError(
"'Set Test Message' keyword cannot be used in "
3497 "suite setup or teardown.")
3498 test.message = self.
_get_new_text_get_new_text(test.message, message,
3499 append, handle_html=
True)
3503 self.
loglog(
'Set test message to:\n%s' % message, level)
3511 if new.startswith(
'*HTML*'):
3512 new = new[6:].lstrip()
3513 if not old.startswith(
'*HTML*'):
3515 elif old.startswith(
'*HTML*'):
3517 return '%s %s' % (old, new)
3520 if message.startswith(
'*HTML*'):
3521 return message[6:].lstrip(),
'HTML'
3522 return message,
'INFO'
3537 raise RuntimeError(
"'Set Test Documentation' keyword cannot be "
3538 "used in suite setup or teardown.")
3539 test.doc = self.
_get_new_text_get_new_text(test.doc, doc, append)
3541 self.
loglog(
'Set test documentation to:\n%s' % test.doc)
3559 suite.doc = self.
_get_new_text_get_new_text(suite.doc, doc, append)
3561 self.
loglog(
'Set suite documentation to:\n%s' % suite.doc)
3580 metadata = self.
_get_context_get_context(top).suite.metadata
3581 original = metadata.get(name,
'')
3582 metadata[name] = self.
_get_new_text_get_new_text(original, value, append)
3584 self.
loglog(
"Set suite metadata '%s' to value '%s'." % (name, metadata[name]))
3603 ctx.test.tags.add(tags)
3604 ctx.variables.set_test(
'@{TEST_TAGS}', list(ctx.test.tags))
3605 elif not ctx.in_suite_teardown:
3606 ctx.suite.set_tags(tags, persist=
True)
3608 raise RuntimeError(
"'Set Tags' cannot be used in suite teardown.")
3609 self.
loglog(
'Set tag%s %s.' % (s(tags),
seq2str(tags)))
3631 ctx.test.tags.remove(tags)
3632 ctx.variables.set_test(
'@{TEST_TAGS}', list(ctx.test.tags))
3633 elif not ctx.in_suite_teardown:
3634 ctx.suite.set_tags(remove=tags, persist=
True)
3636 raise RuntimeError(
"'Remove Tags' cannot be used in suite teardown.")
3637 self.
loglog(
'Removed tag%s %s.' % (s(tags),
seq2str(tags)))
3670 except DataError
as err:
3945 ROBOT_LIBRARY_SCOPE =
'GLOBAL'
4017 RUN_KW_REGISTER.register_run_keyword(library, keyword, args_to_process,
4018 deprecation_warning)
Mark the executed test or task skipped.
Used by CONTINUE statement.
Used by 'Pass Execution' keyword.
Used by 'RETURN' statement.
An always available standard library with often needed keywords.
Used when something cannot be done because Robot is not running.
def _is_true(self, condition)
def _get_context(self, top=False)
def _log_types(self, *args)
def _matches(self, string, pattern, caseless=False)
def _log_types_at_level(self, level, *args)
def return_from_keyword(self, *return_values)
Returns from the enclosing user keyword.
def pass_execution(self, message, *tags)
Skips rest of the current test, setup, or teardown with PASS status.
def continue_for_loop_if(self, condition)
Skips the current FOR loop iteration if the condition is true.
def skip(self, msg='Skipped with Skip keyword.')
Skips the rest of the current test.
def return_from_keyword_if(self, condition, *return_values)
Returns from the enclosing user keyword if condition is true.
def exit_for_loop_if(self, condition)
Stops executing the enclosing FOR loop if the condition is true.
def run_keyword_and_return_if(self, condition, name, *args)
Runs the specified keyword and returns from the enclosing user keyword.
def run_keyword_and_return(self, name, *args)
Runs the specified keyword and returns from the enclosing user keyword.
def exit_for_loop(self)
Stops executing the enclosing FOR loop.
def skip_if(self, condition, msg=None)
Skips the rest of the current test if the condition is True.
def _return_from_keyword(self, return_values=None, failures=None)
def continue_for_loop(self)
Skips the current FOR loop iteration and continues from the next.
def pass_execution_if(self, condition, message, *tags)
Conditionally skips rest of the current test, setup, or teardown with PASS status.
def _get_ordinals_from_text(self, input)
def _get_ordinals_from_hex(self, input)
def convert_to_octal(self, item, base=None, prefix=None, length=None)
Converts the given item to an octal string.
def create_list(self, *items)
Returns a list containing given items.
def convert_to_string(self, item)
Converts the given item to a Unicode string.
def convert_to_bytes(self, input, input_type='text')
Converts the given input to bytes according to the input_type.
def convert_to_integer(self, item, base=None)
Converts the given item to an integer number.
def _test_ordinal(self, ordinal, original, type)
def convert_to_number(self, item, precision=None)
Converts the given item to a floating point number.
def _get_ordinals_from_int(self, input)
def convert_to_boolean(self, item)
Converts the given item to Boolean true or false.
def _input_to_tokens(self, input, length)
def _convert_to_number(self, item, precision=None)
def convert_to_hex(self, item, base=None, prefix=None, length=None, lowercase=False)
Converts the given item to a hexadecimal string.
def _get_base(self, item, base)
def create_dictionary(self, *items)
Creates and returns a dictionary based on the given items.
def convert_to_binary(self, item, base=None, prefix=None, length=None)
Converts the given item to a binary string.
def _convert_to_number_without_precision(self, item)
def _convert_to_integer(self, orig, base=None)
def _get_ordinals_from_bin(self, input)
def _format_separate_dict_items(self, separate)
def _split_dict_items(self, items)
def _convert_to_bin_oct_hex(self, item, base, prefix, length, format_spec)
def set_suite_documentation(self, doc, append=False, top=False)
Sets documentation for the current test suite.
def _get_new_text(self, old, new, append, handle_html=False)
def get_library_instance(self, name=None, all=False)
Returns the currently active instance of the specified library.
def _yield_logged_messages(self, messages)
def log(self, message, level='INFO', html=False, console=False, repr='DEPRECATED', formatter='str')
Logs the given message with the given level.
def comment(self, *messages)
Displays the given messages in the log file as keyword arguments.
def _get_formatter(self, formatter)
def set_suite_metadata(self, name, value, append=False, top=False)
Sets metadata for the current test suite.
def remove_tags(self, *tags)
Removes given tags from the current test or all tests in a suite.
def regexp_escape(self, *patterns)
Returns each argument string escaped for use as a regular expression.
def set_tags(self, *tags)
Adds given tags for the current test or all tests in a suite.
def get_time(self, format='timestamp', time_='NOW')
Returns the given time in the requested format.
def keyword_should_exist(self, name, msg=None)
Fails unless the given keyword exists in the current scope.
def set_test_documentation(self, doc, append=False)
Sets documentation for the current test case.
def sleep(self, time_, reason=None)
Pauses the test executed for the given time.
def log_to_console(self, message, stream='STDOUT', no_newline=False, format='')
Logs the given message to the console.
def import_variables(self, path, *args)
Imports a variable file with the given path and optional arguments.
def import_library(self, name, *args)
Imports a library with the given name and optional arguments.
def _get_logged_test_message_and_level(self, message)
def log_many(self, *messages)
Logs the given messages as separate entries using the INFO level.
def set_test_message(self, message, append=False)
Sets message for the current test case.
def set_library_search_order(self, *search_order)
Sets the resolution order to use when a name matches multiple keywords.
def set_log_level(self, level)
Sets the log threshold to the specified level and returns the old level.
def _sleep_in_parts(self, seconds)
def import_resource(self, path)
Imports a resource file with the given path.
def _split_alias(self, args)
def evaluate(self, expression, modules=None, namespace=None)
Evaluates the given expression in Python and returns the result.
def reload_library(self, name_or_instance)
Rechecks what keywords the specified library provides.
def no_operation(self)
Does absolutely nothing.
def call_method(self, object, method_name, *args, **kwargs)
Calls the named method of the given object with the provided arguments.
def catenate(self, *items)
Catenates the given items together and returns the resulted string.
def run_keyword_and_expect_error(self, expected_error, name, *args)
Runs the keyword and checks that the expected error occurred.
def run_keywords(self, *keywords)
Executes all the given keywords in a sequence.
def run_keyword_and_continue_on_failure(self, name, *args)
Runs the keyword and continues execution even if a failure occurs.
def _get_suite_in_teardown(self, kwname)
def _split_elif_or_else_branch(self, args)
def repeat_keyword(self, repeat, name, *args)
Executes the specified keyword multiple times.
def run_keyword_if_timeout_occurred(self, name, *args)
Runs the given keyword if either a test or a keyword timeout has occurred.
def _replace_variables_in_name(self, name_and_args)
def wait_until_keyword_succeeds(self, retry, retry_interval, name, *args)
Runs the specified keyword and retries if it fails.
def _split_run_keywords_without_and(self, keywords)
def set_variable_if(self, condition, *values)
Sets variable based on the given condition.
def run_keyword_and_return_status(self, name, *args)
Runs the given keyword with given arguments and returns the status as a Boolean value.
def run_keyword_if_test_passed(self, name, *args)
Runs the given keyword with the given arguments, if the test passed.
def run_keyword(self, name, *args)
Executes the given keyword with the given arguments.
def run_keyword_and_warn_on_failure(self, name, *args)
Runs the specified keyword logs a warning if the keyword fails.
def _get_repeat_timeout(self, timestr)
def _split_run_keywords_with_and(self, keywords)
def _verify_values_for_set_variable_if(self, values, default=False)
def _split_branch(self, args, control_word, required, required_error)
def _keywords_repeated_by_timeout(self, timeout, name, args)
def _error_is_expected(self, error, expected_error)
def run_keyword_if_test_failed(self, name, *args)
Runs the given keyword with the given arguments, if the test failed.
def _split_run_keywords(self, keywords)
def run_keyword_if_all_tests_passed(self, name, *args)
Runs the given keyword with the given arguments, if all tests passed.
def run_keyword_unless(self, condition, name, *args)
DEPRECATED since RF 5.0.
def _get_test_in_teardown(self, kwname)
def run_keyword_if_any_tests_failed(self, name, *args)
Runs the given keyword with the given arguments, if one or more tests failed.
def run_keyword_and_ignore_error(self, name, *args)
Runs the given keyword with the given arguments and ignores possible error.
def _run_keywords(self, iterable)
def _accepts_embedded_arguments(self, name)
def _get_repeat_count(self, times, require_postfix=False)
def _keywords_repeated_by_count(self, count, name, args)
def run_keyword_if(self, condition, name, *args)
Runs the given keyword with the given arguments, if condition is true.
def variable_should_exist(self, name, msg=None)
Fails unless the given variable exists within the current scope.
def set_local_variable(self, name, *values)
Makes a variable available everywhere within the local scope.
def get_variable_value(self, name, default=None)
Returns variable value or default if the variable does not exist.
def set_test_variable(self, name, *values)
Makes a variable available everywhere within the scope of the current test.
def log_variables(self, level='INFO')
Logs all variables in the current scope with given log level.
def _get_logged_variable(self, name, variables)
def set_task_variable(self, name, *values)
Makes a variable available everywhere within the scope of the current task.
def get_variables(self, no_decoration=False)
Returns a dictionary containing all variables in the current scope.
def replace_variables(self, text)
Replaces variables in the given text with their current values.
def set_global_variable(self, name, *values)
Makes a variable available globally in all tests and suites.
def variable_should_not_exist(self, name, msg=None)
Fails if the given variable exists within the current scope.
def _resolve_var_name(self, name)
def set_suite_variable(self, name, *values)
Makes a variable available everywhere within the scope of the current suite.
def _get_var_value(self, name, values)
def _log_set_variable(self, name, value)
def _get_var_name(self, original, require_assign=True)
def set_variable(self, *values)
Returns the given values which can then be assigned to a variables.
def should_match(self, string, pattern, msg=None, values=True, ignore_case=False)
Fails if the given string does not match the given pattern.
def length_should_be(self, item, length, msg=None)
Verifies that the length of the given item is correct.
def should_not_be_empty(self, item, msg=None)
Verifies that the given item is not empty.
def get_length(self, item)
Returns and logs the length of the given item as an integer.
def _collapse_spaces(self, value)
def should_not_contain_any(self, container, *items, **configuration)
Fails if container contains one or more of the *items.
def should_contain_x_times(self, container, item, count, msg=None, ignore_case=False, strip_spaces=False, collapse_spaces=False)
Fails if container does not contain item count times.
def fatal_error(self, msg=None)
Stops the whole test execution.
def _get_string_msg(self, item1, item2, custom_message, include_values, delimiter, quote_item1=True, quote_item2=True)
def _get_length(self, item)
def _set_and_remove_tags(self, tags)
def should_not_contain(self, container, item, msg=None, values=True, ignore_case=False, strip_spaces=False, collapse_spaces=False)
Fails if container contains item one or more times.
def should_not_be_equal_as_numbers(self, first, second, msg=None, values=True, precision=6)
Fails if objects are equal after converting them to real numbers.
def _should_be_equal(self, first, second, msg, values, formatter='str')
def get_count(self, container, item)
Returns and logs how many times item is found from container.
def should_be_true(self, condition, msg=None)
Fails if the given condition is not true.
def _include_values(self, values)
def should_start_with(self, str1, str2, msg=None, values=True, ignore_case=False, strip_spaces=False, collapse_spaces=False)
Fails if the string str1 does not start with the string str2.
def should_not_be_true(self, condition, msg=None)
Fails if the given condition is true.
def should_not_be_equal_as_strings(self, first, second, msg=None, values=True, ignore_case=False, strip_spaces=False, collapse_spaces=False)
Fails if objects are equal after converting them to strings.
def _should_not_be_equal(self, first, second, msg, values)
def should_contain_any(self, container, *items, **configuration)
Fails if container does not contain any of the *items.
def should_match_regexp(self, string, pattern, msg=None, values=True, flags=None)
Fails if string does not match pattern as a regular expression.
def should_not_be_equal_as_integers(self, first, second, msg=None, values=True, base=None)
Fails if objects are equal after converting them to integers.
def should_end_with(self, str1, str2, msg=None, values=True, ignore_case=False, strip_spaces=False, collapse_spaces=False)
Fails if the string str1 does not end with the string str2.
def should_not_be_equal(self, first, second, msg=None, values=True, ignore_case=False, strip_spaces=False, collapse_spaces=False)
Fails if the given objects are equal.
def should_not_start_with(self, str1, str2, msg=None, values=True, ignore_case=False, strip_spaces=False, collapse_spaces=False)
Fails if the string str1 starts with the string str2.
def fail(self, msg=None, *tags)
Fails the test with the given message and optionally alters its tags.
def should_be_equal_as_strings(self, first, second, msg=None, values=True, ignore_case=False, strip_spaces=False, formatter='str', collapse_spaces=False)
Fails if objects are unequal after converting them to strings.
def _raise_multi_diff(self, first, second, msg, formatter)
def should_be_empty(self, item, msg=None)
Verifies that the given item is empty.
def _log_types_at_info_if_different(self, first, second)
def _strip_spaces(self, value, strip_spaces)
def should_not_match(self, string, pattern, msg=None, values=True, ignore_case=False)
Fails if the given string matches the given pattern.
def should_be_equal_as_integers(self, first, second, msg=None, values=True, base=None)
Fails if objects are unequal after converting them to integers.
def should_not_end_with(self, str1, str2, msg=None, values=True, ignore_case=False, strip_spaces=False, collapse_spaces=False)
Fails if the string str1 ends with the string str2.
def should_be_equal(self, first, second, msg=None, values=True, ignore_case=False, formatter='str', strip_spaces=False, collapse_spaces=False)
Fails if the given objects are unequal.
def should_be_equal_as_numbers(self, first, second, msg=None, values=True, precision=6)
Fails if objects are unequal after converting them to real numbers.
def should_not_match_regexp(self, string, pattern, msg=None, values=True, flags=None)
Fails if string matches pattern as a regular expression.
def should_contain(self, container, item, msg=None, values=True, ignore_case=False, strip_spaces=False, collapse_spaces=False)
Fails if container does not contain item one or more times.
def register_run_keyword(library, keyword, args_to_process=0, deprecation_warning=True)
Tell Robot Framework that this keyword runs other keywords internally.
def run_keyword_variant(resolve, dry_run=False)
def assert_not_equal(first, second, msg=None, values=True, formatter=safe_str)
Fail if given objects are equal as determined by the '==' operator.
def assert_equal(first, second, msg=None, values=True, formatter=safe_str)
Fail if given objects are unequal as determined by the '==' operator.
def get_error_message()
Returns error message of the last occurred exception.
def split_from_equals(string)
def html_escape(text, linkify=True)
def seq2str(sequence, quote="'", sep=', ', lastsep=' and ')
Returns sequence in format ‘'item 1’, 'item 2' and 'item 3'`.
def parse_re_flags(flags=None)
def normalize_whitespace(string)
def normalize(string, ignore=(), caseless=True, spaceless=True)
Normalizes given string according to given spec.
def secs_to_timestr(secs, compact=False)
Converts time in seconds to a string representation.
def parse_time(timestr)
Parses the time string and returns its value as seconds since epoch.
def timestr_to_secs(timestr, round_to=3, accept_plain_values=True)
Parses time strings like '1h 10s', '01:00:10' and '42' and returns seconds.
def is_truthy(item)
Returns True or False depending on is the item considered true or not.
def is_falsy(item)
Opposite of :func:is_truthy.
def format_assign_message(variable, value, cut_long=True)
def evaluate_expression(expression, variable_store, modules=None, namespace=None)
def is_list_variable(string)
def search_variable(string, identifiers='$@&% *', ignore_errors=False)
def is_dict_variable(string)
def VariableTableValue(value, name, error_reporter=None)
def get_version(naked=False)