testit-python-commons 3.3.1__tar.gz → 3.4.0__tar.gz

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.
Files changed (39) hide show
  1. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/PKG-INFO +1 -1
  2. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/setup.py +1 -1
  3. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/app_properties.py +12 -0
  4. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/client/api_client.py +204 -18
  5. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/client/converter.py +29 -3
  6. testit_python_commons-3.4.0/src/testit_python_commons/models/fixture.py +24 -0
  7. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/models/test_result.py +11 -0
  8. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/services/__init__.py +2 -0
  9. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/services/adapter_manager.py +34 -7
  10. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/services/adapter_manager_configuration.py +8 -8
  11. testit_python_commons-3.4.0/src/testit_python_commons/services/fixture_manager.py +60 -0
  12. testit_python_commons-3.4.0/src/testit_python_commons/services/fixture_storage.py +40 -0
  13. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/services/plugin_manager.py +12 -1
  14. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/services/utils.py +8 -0
  15. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons.egg-info/PKG-INFO +1 -1
  16. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons.egg-info/SOURCES.txt +3 -0
  17. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/README.md +0 -0
  18. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/setup.cfg +0 -0
  19. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit.py +0 -0
  20. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/__init__.py +0 -0
  21. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/client/__init__.py +0 -0
  22. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/client/client_configuration.py +0 -0
  23. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/decorators.py +0 -0
  24. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/dynamic_methods.py +0 -0
  25. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/models/__init__.py +0 -0
  26. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/models/adapter_mode.py +0 -0
  27. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/models/link.py +0 -0
  28. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/models/link_type.py +0 -0
  29. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/models/outcome_type.py +0 -0
  30. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/models/step_result.py +0 -0
  31. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/models/test_result_with_all_fixture_step_results_model.py +0 -0
  32. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/services/logger.py +0 -0
  33. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/services/retry.py +0 -0
  34. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/services/step_manager.py +0 -0
  35. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/services/step_result_storage.py +0 -0
  36. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons/step.py +0 -0
  37. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons.egg-info/dependency_links.txt +0 -0
  38. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons.egg-info/requires.txt +0 -0
  39. {testit_python_commons-3.3.1 → testit_python_commons-3.4.0}/src/testit_python_commons.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: testit-python-commons
3
- Version: 3.3.1
3
+ Version: 3.4.0
4
4
  Summary: Python commons for Test IT
5
5
  Home-page: https://github.com/testit-tms/adapters-python/
6
6
  Author: Integration team
@@ -2,7 +2,7 @@ from setuptools import find_packages, setup
2
2
 
3
3
  setup(
4
4
  name='testit-python-commons',
5
- version='3.3.1',
5
+ version='3.4.0',
6
6
  description='Python commons for Test IT',
7
7
  long_description=open('README.md', "r").read(),
8
8
  long_description_content_type="text/markdown",
@@ -113,6 +113,10 @@ class AppProperties:
113
113
  option.set_automatic_updation_links_to_test_cases):
114
114
  cli_properties['automaticupdationlinkstotestcases'] = option.set_automatic_updation_links_to_test_cases
115
115
 
116
+ if hasattr(option, 'set_import_realtime') and cls.__check_property_value(
117
+ option.set_import_realtime):
118
+ cli_properties['importrealtime'] = option.set_import_realtime
119
+
116
120
  return cli_properties
117
121
 
118
122
  @classmethod
@@ -165,6 +169,11 @@ class AppProperties:
165
169
  env_properties['automaticupdationlinkstotestcases'] = os.environ.get(
166
170
  f'{cls.__env_prefix}_AUTOMATIC_UPDATION_LINKS_TO_TEST_CASES')
167
171
 
172
+ if f'{cls.__env_prefix}_IMPORT_REALTIME' in os.environ.keys() and cls.__check_property_value(
173
+ os.environ.get(f'{cls.__env_prefix}_IMPORT_REALTIME')):
174
+ env_properties['importrealtime'] = os.environ.get(
175
+ f'{cls.__env_prefix}_IMPORT_REALTIME')
176
+
168
177
  return env_properties
169
178
 
170
179
  @classmethod
@@ -226,6 +235,9 @@ class AppProperties:
226
235
  if not cls.__check_property_value(properties.get('automaticupdationlinkstotestcases')):
227
236
  properties['automaticupdationlinkstotestcases'] = 'false'
228
237
 
238
+ if not cls.__check_property_value(properties.get('importrealtime')):
239
+ properties['importrealtime'] = 'true'
240
+
229
241
  @staticmethod
230
242
  def __search_in_environ(var_name: str):
231
243
  if re.fullmatch(r'{[a-zA-Z_]\w*}', var_name) and var_name[1:-1] in os.environ:
@@ -4,9 +4,13 @@ import typing
4
4
  from datetime import datetime
5
5
 
6
6
  from testit_api_client import ApiClient, Configuration
7
- from testit_api_client.api import AttachmentsApi, AutoTestsApi, TestRunsApi, TestResultsApi
7
+ from testit_api_client.api import AttachmentsApi, AutoTestsApi, TestRunsApi, TestResultsApi, WorkItemsApi
8
8
  from testit_api_client.models import (
9
+ AutoTestModel,
10
+ AutoTestPostModel,
11
+ AutoTestPutModel,
9
12
  AttachmentPutModel,
13
+ AutoTestResultsForTestRunModel,
10
14
  TestResultModel,
11
15
  WorkItemIdModel,
12
16
  WorkItemIdentifierModel
@@ -15,13 +19,13 @@ from testit_api_client.models import (
15
19
  from testit_python_commons.client.client_configuration import ClientConfiguration
16
20
  from testit_python_commons.client.converter import Converter
17
21
  from testit_python_commons.models.test_result import TestResult
18
- from testit_python_commons.models.test_result_with_all_fixture_step_results_model import \
19
- TestResultWithAllFixtureStepResults
20
22
  from testit_python_commons.services.logger import adapter_logger
21
23
  from testit_python_commons.services.retry import retry
22
24
 
23
25
 
24
26
  class ApiClientWorker:
27
+ __max_tests_for_write = 100
28
+
25
29
  def __init__(self, config: ClientConfiguration):
26
30
  api_client_config = self.__get_api_client_configuration(
27
31
  url=config.get_url(),
@@ -33,6 +37,7 @@ class ApiClientWorker:
33
37
  self.__autotest_api = AutoTestsApi(api_client=api_client)
34
38
  self.__attachments_api = AttachmentsApi(api_client=api_client)
35
39
  self.__test_results_api = TestResultsApi(api_client=api_client)
40
+ self.__work_items_api = WorkItemsApi(api_client=api_client)
36
41
  self.__config = config
37
42
 
38
43
  @staticmethod
@@ -86,16 +91,175 @@ class ApiClientWorker:
86
91
  autotests = self.__autotest_api.api_v2_auto_tests_search_post(autotests_select_model=model)
87
92
 
88
93
  if autotests:
89
- self.__update_test(test_result, autotests[0].is_flaky)
90
-
91
- autotest_global_id = autotests[0].id
94
+ self.__update_test(test_result, autotests[0])
92
95
  else:
93
- autotest_global_id = self.__create_test(test_result)
96
+ self.__create_test(test_result)
97
+
98
+ return self.__load_test_result(test_result)
99
+
100
+ @adapter_logger
101
+ def write_tests(self, test_results: typing.List[TestResult], fixture_containers: dict):
102
+ autotests_for_create = []
103
+ autotests_for_update = []
104
+ results_for_autotests_being_created = []
105
+ results_for_autotests_being_updated = []
106
+
107
+ for test_result in test_results:
108
+ test_result = self.__add_fixtures_to_test_result(test_result, fixture_containers)
109
+
110
+ model = Converter.project_id_and_external_id_to_auto_tests_search_post_request(
111
+ self.__config.get_project_id(),
112
+ test_result.get_external_id())
113
+
114
+ test_result_model = Converter.test_result_to_testrun_result_post_model(
115
+ test_result,
116
+ self.__config.get_configuration_id())
117
+
118
+ autotests = self.__autotest_api.api_v2_auto_tests_search_post(autotests_select_model=model)
119
+
120
+ if autotests:
121
+ autotest_for_update = self.__prepare_to_update_autotest(test_result, autotests[0])
122
+
123
+ autotests_for_update.append(autotest_for_update)
124
+ results_for_autotests_being_updated.append(test_result_model)
125
+
126
+ if len(autotests_for_update) >= self.__max_tests_for_write:
127
+ self.__update_tests(autotests_for_update)
128
+ self.__load_test_results(results_for_autotests_being_updated)
129
+
130
+ autotests_for_update.clear()
131
+ results_for_autotests_being_updated.clear()
132
+ else:
133
+ autotest_for_create = self.__prepare_to_create_autotest(test_result)
134
+
135
+ autotests_for_create.append(autotest_for_create)
136
+ results_for_autotests_being_created.append(test_result_model)
137
+
138
+ if len(autotests_for_create) >= self.__max_tests_for_write:
139
+ self.__create_tests(autotests_for_create)
140
+ self.__load_test_results(results_for_autotests_being_created)
141
+
142
+ autotests_for_create.clear()
143
+ results_for_autotests_being_created.clear()
144
+
145
+ if len(autotests_for_update) > 0:
146
+ self.__update_tests(autotests_for_update)
147
+ self.__load_test_results(results_for_autotests_being_updated)
148
+
149
+ autotests_for_update.clear()
150
+ results_for_autotests_being_updated.clear()
151
+
152
+ if len(autotests_for_create) > 0:
153
+ self.__create_tests(autotests_for_create)
154
+ self.__load_test_results(results_for_autotests_being_created)
155
+
156
+ autotests_for_create.clear()
157
+ results_for_autotests_being_created.clear()
158
+
159
+ @adapter_logger
160
+ def __prepare_to_create_autotest(self, test_result: TestResult) -> AutoTestPostModel:
161
+ logging.debug('Preparing to create the auto test ', test_result.get_external_id())
162
+
163
+ model = Converter.test_result_to_autotest_post_model(
164
+ test_result,
165
+ self.__config.get_project_id())
166
+ model.work_item_ids_for_link_with_auto_test = self.__get_work_item_uuids_for_link_with_auto_test(
167
+ test_result.get_work_item_ids())
168
+
169
+ return model
170
+
171
+ @adapter_logger
172
+ def __prepare_to_update_autotest(
173
+ self,
174
+ test_result: TestResult,
175
+ autotest: AutoTestModel) -> AutoTestPutModel:
176
+ logging.debug('Preparing to update the auto test ', test_result.get_external_id())
177
+
178
+ model = Converter.test_result_to_autotest_put_model(
179
+ test_result,
180
+ self.__config.get_project_id())
181
+ model.is_flaky = autotest.is_flaky
182
+ model.work_item_ids_for_link_with_auto_test = self.__get_work_item_uuids_for_link_with_auto_test(
183
+ test_result.get_work_item_ids(),
184
+ str(autotest.global_id))
185
+
186
+ return model
187
+
188
+ @staticmethod
189
+ @adapter_logger
190
+ def __add_fixtures_to_test_result(
191
+ test_result: TestResult,
192
+ fixtures_containers: dict) -> TestResult:
193
+ setup_results = []
194
+ teardown_results = []
195
+
196
+ for uuid, fixtures_container in fixtures_containers.items():
197
+ if test_result.get_external_id() in fixtures_container.external_ids:
198
+ if fixtures_container.befores:
199
+ setup_results += fixtures_container.befores[0].steps
200
+
201
+ if fixtures_container.afters:
202
+ teardown_results = fixtures_container.afters[0].steps + teardown_results
203
+
204
+ test_result.set_setup_results(setup_results)
205
+ test_result.set_teardown_results(teardown_results)
206
+
207
+ return test_result
208
+
209
+ @adapter_logger
210
+ def __get_work_item_uuids_for_link_with_auto_test(
211
+ self,
212
+ work_item_ids: list,
213
+ autotest_global_id: str = None) -> list:
214
+ linked_work_items = []
94
215
 
95
216
  if autotest_global_id:
96
- self.__update_autotest_link_from_work_items(autotest_global_id, test_result.get_work_item_ids())
217
+ linked_work_items = self.__get_work_items_linked_to_autotest(autotest_global_id)
97
218
 
98
- return self.__load_test_result(test_result)
219
+ work_item_uuids = self.__prepare_list_of_work_item_uuids(linked_work_items, work_item_ids)
220
+
221
+ return work_item_uuids
222
+
223
+ @adapter_logger
224
+ def __prepare_list_of_work_item_uuids(
225
+ self,
226
+ linked_work_items: list,
227
+ work_item_ids: list) -> list:
228
+ work_item_uuids = []
229
+
230
+ for linked_work_item in linked_work_items:
231
+ linked_work_item_id = str(linked_work_item.global_id)
232
+ linked_work_item_uuid = linked_work_item.id
233
+
234
+ if linked_work_item_id in work_item_ids:
235
+ work_item_ids.remove(linked_work_item_id)
236
+ work_item_uuids.append(linked_work_item_uuid)
237
+
238
+ continue
239
+
240
+ if self.__config.get_automatic_updation_links_to_test_cases() != 'true':
241
+ work_item_uuids.append(linked_work_item_uuid)
242
+
243
+ for work_item_id in work_item_ids:
244
+ work_item_uuid = self.__get_work_item_uuid_by_work_item_id(work_item_id)
245
+
246
+ if work_item_uuid:
247
+ work_item_uuids.append(work_item_uuid)
248
+
249
+ return work_item_uuids
250
+
251
+ @adapter_logger
252
+ def __get_work_item_uuid_by_work_item_id(self, work_item_id: str) -> str | None:
253
+ logging.debug('Getting workitem by id ' + work_item_id)
254
+
255
+ try:
256
+ work_item = self.__work_items_api.get_work_item_by_id(id=work_item_id)
257
+
258
+ logging.debug(f'Got workitem {work_item}')
259
+
260
+ return work_item.id
261
+ except Exception as exc:
262
+ logging.error(f'Getting workitem by id {work_item_id} status: {exc}')
99
263
 
100
264
  @adapter_logger
101
265
  def __get_work_items_linked_to_autotest(self, autotest_global_id: str) -> typing.List[WorkItemIdentifierModel]:
@@ -123,9 +287,7 @@ class ApiClientWorker:
123
287
  def __create_test(self, test_result: TestResult) -> str:
124
288
  logging.debug(f'Autotest "{test_result.get_autotest_name()}" was not found')
125
289
 
126
- model = Converter.test_result_to_autotest_post_model(
127
- test_result,
128
- self.__config.get_project_id())
290
+ model = self.__prepare_to_create_autotest(test_result)
129
291
 
130
292
  autotest_response = self.__autotest_api.create_auto_test(auto_test_post_model=model)
131
293
 
@@ -134,18 +296,31 @@ class ApiClientWorker:
134
296
  return autotest_response.id
135
297
 
136
298
  @adapter_logger
137
- def __update_test(self, test_result: TestResult, is_flaky: bool):
299
+ def __create_tests(self, autotests_for_create: typing.List[AutoTestPostModel]):
300
+ logging.debug(f'Creating autotests: "{autotests_for_create}')
301
+
302
+ self.__autotest_api.create_multiple(auto_test_post_model=autotests_for_create)
303
+
304
+ logging.debug(f'Autotests were created')
305
+
306
+ @adapter_logger
307
+ def __update_test(self, test_result: TestResult, autotest: AutoTestModel):
138
308
  logging.debug(f'Autotest "{test_result.get_autotest_name()}" was found')
139
309
 
140
- model = Converter.test_result_to_autotest_put_model(
141
- test_result,
142
- self.__config.get_project_id())
143
- model.is_flaky = is_flaky
310
+ model = self.__prepare_to_update_autotest(test_result, autotest)
144
311
 
145
312
  self.__autotest_api.update_auto_test(auto_test_put_model=model)
146
313
 
147
314
  logging.debug(f'Autotest "{test_result.get_autotest_name()}" was updated')
148
315
 
316
+ @adapter_logger
317
+ def __update_tests(self, autotests_for_update: typing.List[AutoTestPutModel]):
318
+ logging.debug(f'Updating autotests: {autotests_for_update}')
319
+
320
+ self.__autotest_api.update_multiple(auto_test_put_model=autotests_for_update)
321
+
322
+ logging.debug(f'Autotests were updated')
323
+
149
324
  @adapter_logger
150
325
  @retry
151
326
  def __unlink_test_to_work_item(self, autotest_global_id: str, work_item_id: str):
@@ -179,12 +354,23 @@ class ApiClientWorker:
179
354
 
180
355
  return Converter.get_test_result_id_from_testrun_result_post_response(response)
181
356
 
357
+ @adapter_logger
358
+ def __load_test_results(self, test_results: typing.List[AutoTestResultsForTestRunModel]):
359
+ logging.debug(f'Loading test results: {test_results}')
360
+
361
+ self.__test_run_api.set_auto_test_results_for_test_run(
362
+ id=self.__config.get_test_run_id(),
363
+ auto_test_results_for_test_run_model=test_results)
364
+
182
365
  @adapter_logger
183
366
  def get_test_result_by_id(self, test_result_id: str) -> TestResultModel:
184
367
  return self.__test_results_api.api_v2_test_results_id_get(id=test_result_id)
185
368
 
186
369
  @adapter_logger
187
- def update_test_results(self, test_results: typing.List[TestResultWithAllFixtureStepResults]):
370
+ def update_test_results(self, fixtures_containers: dict, test_result_ids: dict):
371
+ test_results = Converter.fixtures_containers_to_test_results_with_all_fixture_step_results(
372
+ fixtures_containers, test_result_ids)
373
+
188
374
  for test_result in test_results:
189
375
  model = Converter.convert_test_result_model_to_test_results_id_put_request(
190
376
  self.get_test_result_by_id(test_result.get_test_result_id()))
@@ -98,7 +98,8 @@ class Converter:
98
98
  description=test_result.get_description(),
99
99
  links=cls.links_to_links_post_model(test_result.get_links()),
100
100
  labels=test_result.get_labels(),
101
- should_create_work_item=test_result.get_automatic_creation_test_cases()
101
+ should_create_work_item=test_result.get_automatic_creation_test_cases(),
102
+ external_key=test_result.get_external_key()
102
103
  )
103
104
 
104
105
  @classmethod
@@ -123,7 +124,8 @@ class Converter:
123
124
  title=test_result.get_title(),
124
125
  description=test_result.get_description(),
125
126
  links=cls.links_to_links_put_model(test_result.get_links()),
126
- labels=test_result.get_labels()
127
+ labels=test_result.get_labels(),
128
+ external_key=test_result.get_external_key()
127
129
  )
128
130
  else:
129
131
  return AutoTestPutModel(
@@ -141,7 +143,8 @@ class Converter:
141
143
  title=test_result.get_title(),
142
144
  description=test_result.get_description(),
143
145
  links=cls.links_to_links_put_model(test_result.get_links()),
144
- labels=test_result.get_labels()
146
+ labels=test_result.get_labels(),
147
+ external_key=test_result.get_external_key()
145
148
  )
146
149
 
147
150
  @classmethod
@@ -328,6 +331,29 @@ class Converter:
328
331
 
329
332
  return autotest_model_step_results
330
333
 
334
+ @staticmethod
335
+ @adapter_logger
336
+ def fixtures_containers_to_test_results_with_all_fixture_step_results(
337
+ fixtures_containers: dict,
338
+ test_result_ids: dict) -> typing.List[TestResultWithAllFixtureStepResults]:
339
+ test_results_with_all_fixture_step_results = []
340
+
341
+ for external_id, test_result_id in test_result_ids.items():
342
+ test_result_with_all_fixture_step_results = TestResultWithAllFixtureStepResults(test_result_id)
343
+
344
+ for uuid, fixtures_container in fixtures_containers.items():
345
+ if external_id in fixtures_container.external_ids:
346
+ if fixtures_container.befores:
347
+ test_result_with_all_fixture_step_results.set_setup_results(fixtures_container.befores[0].steps)
348
+
349
+ if fixtures_container.afters:
350
+ test_result_with_all_fixture_step_results.set_teardown_results(
351
+ fixtures_container.afters[0].steps)
352
+
353
+ test_results_with_all_fixture_step_results.append(test_result_with_all_fixture_step_results)
354
+
355
+ return test_results_with_all_fixture_step_results
356
+
331
357
  @classmethod
332
358
  @adapter_logger
333
359
  def step_results_to_auto_test_step_result_update_request(
@@ -0,0 +1,24 @@
1
+ from attr import attrs, attrib
2
+ from attr import Factory
3
+
4
+
5
+ @attrs
6
+ class FixtureResult:
7
+ title = attrib(default=None)
8
+ outcome = attrib(default=None)
9
+ description = attrib(default=None)
10
+ message = attrib(default=None)
11
+ stacktrace = attrib(default=None)
12
+ steps = attrib(default=None)
13
+ attachments = attrib(default=Factory(list))
14
+ parameters = attrib(default=Factory(list))
15
+ start = attrib(default=None)
16
+ stop = attrib(default=None)
17
+
18
+
19
+ @attrs
20
+ class FixturesContainer:
21
+ uuid = attrib(default=None)
22
+ external_ids = attrib(default=Factory(list))
23
+ befores = attrib(default=Factory(list))
24
+ afters = attrib(default=Factory(list))
@@ -29,6 +29,7 @@ class TestResult:
29
29
  __parameters: dict = {}
30
30
  __properties: dict = {}
31
31
  __automatic_creation_test_cases: bool = False
32
+ __external_key: str = None
32
33
 
33
34
  @adapter_logger
34
35
  def set_external_id(self, external_id: str):
@@ -259,3 +260,13 @@ class TestResult:
259
260
  @adapter_logger
260
261
  def get_automatic_creation_test_cases(self) -> bool:
261
262
  return self.__automatic_creation_test_cases
263
+
264
+ @adapter_logger
265
+ def set_external_key(self, external_key: str):
266
+ self.__external_key = external_key
267
+
268
+ return self
269
+
270
+ @adapter_logger
271
+ def get_external_key(self) -> str:
272
+ return self.__external_key
@@ -2,6 +2,7 @@ from pluggy import HookimplMarker
2
2
 
3
3
  from testit_python_commons.services.adapter_manager import AdapterManager
4
4
  from testit_python_commons.services.plugin_manager import TmsPluginManager
5
+ from testit_python_commons.services.fixture_manager import FixtureManager
5
6
  from testit_python_commons.services.step_manager import StepManager
6
7
  from testit_python_commons.services.utils import Utils
7
8
 
@@ -10,6 +11,7 @@ hookimpl = HookimplMarker("testit")
10
11
  __all__ = [
11
12
  'AdapterManager',
12
13
  'TmsPluginManager',
14
+ 'FixtureManager',
13
15
  'StepManager',
14
16
  'Utils',
15
17
  'hookimpl'
@@ -1,12 +1,11 @@
1
1
  import os
2
- import typing
3
2
  import uuid
4
3
 
5
4
  from testit_python_commons.client.api_client import ApiClientWorker
6
5
  from testit_python_commons.client.client_configuration import ClientConfiguration
7
6
  from testit_python_commons.models.adapter_mode import AdapterMode
8
7
  from testit_python_commons.models.test_result import TestResult
9
- from testit_python_commons.models.test_result_with_all_fixture_step_results_model import TestResultWithAllFixtureStepResults
8
+ from testit_python_commons.services.fixture_manager import FixtureManager
10
9
  from testit_python_commons.services.adapter_manager_configuration import AdapterManagerConfiguration
11
10
  from testit_python_commons.services.logger import adapter_logger
12
11
  from testit_python_commons.services.utils import Utils
@@ -16,9 +15,13 @@ class AdapterManager:
16
15
  def __init__(
17
16
  self,
18
17
  adapter_configuration: AdapterManagerConfiguration,
19
- client_configuration: ClientConfiguration):
18
+ client_configuration: ClientConfiguration,
19
+ fixture_manager: FixtureManager):
20
20
  self.__config = adapter_configuration
21
21
  self.__api_client = ApiClientWorker(client_configuration)
22
+ self.__fixture_manager = fixture_manager
23
+ self.__test_result_map = {}
24
+ self.__test_results = []
22
25
 
23
26
  @adapter_logger
24
27
  def set_test_run_id(self, test_run_id: str):
@@ -40,15 +43,39 @@ class AdapterManager:
40
43
  return
41
44
 
42
45
  @adapter_logger
43
- def write_test(self, test_result: TestResult) -> str:
46
+ def write_test(self, test_result: TestResult):
47
+ if self.__config.should_import_realtime():
48
+ self.__write_test_realtime(test_result)
49
+
50
+ return
51
+
52
+ self.__test_results.append(test_result)
53
+
54
+ @adapter_logger
55
+ def __write_test_realtime(self, test_result: TestResult):
44
56
  test_result.set_automatic_creation_test_cases(
45
57
  self.__config.should_automatic_creation_test_cases())
46
58
 
47
- return self.__api_client.write_test(test_result)
59
+ self.__test_result_map[test_result.get_external_id()] = self.__api_client.write_test(test_result)
48
60
 
49
61
  @adapter_logger
50
- def load_setup_and_teardown_step_results(self, test_results: typing.List[TestResultWithAllFixtureStepResults]):
51
- self.__api_client.update_test_results(test_results)
62
+ def write_tests(self):
63
+ if self.__config.should_import_realtime():
64
+ self.__load_setup_and_teardown_step_results()
65
+
66
+ return
67
+
68
+ self.__write_tests_after_all()
69
+
70
+ @adapter_logger
71
+ def __load_setup_and_teardown_step_results(self):
72
+ self.__api_client.update_test_results(self.__fixture_manager.get_all_items(), self.__test_result_map)
73
+
74
+ @adapter_logger
75
+ def __write_tests_after_all(self):
76
+ fixtures = self.__fixture_manager.get_all_items()
77
+
78
+ self.__api_client.write_tests(self.__test_results, fixtures)
52
79
 
53
80
  @adapter_logger
54
81
  def load_attachments(self, attach_paths: list or tuple):
@@ -11,13 +11,9 @@ class AdapterManagerConfiguration:
11
11
  self.__test_run_id = Utils.uuid_check(app_properties.get('testrunid'))
12
12
 
13
13
  self.__adapter_mode = app_properties.get('adaptermode', AdapterMode.USE_FILTER)
14
-
15
- __automatic_creation_test_cases = app_properties.get('automaticcreationtestcases')
16
-
17
- if __automatic_creation_test_cases and __automatic_creation_test_cases == 'true':
18
- self.__automatic_creation_test_cases = True
19
- else:
20
- self.__automatic_creation_test_cases = False
14
+ self.__automatic_creation_test_cases = Utils.convert_value_str_to_bool(
15
+ app_properties.get('automaticcreationtestcases'))
16
+ self.__import_realtime = Utils.convert_value_str_to_bool(app_properties.get('importrealtime'))
21
17
 
22
18
  @adapter_logger
23
19
  def get_test_run_id(self):
@@ -32,5 +28,9 @@ class AdapterManagerConfiguration:
32
28
  return self.__adapter_mode
33
29
 
34
30
  @adapter_logger
35
- def should_automatic_creation_test_cases(self):
31
+ def should_automatic_creation_test_cases(self) -> bool:
36
32
  return self.__automatic_creation_test_cases
33
+
34
+ @adapter_logger
35
+ def should_import_realtime(self) -> bool:
36
+ return self.__import_realtime
@@ -0,0 +1,60 @@
1
+ from testit_python_commons.services.fixture_storage import ThreadContextFixtures
2
+ from testit_python_commons.models.step_result import StepResult
3
+
4
+
5
+ class FixtureManager:
6
+ def __init__(self):
7
+ self._items = ThreadContextFixtures()
8
+ self._orphan_items = []
9
+
10
+ def _update_item(self, uuid, **kwargs):
11
+ item = self._items[uuid] if uuid else self._items[next(reversed(self._items))]
12
+ for name, value in kwargs.items():
13
+ attr = getattr(item, name)
14
+ if isinstance(attr, list):
15
+ attr.append(value)
16
+ else:
17
+ setattr(item, name, value)
18
+
19
+ def _last_executable(self):
20
+ for _uuid in reversed(self._items):
21
+ if isinstance(self._items[_uuid], StepResult):
22
+ return _uuid
23
+
24
+ def get_item(self, uuid):
25
+ return self._items.get(uuid)
26
+
27
+ def get_last_item(self, item_type=None):
28
+ for _uuid in reversed(self._items):
29
+ if item_type is None:
30
+ return self._items.get(_uuid)
31
+ if type(self._items[_uuid]) == item_type:
32
+ return self._items.get(_uuid)
33
+
34
+ def start_group(self, uuid, group):
35
+ self._items[uuid] = group
36
+
37
+ def stop_group(self, uuid, **kwargs):
38
+ self._update_item(uuid, **kwargs)
39
+
40
+ def update_group(self, uuid, **kwargs):
41
+ self._update_item(uuid, **kwargs)
42
+
43
+ def start_before_fixture(self, parent_uuid, uuid, fixture):
44
+ self._items.get(parent_uuid).befores.append(fixture)
45
+ self._items[uuid] = fixture
46
+
47
+ def stop_before_fixture(self, uuid, **kwargs):
48
+ self._update_item(uuid, **kwargs)
49
+ self._items.pop(uuid)
50
+
51
+ def start_after_fixture(self, parent_uuid, uuid, fixture):
52
+ self._items.get(parent_uuid).afters.append(fixture)
53
+ self._items[uuid] = fixture
54
+
55
+ def stop_after_fixture(self, uuid, **kwargs):
56
+ self._update_item(uuid, **kwargs)
57
+ self._items.pop(uuid)
58
+
59
+ def get_all_items(self):
60
+ return self._items.get_all()
@@ -0,0 +1,40 @@
1
+ import threading
2
+ from collections import OrderedDict, defaultdict
3
+
4
+
5
+ class ThreadContextFixtures:
6
+ _thread_context = defaultdict(OrderedDict)
7
+ _init_thread: threading.Thread
8
+
9
+ @property
10
+ def thread_context(self):
11
+ context = self._thread_context[threading.current_thread()]
12
+ if not context and threading.current_thread() is not self._init_thread:
13
+ uuid, last_item = next(reversed(self._thread_context[self._init_thread].items()))
14
+ context[uuid] = last_item
15
+ return context
16
+
17
+ def __init__(self, *args, **kwargs):
18
+ self._init_thread = threading.current_thread()
19
+ super().__init__(*args, **kwargs)
20
+
21
+ def __setitem__(self, key, value):
22
+ self.thread_context.__setitem__(key, value)
23
+
24
+ def __getitem__(self, item):
25
+ return self.thread_context.__getitem__(item)
26
+
27
+ def __iter__(self):
28
+ return self.thread_context.__iter__()
29
+
30
+ def __reversed__(self):
31
+ return self.thread_context.__reversed__()
32
+
33
+ def get(self, key):
34
+ return self.thread_context.get(key)
35
+
36
+ def pop(self, key):
37
+ return self.thread_context.pop(key)
38
+
39
+ def get_all(self):
40
+ return dict(self.thread_context.items())
@@ -9,6 +9,7 @@ from testit_python_commons.app_properties import AppProperties
9
9
  class TmsPluginManager:
10
10
  __plugin_manager = None
11
11
  __adapter_manager = None
12
+ __fixture_manager = None
12
13
  __step_manager = None
13
14
  __logger = None
14
15
 
@@ -32,11 +33,21 @@ class TmsPluginManager:
32
33
 
33
34
  client_configuration = ClientConfiguration(app_properties)
34
35
  adapter_configuration = AdapterManagerConfiguration(app_properties)
36
+ fixture_manager = cls.get_fixture_manager()
35
37
 
36
- cls.__adapter_manager = AdapterManager(adapter_configuration, client_configuration)
38
+ cls.__adapter_manager = AdapterManager(adapter_configuration, client_configuration, fixture_manager)
37
39
 
38
40
  return cls.__adapter_manager
39
41
 
42
+ @classmethod
43
+ def get_fixture_manager(cls):
44
+ if cls.__fixture_manager is None:
45
+ from testit_python_commons.services.fixture_manager import FixtureManager
46
+
47
+ cls.__fixture_manager = FixtureManager()
48
+
49
+ return cls.__fixture_manager
50
+
40
51
  @classmethod
41
52
  def get_step_manager(cls) -> StepManager:
42
53
  if cls.__step_manager is None:
@@ -115,3 +115,11 @@ class Utils:
115
115
  return body
116
116
 
117
117
  return str(body).encode('utf-8')
118
+
119
+ @staticmethod
120
+ @adapter_logger
121
+ def convert_value_str_to_bool(value: str) -> bool:
122
+ if value:
123
+ return value == 'true'
124
+
125
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: testit-python-commons
3
- Version: 3.3.1
3
+ Version: 3.4.0
4
4
  Summary: Python commons for Test IT
5
5
  Home-page: https://github.com/testit-tms/adapters-python/
6
6
  Author: Integration team
@@ -17,6 +17,7 @@ src/testit_python_commons/client/client_configuration.py
17
17
  src/testit_python_commons/client/converter.py
18
18
  src/testit_python_commons/models/__init__.py
19
19
  src/testit_python_commons/models/adapter_mode.py
20
+ src/testit_python_commons/models/fixture.py
20
21
  src/testit_python_commons/models/link.py
21
22
  src/testit_python_commons/models/link_type.py
22
23
  src/testit_python_commons/models/outcome_type.py
@@ -26,6 +27,8 @@ src/testit_python_commons/models/test_result_with_all_fixture_step_results_model
26
27
  src/testit_python_commons/services/__init__.py
27
28
  src/testit_python_commons/services/adapter_manager.py
28
29
  src/testit_python_commons/services/adapter_manager_configuration.py
30
+ src/testit_python_commons/services/fixture_manager.py
31
+ src/testit_python_commons/services/fixture_storage.py
29
32
  src/testit_python_commons/services/logger.py
30
33
  src/testit_python_commons/services/plugin_manager.py
31
34
  src/testit_python_commons/services/retry.py