def _run_suite_related(self, testsuite, method): """Runs testsuite related special methods setup/teardown/etc.""" attr = getattr(testsuite, method, None) if attr is None: return None elif not callable(attr): raise TypeError("{} expected to be callable.".format(method)) method_report = testplan.report.TestCaseReport(method, uid=method, suite_related=True) case_result = self.cfg.result(stdout_style=self.stdout_style) try: interface.check_signature(attr, ["self", "env", "result"]) method_args = (self.resources, case_result) except interface.MethodSignatureMismatch: interface.check_signature(attr, ["self", "env"]) method_args = (self.resources, ) with method_report.logged_exceptions(): attr(*method_args) method_report.extend(case_result.serialized_entries) method_report.attachments.extend(case_result.attachments) method_report.pass_if_empty() return method_report
def wrapper(klass): """Meta logic for suite goes here.""" if custom_name is None or isinstance(custom_name, six.string_types): pass elif callable(custom_name): try: interface.check_signature( custom_name, ["self", "original_name"] ) except interface.MethodSignatureMismatch as err: _reset_globals() raise err else: _reset_globals() raise TypeError("`custom_name` should be callable or a string") klass.custom_name = custom_name if tags: klass.__tags__ = tagging.validate_tag_value(tags) klass.__tags_index__ = copy.deepcopy(klass.__tags__) else: klass.__tags__ = {} klass.__tags_index__ = {} return _testsuite(klass)
def _validate_testcase(func): """Validate the expected function signature of a testcase.""" try: interface.check_signature(func, ["self", "env", "result"]) if not isinstance(func.name, six.string_types): raise ValueError( 'Testcase name "{name}" must be a string, it is of type:' " {type}".format(name=func.name, type=type(func.name)) ) elif not func.name: raise ValueError("Testcase name cannot be an empty string") except Exception as ex: _reset_globals() raise ex func.name = six.ensure_str(func.name) if len(func.name) > defaults.MAX_TEST_NAME_LENGTH: warnings.warn( 'Name defined for testcase "{}" is too long,' ' consider customizing testcase name with argument "name_func"' " in @testcase decorator.".format(func.__name__) )
def _run_case_related(self, method, testcase, resources, case_result): try: interface.check_signature( method, ["self", "name", "env", "result"] ) method_args = (testcase.name, resources, case_result) except interface.MethodSignatureMismatch: interface.check_signature( method, ["self", "name", "env", "result", "kwargs"] ) method_args = ( testcase.name, resources, case_result, getattr(testcase, "_parametrization_kwargs", {}), ) time_restriction = getattr(method, "timeout", None) if time_restriction: # pylint: disable=unbalanced-tuple-unpacking executed, execution_result = timing.timeout( time_restriction, f"`{method.__name__}` timeout after {{}} second(s)", )(method)(*method_args) if not executed: raise Exception(execution_result) else: method(*method_args)
def _run_suite_related(self, testsuite, method): """Runs testsuite related special methods setup/teardown/etc.""" testsuite_method = getattr(testsuite, method, None) if testsuite_method is None: return None elif not callable(testsuite_method): raise TypeError("{} expected to be callable.".format(method)) method_report = TestCaseReport(name=method, uid=method, suite_related=True) case_result = self.cfg.result(stdout_style=self.stdout_style, _scratch=self._scratch) try: interface.check_signature(testsuite_method, ["self", "env", "result"]) method_args = (self.resources, case_result) except interface.MethodSignatureMismatch: interface.check_signature(testsuite_method, ["self", "env"]) method_args = (self.resources, ) with method_report.timer.record("run"): with method_report.logged_exceptions(): testsuite_method(*method_args) method_report.extend(case_result.serialized_entries) method_report.attachments.extend(case_result.attachments) method_report.pass_if_empty() method_report.runtime_status = RuntimeStatus.FINISHED return method_report
def _validate_skip_if_predicates(predicates): """ Check for method signature, set / extend ``skip_funcs`` attribute of the testcase method. """ for predicate in predicates: interface.check_signature(predicate, ['suite']) return predicates
def _validate_testcase(func): """Validate the expected function signature of a testcase.""" try: interface.check_signature(func, ["self", "env", "result"]) validation.validate_display_name( func.name, defaults.MAX_TESTCASE_NAME_LENGTH, "Testcase name" ) except Exception as ex: _reset_globals() raise ex
def _validate_skip_if_predicates(predicates): """ Check for signature of functions, which are used to set / extend ``skip_funcs`` attribute of the testcase method. """ for predicate in predicates: try: interface.check_signature(predicate, ["testsuite"]) except interface.MethodSignatureMismatch as err: _reset_globals() raise err
def _run_case_related(self, method, testcase, resources, case_result): try: interface.check_signature(method, ["self", "name", "env", "result"]) method(testcase.name, resources, case_result) except interface.MethodSignatureMismatch: interface.check_signature( method, ["self", "name", "env", "result", "kwargs"]) method( testcase.name, resources, case_result, getattr(testcase, "_parametrization_kwargs", {}), )
def _check_tag_func(tag_func): """Make sure ``tag_func`` is a callable that takes ``kwargs`` arguments""" if tag_func is None: return if not callable(tag_func): raise ParametrizationError("tag_func must be a callable or `None`") try: interface.check_signature(tag_func, ["kwargs"]) except interface.MethodSignatureMismatch: raise ParametrizationError( 'tag_func must be a callable that takes 1 argument named "kwargs"' " (e.g. def custom_tag_func(kwargs): ..." )
def _run_suite_related(self, testsuite, method_name): """Runs testsuite related special methods setup/teardown/etc.""" testsuite_method = getattr(testsuite, method_name, None) if testsuite_method is None: return None elif not callable(testsuite_method): raise TypeError("{} expected to be callable.".format(method_name)) method_report = TestCaseReport( name=method_name, uid=method_name, suite_related=True ) case_result = self.cfg.result( stdout_style=self.stdout_style, _scratch=self._scratch ) try: interface.check_signature( testsuite_method, ["self", "env", "result"] ) method_args = (self.resources, case_result) except interface.MethodSignatureMismatch: interface.check_signature(testsuite_method, ["self", "env"]) method_args = (self.resources,) with method_report.timer.record("run"): with method_report.logged_exceptions(): time_restriction = getattr(testsuite_method, "timeout", None) if time_restriction: # pylint: disable=unbalanced-tuple-unpacking executed, execution_result = timing.timeout( time_restriction, f"`{method_name}` timeout after {{}} second(s)", )(testsuite_method)(*method_args) if not executed: method_report.logger.error(execution_result) method_report.status_override = Status.ERROR else: testsuite_method(*method_args) method_report.extend(case_result.serialized_entries) method_report.attachments.extend(case_result.attachments) method_report.pass_if_empty() method_report.runtime_status = RuntimeStatus.FINISHED return method_report
def _run_suite_related(self, object, method, report): """Runs testsuite related special methods setup/teardown/etc.""" attr = getattr(object, method, None) if attr is None: return elif not callable(attr): raise RuntimeError('{} expected to be callable.'.format(method)) try: check_signature(attr, ['self', 'env', 'result']) except MethodSignatureMismatch: check_signature(attr, ['self', 'env']) attr(self.resources) else: method_report = TestCaseReport(method) report.append(method_report) case_result = self.cfg.result(stdout_style=self.stdout_style) attr(self.resources, case_result) method_report.extend(case_result.serialized_entries)
def _check_name_func(name_func): """ Make sure ``name_func`` is ``None`` or a callable that takes ``func_name``, ``kwargs`` arguments. """ if name_func is None: return if not callable(name_func): raise ParametrizationError("name_func must be a callable or `None`") try: interface.check_signature(name_func, ["func_name", "kwargs"]) except interface.MethodSignatureMismatch: raise ParametrizationError( '"name_func" must be a callable that takes 2 arguments' ' named "func_name" and "kwargs"' " (e.g. def custom_name_func(func_name, kwargs): ..." )
def _run_case_related(method): # Does not work if defined as methods in a testsuite. # Needs usage of pre/post_testcase decorators. check_signature(method, ['name', 'self', 'env', 'result']) method(testcase.__name__, self.resources, case_result)
def _run_case_related(self, method, testcase, case_result): interface.check_signature(method, ["self", "name", "env", "result"]) method(testcase.name, self.resources, case_result)
def validate_func(*arg_names): """Validate given function signature.""" return lambda x: callable(x) and check_signature(x, list(arg_names))
def _testsuite(klass): """ Actual decorator that transforms a class into a suite and registers testcases. """ # nasty, but smallest possible evil that has to be perpetrated in order # to preserve the order of definition of the testcases and make sure # they get executed in the same order _ensure_unique_generated_testcase_names( __TESTCASES__ + __PARAMETRIZATION_TEMPLATE__, __GENERATED_TESTCASES__) klass.__testcases__ = [None] * _number_of_testcases() klass.__skip__ = __SKIP__ for testcase_name in __TESTCASES__: klass.__testcases__[getattr( klass, testcase_name).__seq_number__] = testcase_name for func in __GENERATED_TESTCASES__: klass.__testcases__[func.__seq_number__] = func.__name__ setattr(klass, func.__name__, func) assert all(testcase for testcase in klass.__testcases__) # Attributes `name` and `__tags__` are added only when class is # decorated by @testsuite(...) which has the following parentheses. if not hasattr(klass, "name"): klass.name = None if callable(klass.name): try: interface.check_signature(klass.name, ["cls_name", "suite"]) except interface.MethodSignatureMismatch as err: _reset_globals() raise err elif not (klass.name is None or isinstance(klass.name, six.string_types)): _reset_globals() raise TypeError('"name" should be a string or a callable or `None`') if not hasattr(klass, "__tags__"): klass.__tags__ = {} # used for UI klass.__tags_index__ = {} # used for actual filtering klass.get_testcases = get_testcase_methods testcase_methods = get_testcase_methods(klass) # propagate suite's native tags onto itself, which # will propagate them further to the suite's testcases propagate_tag_indices(klass, klass.__tags__) # Collect tag indices from testcase methods and update suite's tag index. update_tag_index( obj=klass, tag_dict=tagging.merge_tag_dicts( *[tc.__tags_index__ for tc in testcase_methods]), ) # Suite resolved, clear global variables for resolving the next suite. _reset_globals() return klass
def _validate_testcase(func): """Validate the expected function signature of a testcase.""" interface.check_signature(func, ["self", "env", "result"])
def _validate_testcase(func): """Validate the expected function signature of a testcase.""" interface.check_signature(func, ['self', 'env', 'result'])
def validate_func(args_list): """Validate given function signature.""" return lambda x: callable(x) and check_signature(x, args_list)