11import pytest
2- from itertools import chain , islice , repeat
2+ from itertools import repeat
33from allure_commons .utils import SafeFormatter , md5
44from allure_commons .utils import format_exception , format_traceback
55from allure_commons .model2 import Status
66from allure_commons .model2 import StatusDetails
77from allure_commons .types import LabelType
8-
8+ from allure_pytest . stash import stashed
99
1010ALLURE_DESCRIPTION_MARK = 'allure_description'
1111ALLURE_DESCRIPTION_HTML_MARK = 'allure_description_html'
3030}
3131
3232
33+ class ParsedPytestNodeId :
34+ def __init__ (self , nodeid ):
35+ filepath , * class_names , function_segment = ensure_len (nodeid .split ("::" ), 2 )
36+ self .filepath = filepath
37+ self .path_segments = filepath .split ('/' )
38+ * parent_dirs , filename = ensure_len (self .path_segments , 1 )
39+ self .parent_package = '.' .join (parent_dirs )
40+ self .module = filename .rsplit ("." , 1 )[0 ]
41+ self .package = '.' .join (filter (None , [self .parent_package , self .module ]))
42+ self .class_names = class_names
43+ self .test_function = function_segment .split ("[" , 1 )[0 ]
44+
45+
46+ @stashed
47+ def parse_nodeid (item ):
48+ return ParsedPytestNodeId (item .nodeid )
49+
50+
3351def get_marker_value (item , keyword ):
3452 marker = item .get_closest_marker (keyword )
3553 return marker .args [0 ] if marker and marker .args else None
@@ -101,9 +119,7 @@ def should_convert_mark_to_tag(mark):
101119
102120
103121def allure_package (item ):
104- parts = item .nodeid .split ('::' )
105- path = parts [0 ].rsplit ('.' , 1 )[0 ]
106- return path .replace ('/' , '.' )
122+ return parse_nodeid (item ).package
107123
108124
109125def allure_name (item , parameters , param_id = None ):
@@ -122,37 +138,41 @@ def allure_name(item, parameters, param_id=None):
122138
123139
124140def allure_full_name (item : pytest .Item ):
125- package = allure_package (item )
126- class_names = item .nodeid .split ("::" )[1 :- 1 ]
127- class_part = ("." + "." .join (class_names )) if class_names else ""
128- test = item .originalname if isinstance (item , pytest .Function ) else item .name .split ("[" )[0 ]
129- full_name = f'{ package } { class_part } #{ test } '
141+ nodeid = parse_nodeid (item )
142+ class_part = ("." + "." .join (nodeid .class_names )) if nodeid .class_names else ""
143+ test = item .originalname if isinstance (item , pytest .Function ) else nodeid .test_function
144+ full_name = f"{ nodeid .package } { class_part } #{ test } "
130145 return full_name
131146
132147
148+ def allure_title_path (item ):
149+ nodeid = parse_nodeid (item )
150+ return list (
151+ filter (None , [* nodeid .path_segments , * nodeid .class_names ]),
152+ )
153+
154+
133155def ensure_len (value , min_length , fill_value = None ):
134156 yield from value
135157 yield from repeat (fill_value , min_length - len (value ))
136158
137159
138160def allure_suite_labels (item ):
139- head , * class_names , _ = ensure_len (item .nodeid .split ("::" ), 2 )
140- file_name , path = islice (chain (reversed (head .rsplit ('/' , 1 )), [None ]), 2 )
141- module = file_name .split ('.' )[0 ]
142- package = path .replace ('/' , '.' ) if path else None
143- pairs = dict (
144- zip (
145- [LabelType .PARENT_SUITE , LabelType .SUITE , LabelType .SUB_SUITE ],
146- [package , module , " > " .join (class_names )],
147- ),
148- )
149- labels = dict (allure_labels (item ))
150- default_suite_labels = []
151- for label , value in pairs .items ():
152- if label not in labels .keys () and value :
153- default_suite_labels .append ((label , value ))
161+ nodeid = parse_nodeid (item )
162+
163+ default_suite_labels = {
164+ LabelType .PARENT_SUITE : nodeid .parent_package ,
165+ LabelType .SUITE : nodeid .module ,
166+ LabelType .SUB_SUITE : " > " .join (nodeid .class_names ),
167+ }
168+
169+ existing_labels = dict (allure_labels (item ))
170+ resolved_default_suite_labels = []
171+ for label , value in default_suite_labels .items ():
172+ if label not in existing_labels and value :
173+ resolved_default_suite_labels .append ((label , value ))
154174
155- return default_suite_labels
175+ return resolved_default_suite_labels
156176
157177
158178def get_outcome_status (outcome ):
0 commit comments