Skip to content

Commit 1ceb156

Browse files
authored
feat(pytest-bdd): Allure API implementation (fixes #726, via #845)
1 parent 4198940 commit 1ceb156

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+6513
-106
lines changed

allure-behave/setup.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
'Topic :: Software Development :: Testing :: BDD',
1313
'Programming Language :: Python :: 3',
1414
'Programming Language :: Python :: 3 :: Only',
15-
'Programming Language :: Python :: 3.7',
1615
'Programming Language :: Python :: 3.8',
1716
'Programming Language :: Python :: 3.9',
1817
'Programming Language :: Python :: 3.10',
1918
'Programming Language :: Python :: 3.11',
2019
'Programming Language :: Python :: 3.12',
20+
'Programming Language :: Python :: 3.13',
2121
]
2222

2323
setup_requires = [
@@ -66,4 +66,3 @@ def main():
6666

6767
if __name__ == '__main__':
6868
main()
69-

allure-nose2/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
'Topic :: Software Development :: Testing',
1212
'Programming Language :: Python :: 3',
1313
'Programming Language :: Python :: 3 :: Only',
14-
'Programming Language :: Python :: 3.7',
1514
'Programming Language :: Python :: 3.8',
1615
'Programming Language :: Python :: 3.9',
1716
'Programming Language :: Python :: 3.10',
1817
'Programming Language :: Python :: 3.11',
1918
'Programming Language :: Python :: 3.12',
19+
'Programming Language :: Python :: 3.13',
2020
]
2121

2222
setup_requires = [

allure-pytest-bdd/setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@
1010
'License :: OSI Approved :: Apache Software License',
1111
'Topic :: Software Development :: Quality Assurance',
1212
'Topic :: Software Development :: Testing',
13+
'Topic :: Software Development :: Testing :: BDD',
1314
'Programming Language :: Python :: 3',
1415
'Programming Language :: Python :: 3 :: Only',
15-
'Programming Language :: Python :: 3.7',
1616
'Programming Language :: Python :: 3.8',
1717
'Programming Language :: Python :: 3.9',
1818
'Programming Language :: Python :: 3.10',
1919
'Programming Language :: Python :: 3.11',
2020
'Programming Language :: Python :: 3.12',
21+
'Programming Language :: Python :: 3.13',
2122
]
2223

2324
setup_requires = [
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import pytest
2+
3+
import allure_commons
4+
5+
from allure_commons.model2 import Label
6+
from allure_commons.model2 import Link
7+
from allure_commons.model2 import Parameter
8+
from allure_commons.utils import represent
9+
10+
from .utils import ALLURE_DESCRIPTION_HTML_MARK
11+
from .utils import ALLURE_DESCRIPTION_MARK
12+
from .utils import ALLURE_LABEL_MARK
13+
from .utils import ALLURE_LINK_MARK
14+
from .utils import ALLURE_TITLE_ATTR
15+
16+
from .utils import apply_link_pattern
17+
from .utils import attach_data
18+
from .utils import attach_file
19+
from .utils import get_link_patterns
20+
from .steps import start_step
21+
from .steps import stop_step
22+
23+
24+
class AllurePytestBddApiHooks:
25+
def __init__(self, config, lifecycle):
26+
self.lifecycle = lifecycle
27+
self.__link_patterns = get_link_patterns(config)
28+
29+
@allure_commons.hookimpl
30+
def decorate_as_title(self, test_title):
31+
32+
def decorator(fn):
33+
setattr(fn, ALLURE_TITLE_ATTR, test_title)
34+
return fn
35+
36+
return decorator
37+
38+
@allure_commons.hookimpl
39+
def add_title(self, test_title):
40+
with self.lifecycle.update_test_case() as test_result:
41+
test_result.name = test_title
42+
43+
@allure_commons.hookimpl
44+
def decorate_as_description(self, test_description):
45+
allure_description_mark = getattr(pytest.mark, ALLURE_DESCRIPTION_MARK)
46+
return allure_description_mark(test_description)
47+
48+
@allure_commons.hookimpl
49+
def add_description(self, test_description):
50+
with self.lifecycle.update_test_case() as test_result:
51+
test_result.description = test_description
52+
53+
@allure_commons.hookimpl
54+
def decorate_as_description_html(self, test_description_html):
55+
allure_description_html_mark = getattr(pytest.mark, ALLURE_DESCRIPTION_HTML_MARK)
56+
return allure_description_html_mark(test_description_html)
57+
58+
@allure_commons.hookimpl
59+
def add_description_html(self, test_description_html):
60+
with self.lifecycle.update_test_case() as test_result:
61+
test_result.descriptionHtml = test_description_html
62+
63+
@allure_commons.hookimpl
64+
def decorate_as_label(self, label_type, labels):
65+
allure_label_mark = getattr(pytest.mark, ALLURE_LABEL_MARK)
66+
return allure_label_mark(*labels, label_type=label_type)
67+
68+
@allure_commons.hookimpl
69+
def add_label(self, label_type, labels):
70+
with self.lifecycle.update_test_case() as test_result:
71+
test_result.labels.extend(
72+
Label(name=label_type, value=value) for value in labels or []
73+
)
74+
75+
@allure_commons.hookimpl
76+
def decorate_as_link(self, url, link_type, name):
77+
url = apply_link_pattern(self.__link_patterns, link_type, url)
78+
allure_link_mark = getattr(pytest.mark, ALLURE_LINK_MARK)
79+
return allure_link_mark(url, name=name, link_type=link_type)
80+
81+
@allure_commons.hookimpl
82+
def add_link(self, url, link_type, name):
83+
url = apply_link_pattern(self.__link_patterns, link_type, url)
84+
with self.lifecycle.update_test_case() as test_result:
85+
test_result.links.append(Link(url=url, name=name, type=link_type))
86+
87+
@allure_commons.hookimpl
88+
def add_parameter(self, name, value, excluded, mode):
89+
with self.lifecycle.update_test_case() as test_result:
90+
test_result.parameters.append(
91+
Parameter(
92+
name=name,
93+
value=represent(value),
94+
excluded=excluded,
95+
mode=mode.value if mode else None,
96+
),
97+
)
98+
99+
@allure_commons.hookimpl
100+
def start_step(self, uuid, title, params):
101+
start_step(self.lifecycle, step_uuid=uuid, title=title, params=params)
102+
103+
@allure_commons.hookimpl
104+
def stop_step(self, uuid, exc_type, exc_val, exc_tb):
105+
stop_step(
106+
self.lifecycle,
107+
uuid,
108+
exception=exc_val,
109+
exception_type=exc_type,
110+
traceback=exc_tb,
111+
)
112+
113+
@allure_commons.hookimpl
114+
def attach_data(self, body, name, attachment_type, extension):
115+
attach_data(self.lifecycle, body, name, attachment_type, extension)
116+
117+
@allure_commons.hookimpl
118+
def attach_file(self, source, name, attachment_type, extension):
119+
attach_file(self.lifecycle, source, name, attachment_type, extension)

allure-pytest-bdd/src/plugin.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
1-
import allure_commons
1+
import argparse
22
import os
3+
4+
import allure_commons
35
from allure_commons.logger import AllureFileLogger
6+
from allure_commons.lifecycle import AllureLifecycle
7+
8+
from .allure_api_listener import AllurePytestBddApiHooks
49
from .pytest_bdd_listener import PytestBDDListener
510

11+
from .utils import ALLURE_DESCRIPTION_MARK
12+
from .utils import ALLURE_DESCRIPTION_HTML_MARK
13+
from .utils import ALLURE_LABEL_MARK
14+
from .utils import ALLURE_LINK_MARK
15+
616

717
def pytest_addoption(parser):
818
parser.getgroup("reporting").addoption('--alluredir',
@@ -17,6 +27,27 @@ def pytest_addoption(parser):
1727
dest="clean_alluredir",
1828
help="Clean alluredir folder if it exists")
1929

30+
def link_pattern(string):
31+
pattern = string.split(':', 1)
32+
if not pattern[0]:
33+
raise argparse.ArgumentTypeError("A link type is mandatory")
34+
35+
if len(pattern) != 2:
36+
raise argparse.ArgumentTypeError("A link pattern is mandatory")
37+
return pattern
38+
39+
parser.getgroup("general").addoption(
40+
"--allure-link-pattern",
41+
action="append",
42+
dest="allure_link_pattern",
43+
metavar="LINK_TYPE:LINK_PATTERN",
44+
default=[],
45+
type=link_pattern,
46+
help="""A URL pattern for a link type. Allows short links in tests,
47+
e.g., 'issue-1'. `pattern.format(short_url)` will be called to get
48+
the full URL"""
49+
)
50+
2051

2152
def cleanup_factory(plugin):
2253
def clean_up():
@@ -25,18 +56,33 @@ def clean_up():
2556
return clean_up
2657

2758

59+
def register_marks(config):
60+
config.addinivalue_line("markers", f"{ALLURE_DESCRIPTION_MARK}: allure description")
61+
config.addinivalue_line("markers", f"{ALLURE_DESCRIPTION_HTML_MARK}: allure description in HTML")
62+
config.addinivalue_line("markers", f"{ALLURE_LABEL_MARK}: allure label marker")
63+
config.addinivalue_line("markers", f"{ALLURE_LINK_MARK}: allure link marker")
64+
65+
2866
def pytest_configure(config):
67+
register_marks(config)
68+
2969
report_dir = config.option.allure_report_dir
3070
clean = False if config.option.collectonly else config.option.clean_alluredir
3171

3272
if report_dir:
3373
report_dir = os.path.abspath(report_dir)
3474

35-
pytest_bdd_listener = PytestBDDListener()
75+
lifecycle = AllureLifecycle()
76+
77+
pytest_bdd_listener = PytestBDDListener(lifecycle)
3678
config.pluginmanager.register(pytest_bdd_listener)
3779
allure_commons.plugin_manager.register(pytest_bdd_listener)
3880
config.add_cleanup(cleanup_factory(pytest_bdd_listener))
3981

82+
allure_api_impl = AllurePytestBddApiHooks(config, lifecycle)
83+
allure_commons.plugin_manager.register(allure_api_impl)
84+
config.add_cleanup(cleanup_factory(allure_api_impl))
85+
4086
file_logger = AllureFileLogger(report_dir, clean)
4187
allure_commons.plugin_manager.register(file_logger)
4288
config.add_cleanup(cleanup_factory(file_logger))

0 commit comments

Comments
 (0)