testit-adapter-pytest 4.2.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,440 @@
1
+ import hashlib
2
+ import logging
3
+ import re
4
+ import traceback
5
+ from typing import List
6
+
7
+ import pytest
8
+
9
+ from traceback import format_exception_only
10
+
11
+ from _pytest.mark import Mark
12
+ from testit_python_commons.models.link import Link
13
+ from testit_python_commons.models.link_type import LinkType
14
+ from testit_python_commons.models.test_result import TestResult
15
+ from testit_python_commons.models.test_result_with_all_fixture_step_results_model import TestResultWithAllFixtureStepResults
16
+ from testit_python_commons.models.outcome_type import OutcomeType
17
+
18
+ from testit_adapter_pytest.models.executable_test import ExecutableTest
19
+
20
+
21
+ __ARRAY_TYPES = (frozenset, list, set, tuple,)
22
+
23
+
24
+ def form_test(item) -> ExecutableTest:
25
+ executable_test = ExecutableTest(
26
+ external_id=__get_external_id_from(item),
27
+ name=__get_display_name_from(item),
28
+ duration=0,
29
+ parameters=__get_parameters_from(item),
30
+ properties=__get_properties_from(item),
31
+ namespace=__get_namespace_from(item),
32
+ classname=__get_class_name_from(item),
33
+ title=__get_title_from(item),
34
+ description=__get_description_from(item),
35
+ links=__get_links_from(item),
36
+ labels=__get_labels_from(item),
37
+ tags=__get_tags_from(item),
38
+ work_item_ids=__get_work_item_ids_from(item),
39
+ node_id=item.nodeid
40
+ )
41
+
42
+ if item.own_markers:
43
+ executable_test = __set_outcome_and_message_from_markers(executable_test, item.own_markers)
44
+
45
+ return executable_test
46
+
47
+
48
+ def __set_outcome_and_message_from_markers(executable_test: ExecutableTest, markers: List[Mark]) -> ExecutableTest:
49
+ for marker in markers:
50
+ if marker.name in ('skip', 'skipif'):
51
+ executable_test.outcome = 'Skipped'
52
+ if marker.name == 'xfail':
53
+ executable_test.outcome = 'Xfailed'
54
+ if marker.name in ('skip', 'skipif', 'xfail'):
55
+ if len(marker.args) == 1 and isinstance(marker.args, str):
56
+ executable_test.message = marker.args[0]
57
+
58
+ condition_in_args = marker.args and marker.args[0]
59
+ condition_in_kwargs = marker.kwargs and 'condition' in marker.kwargs and marker.kwargs['condition']
60
+
61
+ if (condition_in_kwargs or condition_in_args) and 'reason' in marker.kwargs:
62
+ executable_test.message = marker.kwargs['reason']
63
+
64
+ return executable_test
65
+
66
+
67
+ def __get_display_name_from(item):
68
+ display_name = __search_attribute(item, 'test_displayname')
69
+
70
+ if not display_name:
71
+ return item.function.__doc__ if \
72
+ item.function.__doc__ else item.function.__name__
73
+
74
+ return collect_parameters_in_string_attribute(display_name, get_all_parameters(item))
75
+
76
+
77
+ def __get_external_id_from(item):
78
+ external_id = __search_attribute(item, 'test_external_id')
79
+
80
+ if not external_id:
81
+ return get_hash(item.parent.nodeid + item.function.__name__)
82
+
83
+ return collect_parameters_in_string_attribute(external_id, get_all_parameters(item))
84
+
85
+
86
+ def __get_title_from(item):
87
+ title = __search_attribute(item, 'test_title')
88
+
89
+ if not title:
90
+ return None
91
+
92
+ return collect_parameters_in_string_attribute(title, get_all_parameters(item))
93
+
94
+
95
+ def __get_description_from(item):
96
+ description = __search_attribute(item, 'test_description')
97
+
98
+ if not description:
99
+ return None
100
+
101
+ return collect_parameters_in_string_attribute(description, get_all_parameters(item))
102
+
103
+
104
+ def __get_namespace_from(item):
105
+ namespace = __search_attribute(item, 'test_namespace')
106
+
107
+ if not namespace:
108
+ return item.function.__module__
109
+
110
+ return collect_parameters_in_string_attribute(namespace, get_all_parameters(item))
111
+
112
+
113
+ def __get_class_name_from(item):
114
+ class_name = __search_attribute(item, 'test_classname')
115
+
116
+ if not class_name:
117
+ i = item.function.__qualname__.find('.')
118
+
119
+ if i != -1:
120
+ return item.function.__qualname__[:i]
121
+
122
+ return None
123
+
124
+ return collect_parameters_in_string_attribute(class_name, get_all_parameters(item))
125
+
126
+
127
+ def __get_links_from(item):
128
+ links = __search_attribute(item, 'test_links')
129
+
130
+ if not links:
131
+ return []
132
+
133
+ return __set_parameters_to_links(links, get_all_parameters(item))
134
+
135
+
136
+ def __get_parameters_from(item):
137
+ test_parameters = {}
138
+
139
+ if hasattr(item, 'callspec'):
140
+ for key, parameter in item.callspec.params.items():
141
+ test_parameters[key] = str(parameter)
142
+
143
+ return test_parameters
144
+
145
+
146
+ def __get_properties_from(item):
147
+ if hasattr(item, 'test_properties'):
148
+ return item.test_properties
149
+ return None
150
+
151
+
152
+ def __set_parameters_to_links(links, all_parameters):
153
+ if not all_parameters:
154
+ return links
155
+
156
+ links_with_parameters = []
157
+
158
+ for link in links:
159
+ links_with_parameters.append(
160
+ Link()
161
+ .set_url(
162
+ collect_parameters_in_string_attribute(
163
+ link.get_url(),
164
+ all_parameters))
165
+ .set_title(
166
+ collect_parameters_in_string_attribute(
167
+ link.get_title(),
168
+ all_parameters) if link.get_title() else None)
169
+ .set_link_type(
170
+ collect_parameters_in_string_attribute(
171
+ link.get_link_type(),
172
+ all_parameters) if link.get_link_type() else LinkType.RELATED)
173
+ .set_description(
174
+ collect_parameters_in_string_attribute(
175
+ link.get_description(),
176
+ all_parameters) if link.get_description() else None))
177
+
178
+ return links_with_parameters
179
+
180
+
181
+ def __get_labels_from(item) -> List[dict]:
182
+ test_labels = __search_attribute(item, 'test_labels')
183
+
184
+ if not test_labels:
185
+ return []
186
+
187
+ labels = []
188
+
189
+ for label in test_labels:
190
+ result = collect_parameters_in_mass_attribute(
191
+ label,
192
+ get_all_parameters(item))
193
+
194
+ if isinstance(result, __ARRAY_TYPES):
195
+ for l in result:
196
+ labels.append({
197
+ 'name': str(l)
198
+ })
199
+ else:
200
+ labels.append({
201
+ 'name': str(result)
202
+ })
203
+
204
+ return labels
205
+
206
+
207
+ def __get_tags_from(item) -> List[str]:
208
+ test_tags = __search_attribute(item, 'test_tags')
209
+
210
+ if not test_tags:
211
+ return []
212
+
213
+ tags = []
214
+
215
+ for tag in test_tags:
216
+ result = collect_parameters_in_mass_attribute(
217
+ tag,
218
+ get_all_parameters(item))
219
+
220
+ if isinstance(result, __ARRAY_TYPES):
221
+ for t in result:
222
+ tags.append(str(t))
223
+ else:
224
+ tags.append(str(result))
225
+
226
+ return tags
227
+
228
+
229
+ def __get_work_item_ids_from(item):
230
+ test_workitem_ids = __search_attribute(item, 'test_workitems_id')
231
+
232
+ if not test_workitem_ids:
233
+ return []
234
+
235
+ workitem_ids = []
236
+
237
+ for workitem_id in test_workitem_ids:
238
+ result = collect_parameters_in_mass_attribute(
239
+ workitem_id,
240
+ get_all_parameters(item))
241
+
242
+ if isinstance(result, __ARRAY_TYPES):
243
+ workitem_ids += list(map(str, result))
244
+ else:
245
+ workitem_ids.append(str(result))
246
+
247
+ return workitem_ids
248
+
249
+
250
+ def collect_parameters_in_string_attribute(attribute, all_parameters):
251
+ param_keys = re.findall(r"\{(.*?)\}", attribute)
252
+
253
+ if len(param_keys) > 0:
254
+ for param_key in param_keys:
255
+ parameter = get_parameter(param_key, all_parameters)
256
+
257
+ if parameter is not None:
258
+ attribute = attribute.replace("{" + param_key + "}", str(parameter))
259
+
260
+ return attribute
261
+
262
+
263
+ def collect_parameters_in_mass_attribute(attribute, all_parameters):
264
+ param_keys = re.findall(r"\{(.*?)\}", attribute)
265
+
266
+ if len(param_keys) == 1:
267
+ parameter = get_parameter(param_keys[0], all_parameters)
268
+
269
+ if parameter is not None:
270
+ return parameter
271
+
272
+ if len(param_keys) > 1:
273
+ logging.error(f'(For type tuple, list, set) support only one key!')
274
+
275
+ return attribute
276
+
277
+
278
+ def get_parameter(key_for_parameter, all_parameters):
279
+ id_keys_in_parameter = re.findall(r'\[(.*?)\]', key_for_parameter)
280
+
281
+ if len(id_keys_in_parameter) > 1:
282
+ logging.error("(For type tuple, list, set, dict) support only one level!")
283
+
284
+ return
285
+
286
+ if len(id_keys_in_parameter) == 0:
287
+ if key_for_parameter not in all_parameters:
288
+ logging.error(f"Key for parameter {key_for_parameter} not found")
289
+
290
+ return
291
+
292
+ return all_parameters[key_for_parameter]
293
+
294
+ parameter_key = key_for_parameter.replace("[" + id_keys_in_parameter[0] + "]", "")
295
+ id_key_in_parameter = id_keys_in_parameter[0].strip("\'\"")
296
+
297
+ nested = all_parameters.get(parameter_key)
298
+
299
+ if id_key_in_parameter.isdigit() and isinstance(nested, (list, tuple)):
300
+ index = int(id_key_in_parameter)
301
+ if index in range(len(nested)):
302
+ return nested[index]
303
+
304
+ if isinstance(nested, dict) and id_key_in_parameter in nested:
305
+ return nested[id_key_in_parameter]
306
+
307
+ logging.error(f"Not key: {key_for_parameter} in run parameters or other keys problem")
308
+
309
+
310
+ def __expand_dict_parameters(params):
311
+ for value in tuple(params.values()):
312
+ if isinstance(value, dict):
313
+ for dict_key, dict_value in value.items():
314
+ params.setdefault(dict_key, dict_value)
315
+
316
+
317
+ def get_all_parameters(item):
318
+ params = {}
319
+
320
+ if hasattr(item, 'test_properties'):
321
+ params.update(item.test_properties)
322
+
323
+ if hasattr(item, 'callspec'):
324
+ params.update(item.callspec.params)
325
+ __expand_dict_parameters(params)
326
+
327
+ return params
328
+
329
+
330
+ def __search_attribute(item, attribute):
331
+ if hasattr(item.function, attribute):
332
+ return getattr(item.function, attribute)
333
+
334
+ if hasattr(item.cls, attribute):
335
+ return getattr(item.cls, attribute)
336
+
337
+ return
338
+
339
+
340
+ def get_hash(value: str):
341
+ md = hashlib.sha256(bytes(value, encoding='utf-8'))
342
+ return md.hexdigest()
343
+
344
+
345
+ def convert_executable_test_to_test_result_model(executable_test: ExecutableTest) -> TestResult:
346
+ pytest_autotest_keys = convert_node_id_to_pytest_autotest_keys(executable_test.node_id)
347
+
348
+ return TestResult()\
349
+ .set_external_id(executable_test.external_id)\
350
+ .set_autotest_name(executable_test.name)\
351
+ .set_step_results(executable_test.step_results)\
352
+ .set_setup_results(executable_test.setup_step_results)\
353
+ .set_teardown_results(executable_test.teardown_step_results)\
354
+ .set_duration(executable_test.duration)\
355
+ .set_outcome(executable_test.outcome)\
356
+ .set_status_type(executable_test.status_type)\
357
+ .set_traces(executable_test.traces)\
358
+ .set_attachments(executable_test.attachments)\
359
+ .set_parameters(executable_test.parameters)\
360
+ .set_properties(executable_test.properties)\
361
+ .set_namespace(executable_test.namespace)\
362
+ .set_classname(executable_test.classname)\
363
+ .set_title(executable_test.title)\
364
+ .set_description(executable_test.description)\
365
+ .set_links(executable_test.links)\
366
+ .set_result_links(executable_test.result_links)\
367
+ .set_labels(executable_test.labels)\
368
+ .set_tags(executable_test.tags)\
369
+ .set_work_item_ids(executable_test.work_item_ids) \
370
+ .set_message(executable_test.message) \
371
+ .set_external_key(pytest_autotest_keys)
372
+
373
+
374
+ def convert_node_id_to_pytest_autotest_keys(node_id: str) -> str:
375
+ test_path_parts = __get_test_path_parts_by_node_id(node_id)
376
+ directories_in_project = __get_directories_in_project_by_test_path_parts(test_path_parts)
377
+ test_node_parts_from_module = __get_test_node_parts_from_module_by_test_path_parts(test_path_parts)
378
+
379
+ return __join_test_node_parts_to_pytest_autotest_keys(directories_in_project + test_node_parts_from_module)
380
+
381
+
382
+ def __get_test_path_parts_by_node_id(node_id: str):
383
+ return node_id.split('/')
384
+
385
+
386
+ def __get_directories_in_project_by_test_path_parts(test_path_parts: List[str]):
387
+ return test_path_parts[:-1]
388
+
389
+
390
+ def __get_test_node_parts_from_module_by_test_path_parts(test_path_parts: List[str]):
391
+ test_node_from_module = test_path_parts[-1]
392
+
393
+ return test_node_from_module.split('::')
394
+
395
+
396
+ def __join_test_node_parts_to_pytest_autotest_keys(test_node_parts: List[str]):
397
+ return ' and '.join(test_node_parts)
398
+
399
+
400
+ def fixtures_containers_to_test_results_with_all_fixture_step_results(
401
+ fixtures_containers: dict,
402
+ test_result_ids: dict) -> List[TestResultWithAllFixtureStepResults]:
403
+ test_results_with_all_fixture_step_results = []
404
+
405
+ for node_id, test_result_id in test_result_ids.items():
406
+ test_result_with_all_fixture_step_results = TestResultWithAllFixtureStepResults(test_result_id)
407
+
408
+ for uuid, fixtures_container in fixtures_containers.items():
409
+ if node_id in fixtures_container.node_ids:
410
+ if fixtures_container.befores:
411
+ test_result_with_all_fixture_step_results.set_setup_results(fixtures_container.befores[0].steps)
412
+
413
+ if fixtures_container.afters:
414
+ test_result_with_all_fixture_step_results.set_teardown_results(fixtures_container.afters[0].steps)
415
+
416
+ test_results_with_all_fixture_step_results.append(test_result_with_all_fixture_step_results)
417
+
418
+ return test_results_with_all_fixture_step_results
419
+
420
+
421
+ def get_status(exception):
422
+ if exception:
423
+ if isinstance(exception, pytest.skip.Exception):
424
+ return OutcomeType.SKIPPED
425
+ return OutcomeType.FAILED
426
+ else:
427
+ return OutcomeType.PASSED
428
+
429
+
430
+ def get_outcome_status(outcome):
431
+ _, exception, _ = outcome.excinfo or (None, None, None)
432
+ return get_status(exception)
433
+
434
+
435
+ def get_traceback(exc_traceback):
436
+ return ''.join(traceback.format_tb(exc_traceback)) if exc_traceback else None
437
+
438
+
439
+ def get_message(etype, value):
440
+ return '\n'.join(format_exception_only(etype, value)) if etype or value else None