from functools import wraps
from typing import Any, Callable, TypeVar
from allure_commons._core import plugin_manager
from allure_commons.types import LabelType, LinkType, ParameterMode
from allure_commons.utils import uuid4
from allure_commons.utils import func_parameters, represent
_TFunc = TypeVar("_TFunc", bound=Callable[..., Any])
def safely(result):
if result:
return result[0]
else:
def dummy(function):
return function
return dummy
def title(test_title):
return safely(plugin_manager.hook.decorate_as_title(test_title=test_title))
def description(test_description):
return safely(plugin_manager.hook.decorate_as_description(test_description=test_description))
def description_html(test_description_html):
return safely(plugin_manager.hook.decorate_as_description_html(test_description_html=test_description_html))
def label(label_type, *labels):
return safely(plugin_manager.hook.decorate_as_label(label_type=label_type, labels=labels))
def severity(severity_level):
return label(LabelType.SEVERITY, severity_level)
def epic(*epics):
return label(LabelType.EPIC, *epics)
def feature(*features):
return label(LabelType.FEATURE, *features)
def story(*stories):
return label(LabelType.STORY, *stories)
def suite(suite_name):
return label(LabelType.SUITE, suite_name)
def parent_suite(parent_suite_name):
return label(LabelType.PARENT_SUITE, parent_suite_name)
def sub_suite(sub_suite_name):
return label(LabelType.SUB_SUITE, sub_suite_name)
def tag(*tags):
return label(LabelType.TAG, *tags)
def id(id): # noqa: A001,A002
return label(LabelType.ID, id)
def manual(fn):
return label(LabelType.MANUAL, True)(fn)
def link(url, link_type=LinkType.LINK, name=None):
return safely(plugin_manager.hook.decorate_as_link(url=url, link_type=link_type, name=name))
def issue(url, name=None):
return link(url, link_type=LinkType.ISSUE, name=name)
def testcase(url, name=None):
return link(url, link_type=LinkType.TEST_CASE, name=name)
class Dynamic:
@staticmethod
def title(test_title):
plugin_manager.hook.add_title(test_title=test_title)
@staticmethod
def description(test_description):
plugin_manager.hook.add_description(test_description=test_description)
@staticmethod
def description_html(test_description_html):
plugin_manager.hook.add_description_html(test_description_html=test_description_html)
@staticmethod
def label(label_type, *labels):
plugin_manager.hook.add_label(label_type=label_type, labels=labels)
@staticmethod
def severity(severity_level):
Dynamic.label(LabelType.SEVERITY, severity_level)
@staticmethod
def epic(*epics):
Dynamic.label(LabelType.EPIC, *epics)
@staticmethod
def feature(*features):
Dynamic.label(LabelType.FEATURE, *features)
@staticmethod
def story(*stories):
Dynamic.label(LabelType.STORY, *stories)
@staticmethod
def tag(*tags):
Dynamic.label(LabelType.TAG, *tags)
@staticmethod
def id(id): # noqa: A003,A002
Dynamic.label(LabelType.ID, id)
@staticmethod
def link(url, link_type=LinkType.LINK, name=None):
plugin_manager.hook.add_link(url=url, link_type=link_type, name=name)
@staticmethod
def parameter(name, value, excluded=None, mode: ParameterMode = None):
plugin_manager.hook.add_parameter(name=name, value=value, excluded=excluded, mode=mode)
@staticmethod
def issue(url, name=None):
Dynamic.link(url, link_type=LinkType.ISSUE, name=name)
@staticmethod
def testcase(url, name=None):
Dynamic.link(url, link_type=LinkType.TEST_CASE, name=name)
@staticmethod
def suite(suite_name):
Dynamic.label(LabelType.SUITE, suite_name)
@staticmethod
def parent_suite(parent_suite_name):
Dynamic.label(LabelType.PARENT_SUITE, parent_suite_name)
@staticmethod
def sub_suite(sub_suite_name):
Dynamic.label(LabelType.SUB_SUITE, sub_suite_name)
@staticmethod
def manual():
return Dynamic.label(LabelType.MANUAL, True)
def step(title):
if callable(title):
return StepContext(title.__name__, {})(title)
else:
return StepContext(title, {})
class StepContext:
def __init__(self, title, params):
self.title = title
self.params = params
self.uuid = uuid4()
def __enter__(self):
plugin_manager.hook.start_step(uuid=self.uuid, title=self.title, params=self.params)
def __exit__(self, exc_type, exc_val, exc_tb):
plugin_manager.hook.stop_step(uuid=self.uuid, title=self.title, exc_type=exc_type, exc_val=exc_val,
exc_tb=exc_tb)
def __call__(self, func: _TFunc) -> _TFunc:
@wraps(func)
def impl(*a, **kw):
__tracebackhide__ = True
params = func_parameters(func, *a, **kw)
args = list(map(lambda x: represent(x), a))
with StepContext(self.title.format(*args, **params), params):
return func(*a, **kw)
return impl
class Attach:
def __call__(self, body, name=None, attachment_type=None, extension=None):
plugin_manager.hook.attach_data(body=body, name=name, attachment_type=attachment_type, extension=extension)
def file(self, source, name=None, attachment_type=None, extension=None):
plugin_manager.hook.attach_file(source=source, name=name, attachment_type=attachment_type, extension=extension)
attach = Attach()
class fixture:
def __init__(self, fixture_function, parent_uuid=None, name=None):
self._fixture_function = fixture_function
self._parent_uuid = parent_uuid
self._name = name if name else fixture_function.__name__
self._uuid = uuid4()
self.parameters = None
def __call__(self, *args, **kwargs):
self.parameters = func_parameters(self._fixture_function, *args, **kwargs)
with self:
return self._fixture_function(*args, **kwargs)
def __enter__(self):
plugin_manager.hook.start_fixture(parent_uuid=self._parent_uuid,
uuid=self._uuid,
name=self._name,
parameters=self.parameters)
def __exit__(self, exc_type, exc_val, exc_tb):
plugin_manager.hook.stop_fixture(parent_uuid=self._parent_uuid,
uuid=self._uuid,
name=self._name,
exc_type=exc_type,
exc_val=exc_val,
exc_tb=exc_tb)
class test:
def __init__(self, _test, context):
self._test = _test
self._uuid = uuid4()
self.context = context
self.parameters = None
def __call__(self, *args, **kwargs):
self.parameters = func_parameters(self._test, *args, **kwargs)
with self:
return self._test(*args, **kwargs)
def __enter__(self):
plugin_manager.hook.start_test(parent_uuid=None,
uuid=self._uuid,
name=None,
parameters=self.parameters,
context=self.context)
def __exit__(self, exc_type, exc_val, exc_tb):
plugin_manager.hook.stop_test(parent_uuid=None,
uuid=self._uuid,
name=None,
context=self.context,
exc_type=exc_type,
exc_val=exc_val,
exc_tb=exc_tb)