diff --git a/allure-python-commons/src/mapping.py b/allure-python-commons/src/mapping.py index 2a80fd23..311be1a8 100644 --- a/allure-python-commons/src/mapping.py +++ b/allure-python-commons/src/mapping.py @@ -1,6 +1,6 @@ from itertools import chain, islice import attr - +import re from allure_commons.types import Severity, LabelType, LinkType from allure_commons.types import ALLURE_UNIQUE_LABELS from allure_commons.model2 import Label, Link @@ -8,6 +8,16 @@ TAG_PREFIX = "allure" +semi_sep = re.compile(r"allure[\.\w]+:") +eq_sep = re.compile(r"allure[\.\w]+=") + + +def allure_tag_sep(tag): + if semi_sep.search(tag): + return ":" + if eq_sep.search(tag): + return "=" + def __is(kind, t): return kind in [v for k, v in t.__dict__.items() if not k.startswith('__')] @@ -39,7 +49,8 @@ def parse_tag(tag, issue_pattern=None, link_pattern=None): >>> parse_tag("allure.foo:1") Label(name='tag', value='allure.foo:1') """ - schema, value = islice(chain(tag.split(':', 1), [None]), 2) + sep = allure_tag_sep(tag) + schema, value = islice(chain(tag.split(sep, 1), [None]), 2) prefix, kind, name = islice(chain(schema.split('.'), [None], [None]), 3) if tag in [severity for severity in Severity]: @@ -57,6 +68,9 @@ def parse_tag(tag, issue_pattern=None, link_pattern=None): if __is(kind, LabelType): return Label(name=kind, value=value) + if kind == "id": + return Label(name=LabelType.ID, value=value) + if kind == "label" and name is not None: return Label(name=name, value=value) diff --git a/allure-robotframework/examples/label/__init__.rst b/allure-robotframework/examples/label/__init__.rst index 5f76f33a..334faa45 100644 --- a/allure-robotframework/examples/label/__init__.rst +++ b/allure-robotframework/examples/label/__init__.rst @@ -2,4 +2,4 @@ .. code:: robotframework *** Settings *** - Force Tags epic:Tag + Force Tags allure.epic:Tag diff --git a/allure-robotframework/examples/label/testcase_bdd_label.rst b/allure-robotframework/examples/label/testcase_bdd_label.rst index cc274cb9..f08ac8fa 100644 --- a/allure-robotframework/examples/label/testcase_bdd_label.rst +++ b/allure-robotframework/examples/label/testcase_bdd_label.rst @@ -2,9 +2,9 @@ .. code:: robotframework *** Settings *** - Force Tags feature:Label + Force Tags allure.feature:Label *** Test Case *** Test Cases With BDD Labels - [Tags] story:Test case BDD labels + [Tags] allure.story:Test case BDD labels No Operation diff --git a/allure-robotframework/examples/testplan/testplan.rst b/allure-robotframework/examples/testplan/testplan.rst new file mode 100644 index 00000000..404d171d --- /dev/null +++ b/allure-robotframework/examples/testplan/testplan.rst @@ -0,0 +1,21 @@ + +.. code:: robotframework + + *** Test Cases *** + First testcase + No Operation + + Second testcase + No Operation + + +.. code:: robotframework + + *** Test Cases *** + Test case with allure id + [Tags] allure.id=123 + No Operation + + One more case with allure id + [Tags] allure.id=777 + No Operation diff --git a/allure-robotframework/src/listener/__init__.py b/allure-robotframework/src/listener/__init__.py index 24ef9b55..d2640a4e 100644 --- a/allure-robotframework/src/listener/__init__.py +++ b/allure-robotframework/src/listener/__init__.py @@ -1,3 +1,4 @@ from allure_robotframework.robot_listener import allure_robotframework +from allure_robotframework.allure_testplan import allure_testplan as testplan -__all__ = ['allure_robotframework'] +__all__ = ['allure_robotframework', "testplan"] diff --git a/allure-robotframework/src/listener/allure_listener.py b/allure-robotframework/src/listener/allure_listener.py index 784a5838..89fab2c9 100644 --- a/allure-robotframework/src/listener/allure_listener.py +++ b/allure-robotframework/src/listener/allure_listener.py @@ -149,15 +149,14 @@ def stop_test(self, _, attributes, messages): test_result.labels.append(Label(name=LabelType.HOST, value=self._host)) test_result.labels.append(Label(name=LabelType.THREAD, value=pool_id())) test_result.labels.extend(allure_tags(attributes)) + tags = attributes.get('tags', ()) + test_result.labels.extend(allure_labels(tags)) test_result.statusDetails = StatusDetails(message=attributes.get('message'), trace=self._current_tb) if attributes.get('critical') == 'yes': test_result.labels.append(Label(name=LabelType.SEVERITY, value=Severity.CRITICAL)) - for label_type in (LabelType.EPIC, LabelType.FEATURE, LabelType.STORY): - test_result.labels.extend(allure_labels(attributes, label_type)) - for link_type in (LinkType.ISSUE, LinkType.TEST_CASE, LinkType.LINK): test_result.links.extend(allure_links(attributes, link_type)) diff --git a/allure-robotframework/src/listener/allure_testplan.py b/allure-robotframework/src/listener/allure_testplan.py new file mode 100644 index 00000000..342d9792 --- /dev/null +++ b/allure-robotframework/src/listener/allure_testplan.py @@ -0,0 +1,27 @@ +from robot.api import SuiteVisitor +from allure_commons.utils import get_testplan +from allure_robotframework.utils import allure_labels +from allure_commons.types import LabelType + + +# noinspection PyPep8Naming +class allure_testplan(SuiteVisitor): + def __init__(self): + self.testplan = get_testplan() + + def start_suite(self, suite): + if self.testplan: + # included_tests = [test["selector"] for test in self.testplan] + suite.filter(included_tests=self.included_tests(suite)) + + def included_tests(self, suite): + included_tests = [""] + for test in suite.tests: + allure_id = None + for label in allure_labels(test.tags): + if label.name == LabelType.ID: + allure_id = str(label.value) + if allure_id and any([allure_id == item.get("id", None) for item in self.testplan]): + included_tests.append(test.name) + + return included_tests or [test["selector"] for test in self.testplan] diff --git a/allure-robotframework/src/listener/utils.py b/allure-robotframework/src/listener/utils.py index 02be3c31..8060de07 100644 --- a/allure-robotframework/src/listener/utils.py +++ b/allure-robotframework/src/listener/utils.py @@ -3,6 +3,7 @@ from allure_commons.model2 import Status, Label, Parameter, Link from allure_commons.types import LabelType from allure_robotframework.types import RobotStatus +from allure_commons.mapping import parse_tag, labels_set, allure_tag_sep def get_allure_status(status): @@ -40,19 +41,12 @@ def get_allure_suites(longname): def allure_tags(attributes): - return [Label(LabelType.TAG, tag) for tag in attributes.get('tags', ())] + return [Label(LabelType.TAG, tag) for tag in attributes.get('tags', ()) if not allure_tag_sep(tag)] -def allure_labels(attributes, prefix): - tags = attributes.get('tags', ()) - - def is_label(label): - return label.startswith("{label}:".format(label=prefix)) - - def label_value(label): - return label.split(':')[1] or 'unknown' - - return [Label(name=prefix, value=label_value(tag)) for tag in tags if is_label(tag)] +def allure_labels(tags): + parsed = [parse_tag(item) for item in tags] + return labels_set(list(filter(lambda x: isinstance(x, Label), parsed))) def allure_links(attributes, prefix): diff --git a/allure-robotframework/test/run_robot_library.py b/allure-robotframework/test/run_robot_library.py index 980b6fb4..4b9f36f0 100644 --- a/allure-robotframework/test/run_robot_library.py +++ b/allure-robotframework/test/run_robot_library.py @@ -1,5 +1,5 @@ import os -from tempfile import mkdtemp +from tempfile import mkdtemp, mkstemp from robot import run from multiprocessing import Process from allure_commons_test.report import AllureReport @@ -10,6 +10,14 @@ def run_robot_with_allure(*args, **kwargs): targets = map(lambda target: os.path.join(root, target), args) tmp_path = mkdtemp(dir=os.environ.get('TEST_TMP', '/tmp')) + if "testplan" in kwargs: + # kwargs.pop("testplan") + kwargs["prerunmodifier"] = "allure_robotframework.testplan" + file, filename = mkstemp(suffix=".json", dir=tmp_path) + os.environ["ALLURE_TESTPLAN_PATH"] = filename + with os.fdopen(file, 'w') as tmp: + tmp.write(kwargs["testplan"]) + def run_robot(path, **kw): # ToDo: fix it (_core not works correctly with multiprocessing) @@ -38,4 +46,6 @@ def run_robot(path, **kw): robot_process.start() robot_process.join() + os.environ.pop("ALLURE_TESTPLAN_PATH", None) + return AllureReport(tmp_path) diff --git a/allure-robotframework/test/testplan/testplan.robot b/allure-robotframework/test/testplan/testplan.robot new file mode 100644 index 00000000..7ba18820 --- /dev/null +++ b/allure-robotframework/test/testplan/testplan.robot @@ -0,0 +1,16 @@ +*** Settings *** +Library ../run_robot_library.py +Library ../test_allure_library.py + + +*** Variables ** +${PLAN_A} \{ +... "version":"1.0", +... "tests": [ +... { "id": "123", "selector": "Second testcase"} +... ] +... \} + +*** Test Case *** +Failed Test Case With Message + ${allure_report} Run Robot With Allure examples/testplan/testplan.rst testplan=${PLAN_A} \ No newline at end of file