def start_keyword(self, kw): attrs = {'name': kw.kwname, 'library': kw.libname} if kw.type != 'kw': attrs['type'] = kw.type self._writer.start('kw', attrs) self._write_list('tags', 'tag', [unic(t) for t in kw.tags]) self._writer.element('doc', kw.doc) self._write_list('arguments', 'arg', [unic(a) for a in kw.args]) self._write_list('assign', 'var', kw.assign)
def __init__(self, result): if not (is_dict_like(result) and 'status' in result): raise RuntimeError('Invalid remote result dictionary: %s' % result) self.status = result['status'] self.output = unic(self._get(result, 'output')) self.return_ = self._get(result, 'return') self.error = unic(self._get(result, 'error')) self.traceback = unic(self._get(result, 'traceback')) self.fatal = bool(self._get(result, 'fatal', False)) self.continuable = bool(self._get(result, 'continuable', False))
def dictionary_should_contain_item(self, dictionary, key, value, msg=None): """An item of ``key`` / ``value`` must be found in a ``dictionary``. Value is converted to unicode for comparison. Use the ``msg`` argument to override the default error message. """ self._validate_dictionary(dictionary) self.dictionary_should_contain_key(dictionary, key, msg) actual, expected = unic(dictionary[key]), unic(value) default = "Value of dictionary key '%s' does not match: %s != %s" % ( key, actual, expected) _verify_condition(actual == expected, default, msg)
def dictionary_should_contain_item(self, dictionary, key, value, msg=None): """An item of ``key`` / ``value`` must be found in a ``dictionary``. Value is converted to unicode for comparison. See `Lists Should Be Equal` for an explanation of ``msg``. The given dictionary is never altered by this keyword. """ self._validate_dictionary(dictionary) self.dictionary_should_contain_key(dictionary, key, msg) actual, expected = unic(dictionary[key]), unic(value) default = "Value of dictionary key '%s' does not match: %s != %s" % (key, actual, expected) _verify_condition(actual == expected, default, msg)
def _keys_should_be_equal(self, dict1, dict2, msg, values): keys1 = self.get_dictionary_keys(dict1) keys2 = self.get_dictionary_keys(dict2) miss1 = [unic(k) for k in keys2 if k not in dict1] miss2 = [unic(k) for k in keys1 if k not in dict2] error = [] if miss1: error += ['Following keys missing from first dictionary: %s' % ', '.join(miss1)] if miss2: error += ['Following keys missing from second dictionary: %s' % ', '.join(miss2)] _verify_condition(not error, '\n'.join(error), msg, values) return keys1
def dictionary_should_contain_item(self, dictionary, key, value, msg=None): """An item of ``key`` / ``value`` must be found in a ``dictionary``. Value is converted to unicode for comparison. See `Lists Should Be Equal` for an explanation of ``msg``. The given dictionary is never altered by this keyword. """ self._validate_dictionary(dictionary) self.dictionary_should_contain_key(dictionary, key, msg) actual, expected = unic(dictionary[key]), unic(value) default = "Value of dictionary key '%s' does not match: %s != %s" % ( key, actual, expected) _verify_condition(actual == expected, default, msg)
def _list_dir(self, dir_path, incl_extensions, incl_suites): # os.listdir returns Unicode entries when path is Unicode dir_path = unic(dir_path) names = os.listdir(dir_path) for name in sorted(names, key=lambda item: item.lower()): name = unic(name) # needed to handle nfc/nfd normalization on OSX path = os.path.join(dir_path, name) base, ext = os.path.splitext(name) ext = ext[1:].lower() if self._is_init_file(path, base, ext, incl_extensions): yield path, True elif self._is_included(path, base, ext, incl_extensions, incl_suites): yield path, False else: LOGGER.info("Ignoring file or directory '%s'." % path)
def _yield_list_diffs(self, list1, list2, names): for index, (item1, item2) in enumerate(zip(list1, list2)): name = ' (%s)' % names[index] if index in names else '' try: assert_equal(item1, item2, msg='Index %d%s' % (index, name)) except AssertionError as err: yield unic(err)
def console(msg, newline=True, stream='stdout'): msg = unic(msg) if newline: msg += '\n' stream = sys.__stdout__ if stream.lower() != 'stderr' else sys.__stderr__ stream.write(console_encode(msg, stream=stream)) stream.flush()
def console(msg, newline=True, stream='stdout'): msg = unic(msg) if newline: msg += '\n' stream = sys.__stdout__ if stream.lower() != 'stderr' else sys.__stderr__ stream.write(encode_output(msg)) stream.flush()
def main(self, datasources, **options): settings = RobotSettings(options) LOGGER.register_console_logger(**settings.console_output_config) LOGGER.info('Settings:\n%s' % unic(settings)) builder = TestSuiteBuilder(settings['SuiteNames'], extension=settings.extension, rpa=settings.rpa) suite = builder.build(*datasources) settings.rpa = builder.rpa suite.configure(**settings.suite_config) if settings.pre_run_modifiers: suite.visit(ModelModifier(settings.pre_run_modifiers, settings.run_empty_suite, LOGGER)) with pyloggingconf.robot_handler_enabled(settings.log_level): old_max_error_lines = text.MAX_ERROR_LINES text.MAX_ERROR_LINES = settings.max_error_lines try: result = suite.run(settings) finally: text.MAX_ERROR_LINES = old_max_error_lines LOGGER.info("Tests execution ended. Statistics:\n%s" % result.suite.stat_message) if settings.log or settings.report or settings.xunit: writer = ResultWriter(settings.output if settings.log else result) writer.write_results(settings.get_rebot_settings()) return result.return_code
def main(self, datasources, **options): settings = RobotSettings(options) LOGGER.register_console_logger(**settings.console_output_config) LOGGER.info('Settings:\n%s' % unic(settings)) builder = TestSuiteBuilder(settings['SuiteNames'], extension=settings.extension, rpa=settings.rpa) suite = builder.build(*datasources) settings.rpa = builder.rpa suite.configure(**settings.suite_config) if settings.pre_run_modifiers: suite.visit( ModelModifier(settings.pre_run_modifiers, settings.run_empty_suite, LOGGER)) with pyloggingconf.robot_handler_enabled(settings.log_level): old_max_error_lines = text.MAX_ERROR_LINES text.MAX_ERROR_LINES = settings.max_error_lines try: result = suite.run(settings) finally: text.MAX_ERROR_LINES = old_max_error_lines LOGGER.info("Tests execution ended. Statistics:\n%s" % result.suite.stat_message) if settings.log or settings.report or settings.xunit: writer = ResultWriter( settings.output if settings.log else result) writer.write_results(settings.get_rebot_settings()) return result.return_code
def replace_string(self, string, ignore_errors=False): """Replaces variables from a string. Result is always a string.""" if not is_string(string): return unic(string) if self._cannot_have_variables(string): return unescape(string) return self._replace_string(string, ignore_errors=ignore_errors)
def end_test(self, test): self._writer.element('doc', test.doc) self._write_list('tags', 'tag', test.tags) if test.timeout: self._writer.element('timeout', attrs={'value': unic(test.timeout)}) self._write_status(test, {'critical': 'yes' if test.critical else 'no'}) self._writer.end('test')
def keyword_teardown(self, error): self.variables.set_keyword('${KEYWORD_STATUS}', 'FAIL' if error else 'PASS') self.variables.set_keyword('${KEYWORD_MESSAGE}', unic(error or '')) self.in_keyword_teardown += 1 try: yield finally: self.in_keyword_teardown -= 1
def _normalize_message(self, msg): if callable(msg): return msg if not is_unicode(msg): msg = unic(msg) if '\r\n' in msg: msg = msg.replace('\r\n', '\n') return msg
def _get_message(self, record): try: return record.getMessage(), None except: message = 'Failed to log following message properly: %s' \ % utils.unic(record.msg) error = '\n'.join(utils.get_error_details()) return message, error
def _get_message(self, record): try: return record.getMessage(), None except: message = 'Failed to log following message properly: %s' \ % unic(record.msg) error = '\n'.join(get_error_details()) return message, error
def _keys_should_be_equal(self, dict1, dict2, msg, values): keys1 = self.get_dictionary_keys(dict1) keys2 = self.get_dictionary_keys(dict2) miss1 = [unic(k) for k in keys2 if k not in dict1] miss2 = [unic(k) for k in keys1 if k not in dict2] error = [] if miss1: error += [ 'Following keys missing from first dictionary: %s' % ', '.join(miss1) ] if miss2: error += [ 'Following keys missing from second dictionary: %s' % ', '.join(miss2) ] _verify_condition(not error, '\n'.join(error), msg, values) return keys1
def write(msg, level, html=False): # Callable messages allow lazy logging internally, but we don't want to # expose this functionality publicly. See the following issue for details: # https://github.com/robotframework/robotframework/issues/1505 if callable(msg): msg = unic(msg) if level.upper() not in ('TRACE', 'DEBUG', 'INFO', 'HTML', 'WARN', 'ERROR'): raise DataError("Invalid log level '%s'." % level) if threading.currentThread().getName() in LOGGING_THREADS: LOGGER.log_message(Message(msg, level, html))
def _single_result(source, options): ets = ETSource(source) result = Result(source, rpa=options.pop('rpa', None)) try: return ExecutionResultBuilder(ets, **options).build(result) except IOError as err: error = err.strerror except: error = get_error_message() raise DataError("Reading XML source '%s' failed: %s" % (unic(ets), error))
def _build_keyword(self, target, data): kw = target.keywords.create(name=data.name, args=tuple(data.args), doc=unic(data.doc), tags=tuple(data.tags), return_=tuple(data.return_), timeout=self._get_timeout(data.timeout)) self._build_steps(kw, data) if data.teardown.is_active(): self._build_step(kw, data.teardown, kw_type='teardown')
def _replace_variables(self, values, variables): separator, values = values if (separator is None and len(values) == 1 and not VariableSplitter(values[0]).is_list_variable()): return variables.replace_scalar(values[0]) if separator is None: separator = ' ' separator = variables.replace_string(separator) values = variables.replace_list(values) return separator.join(unic(item) for item in values)
def write(msg, level, html=False): # Callable messages allow lazy logging internally, but we don't want to # expose this functionality publicly. See the following issue for details: # http://code.google.com/p/robotframework/issues/detail?id=1505 if callable(msg): msg = unic(msg) if level.upper() not in ('TRACE', 'DEBUG', 'INFO', 'HTML', 'WARN', 'ERROR'): raise DataError("Invalid log level '%s'." % level) if threading.currentThread().getName() in LOGGING_THREADS: LOGGER.log_message(Message(msg, level, html))
def _build_test(self, suite, data, defaults): values = defaults.get_test_values(data) template = self._get_template(values.template) test = suite.tests.create(name=data.name, doc=unic(data.doc), tags=values.tags.value, template=template, timeout=self._get_timeout(values.timeout)) self._build_setup(test, values.setup) self._build_steps(test, data, template) self._build_teardown(test, values.teardown)
def __init__(self, library, handler_name, dynamic_method, doc='', argspec=None): self._argspec = argspec _RunnableHandler.__init__(self, library, handler_name, dynamic_method.method, utils.unic(doc or '')) self._run_keyword_method_name = dynamic_method.name self._supports_kwargs = dynamic_method.supports_kwargs if argspec and argspec[-1].startswith('**'): if not self._supports_kwargs: raise DataError("Too few '%s' method parameters for **kwargs " "support." % self._run_keyword_method_name)
def __init__(self, keyword, libname): self.name = keyword.name self.libname = libname self.doc = unic(keyword.doc) self.tags = keyword.tags self.arguments = UserKeywordArgumentParser().parse(tuple(keyword.args), self.longname) self._kw = keyword self.timeout = keyword.timeout self.keywords = keyword.keywords.normal self.return_value = tuple(keyword.return_) self.teardown = keyword.keywords.teardown
def __init__(self, keyword, libname): self.name = keyword.name self.libname = libname self.doc = unic(keyword.doc) self.tags = keyword.tags self.arguments = UserKeywordArgumentParser().parse( tuple(keyword.args), self.longname) self._kw = keyword self.timeout = keyword.timeout self.keywords = keyword.keywords.normal self.return_value = tuple(keyword.return_) self.teardown = keyword.keywords.teardown
def list_should_contain_sub_list(self, list1, list2, msg=None, values=True): """Fails if not all of the elements in ``list2`` are found in ``list1``. The order of values and the number of values are not taken into account. See `Lists Should Be Equal` for more information about configuring the error message with ``msg`` and ``values`` arguments. """ diffs = ', '.join(unic(item) for item in list2 if item not in list1) default = 'Following values were not found from first list: ' + diffs _verify_condition(not diffs, default, msg, values)
def _yield_replaced(self, string, splitter, ignore_errors=False): while splitter.identifier: yield unescape(string[:splitter.start]) try: value = self._get_variable(splitter) except DataError: if not ignore_errors: raise value = string[splitter.start:splitter.end] yield unic(value) string = string[splitter.end:] splitter = VariableSplitter(string) yield unescape(string)
def _write(self, name, writer, path, *args): try: writer(path, *args) except DataError as err: LOGGER.error(err.message) except EnvironmentError as err: # `err.filename` can be different than `path` at least if reading # log/report templates or writing split log fails. # `unic` is needed due to http://bugs.jython.org/issue1825. LOGGER.error("Writing %s file '%s' failed: %s: %s" % (name.lower(), path, err.strerror, unic(err.filename))) else: LOGGER.output_file(name, path)
def dictionary_should_contain_sub_dictionary(self, dict1, dict2, msg=None, values=True): """Fails unless all items in ``dict2`` are found from ``dict1``. See `Lists Should Be Equal` for more information about configuring the error message with ``msg`` and ``values`` arguments. The given dictionaries are never altered by this keyword. """ keys = self.get_dictionary_keys(dict2) diffs = [unic(k) for k in keys if k not in dict1] default = "Following keys missing from first dictionary: %s" \ % ', '.join(diffs) _verify_condition(not diffs, default, msg, values) self._key_values_should_be_equal(keys, dict1, dict2, msg, values)
def end_suite(self, suite): self._suite.message = self._suite_status.message self._context.report_suite_status(self._suite.status, self._suite.full_message) with self._context.suite_teardown(): failure = self._run_teardown(suite.keywords.teardown, self._suite_status) if failure: self._suite.suite_teardown_failed(unic(failure)) if self._suite.statistics.critical.failed: self._suite_status.critical_failure_occurred() self._suite.endtime = get_timestamp() self._suite.message = self._suite_status.message self._context.end_suite(ModelCombiner(suite, self._suite)) self._suite = self._suite.parent self._suite_status = self._suite_status.parent self._output.library_listeners.discard_suite_scope()
def _build_suite(self, data, parent_defaults=None): if self._rpa_not_given and data.testcase_table.is_started(): self._set_execution_mode(data) self._check_deprecated_extensions(data.source) defaults = TestDefaults(data.setting_table, parent_defaults) suite = TestSuite(name=data.name, source=data.source, doc=unic(data.setting_table.doc), metadata=self._get_metadata(data.setting_table)) self._build_setup(suite, data.setting_table.suite_setup) self._build_teardown(suite, data.setting_table.suite_teardown) for test_data in data.testcase_table.tests: self._build_test(suite, test_data, defaults) for child in data.children: suite.suites.append(self._build_suite(child, defaults)) suite.rpa = self.rpa ResourceFileBuilder().build(data, target=suite.resource) return suite
def _get_attr(self, object, attr, default='', upper=False): value = unic(getattr(object, attr, default)) if upper: value = normalize(value, ignore='_').upper() return value
def _trace_log_args(self, positional, named): args = [prepr(arg) for arg in positional] args += ['%s=%s' % (unic(n), prepr(v)) for n, v in named] return 'Arguments: [ %s ]' % ' | '.join(args)
def _fail(self, message, default_template, *items): if not message: message = default_template % tuple(unic(item) for item in items) raise AssertionError(message)
def _get_template(self, template): return unic(template) if template.is_active() else None
def _get_extra_attributes(self, kw): args = [a if is_string(a) else unic(a) for a in kw.args] return {'args': args, 'type': self._types[kw.type]}