Skip to content

Commit 89e04e0

Browse files
authored
Export reporter (#29)
* show traceback verbosity on --debug-testipy * replace dict by TestMethodAttr * replace dict by TestMethodAttr * implement attr for read and execution * replace dict by TestMethodAttr * switch order for attr and name * rename reporter to junit * fix test step end reason when exception * rename variable * remove tests from this repo * fix suite name * fix suite name * improve assertions * fix meid to be global
1 parent 09df1ed commit 89e04e0

5 files changed

Lines changed: 93 additions & 72 deletions

File tree

testipy/engine/models.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def __init__(self, package_attr: "PackageAttr", filename: str, suite_name: str,
104104
self.test_method_attr_list: List[TestMethodAttr] = test_method_attr_list or []
105105
self.ncycles: int = ncycles
106106

107-
self.name: str = name or filename
107+
self.name: str = name or suite_name or filename
108108
self.comment: str = comment
109109
self.prio: int = prio
110110
self.level: int = level
@@ -184,6 +184,11 @@ def get_max_suite_id(self) -> int:
184184
_max_id = max([suite_attr.suite_id for suite_attr in self.suite_attr_list]) if _max_rec > 0 else 0
185185
return max(_max_rec, _max_id) + 1
186186

187+
def get_max_test_method_id(self):
188+
_max_rec = len(self.suite_attr_list)
189+
_max_id = max([suite_attr.get_max_test_method_id() for suite_attr in self.suite_attr_list]) if _max_rec > 0 else 0
190+
return max(_max_rec+1, _max_id)
191+
187192
def duplicate(self, clone_children: bool = True):
188193
_new_attr = PackageAttr(
189194
package_name=self.package_name,
Lines changed: 72 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import List, Dict
1+
from typing import List, Dict, Any
22

33

44
class HandledError(AssertionError):
@@ -59,61 +59,77 @@ def assert_expected_value(expected, received, where: str = "response"):
5959
raise UnexpectedValueError(f"Expected {where}='{expected}', not '{received}'")
6060

6161

62-
# It only works if there is no duplicated data inside lists. lst1=expected, lst2=received
63-
def assert_equal_unique_lists(lst1: List, lst2: List, name_list1: str = "list1", name_list2: str = "list2", strict=True, **kwargs):
64-
assert_expected_type(lst1, (list, tuple, set), where=name_list1)
65-
assert_expected_type(lst2, (list, tuple, set), where=name_list2)
66-
if strict:
67-
assert_same_len(lst1, lst2, where=f"{name_list1} vs {name_list2}")
68-
69-
for x in lst1:
70-
if isinstance(x, (list, tuple, set, dict)):
71-
for z in lst2: # iterate every element z from list2 and compare if equal to element x from list1
72-
if isinstance(z, type(x)):
73-
try:
74-
if isinstance(x, dict):
75-
assert_data(x, z, where=name_list1)
76-
else:
77-
assert_equal_unique_lists(x, z, name_list1=name_list1, name_list2=name_list2)
78-
except:
79-
pass # so this z is not equal, continue to next z
80-
else:
81-
break # found z == x, continue with next x on lst1
82-
else:
83-
raise AssertionError(f"{type(x)} from {name_list1} not found in {name_list2}. {x}")
84-
else:
85-
if x not in lst2:
86-
raise UnexpectedValueError(f"Value '{x}' from {name_list1} not in {name_list2}")
87-
88-
89-
# It only works if there is no duplicated data inside lists
90-
def assert_data(expected_values: Dict, response: Dict, where="", strict: bool = False, **kwargs):
91-
if isinstance(expected_values, dict):
92-
if strict and len(expected_values) != len(response):
93-
raise ExpectedFieldMissingError(f"Not same amount of keys: {expected_values.keys()=} not {response.keys()=}")
94-
95-
for field, value in expected_values.items():
96-
if field not in response:
97-
raise ExpectedFieldMissingError(f"{field=} not in {where}")
98-
if isinstance(value, (list, tuple, set)):
99-
assert_expected_type(response[field], type(value), where=f"{where}.{field}")
100-
assert_equal_unique_lists(value, response[field], f"{where}/{field}[expected]", f"{where}/{field}[response]")
101-
elif isinstance(value, dict):
102-
assert_expected_type(response[field], dict, where=f"{where}.{field}")
103-
assert_data(value, response[field], where=f"{where}/{field}")
104-
else:
105-
assert_expected_value(value, response[field], where=f"{where}.{field}")
106-
elif isinstance(expected_values, list):
107-
assert_equal_unique_lists(expected_values, response, name_list1="expected", name_list2="received", strict=strict)
108-
elif isinstance(expected_values, str):
109-
assert expected_values == response, f"{where} Expected value does not meet received."
110-
else:
111-
if strict:
112-
assert expected_values == response, f"{where} Expected value does not meet received."
113-
else:
114-
assert expected_values in response, f"{where} Expected value not part of received."
115-
116-
11762
def assert_status_code(expected_status_code, received_status_code):
11863
if expected_status_code != received_status_code:
11964
raise UnexpectedValueError(f"Unexpected status_code {received_status_code}, expected {expected_status_code}")
65+
66+
67+
def assert_equal_complex_object(
68+
expected: Any,
69+
received: Any,
70+
expected_name: str = "expected",
71+
received_name: str = "received",
72+
) -> None:
73+
if isinstance(expected, dict) and isinstance(received, dict):
74+
assert_equal_dicts(
75+
expected, received, expected_name=expected_name, received_name=received_name
76+
)
77+
elif isinstance(expected, (list, tuple, set)) and isinstance(
78+
received, (list, tuple, set)
79+
):
80+
assert_equal_lists(
81+
expected, received, expected_name=expected_name, received_name=received_name
82+
)
83+
else:
84+
assert (
85+
expected == received
86+
), f"{expected_name} = '{expected}' not equal to {received_name} = '{received}'"
87+
88+
89+
def assert_equal_dicts(
90+
expected: Any,
91+
received: Any,
92+
expected_name: str = "expected",
93+
received_name: str = "received",
94+
) -> None:
95+
for key in expected:
96+
assert key in received, f"{expected_name}.{key} is not in dict {received_name}"
97+
assert_equal_complex_object(
98+
expected[key],
99+
received[key],
100+
expected_name=f"{expected_name}.{key}",
101+
received_name=f"{received_name}.{key}",
102+
)
103+
104+
105+
def assert_equal_lists(
106+
expected: Any,
107+
received: Any,
108+
expected_name: str = "expected",
109+
received_name: str = "received",
110+
same_len: bool = True,
111+
) -> None:
112+
if same_len:
113+
assert (
114+
len(expected) == len(received)
115+
), f"{expected_name} has {len(expected)} elements != {received_name} has {len(received)} elements"
116+
117+
list2 = list(received)
118+
for i1, v1 in enumerate(expected):
119+
for i2, v2 in enumerate(list2):
120+
try:
121+
assert_equal_complex_object(
122+
v1,
123+
v2,
124+
expected_name=f"{expected_name}[{i1}]",
125+
received_name=f"{received_name}[{i2}]",
126+
)
127+
except AssertionError:
128+
pass
129+
else:
130+
list2.remove(v2)
131+
break
132+
else:
133+
raise AssertionError(
134+
f"{expected_name}[{i1}] '{v1}' is not inside {received_name}"
135+
)

testipy/helpers/rest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from requests import Response
44

55

6-
from testipy.helpers.handle_assertions import assert_status_code, ExpectedError, assert_data
6+
from testipy.helpers.handle_assertions import assert_status_code, ExpectedError, assert_equal_complex_object
77

88

99
def get_response():
@@ -45,7 +45,7 @@ def handle_http_response_wrapper(*args, **kwargs):
4545

4646
assert isinstance(response, expected_type), f"must receive a {type(expected_type)} not a {type(response)}"
4747
if expected_response:= default_kwargs.get("expected_response"):
48-
assert_data(expected_values=expected_response, response=response)
48+
assert_equal_complex_object(expected=expected_response, received=response)
4949

5050
return response
5151
else:
@@ -62,7 +62,7 @@ def handle_http_response_wrapper(*args, **kwargs):
6262
else:
6363
handle_http_response.body = received_response = response.text
6464

65-
assert_data(expected_values=expected_response, response=received_response)
65+
assert_equal_complex_object(expected=expected_response, received=received_response)
6666
else:
6767
try:
6868
handle_http_response.body = response.json()

testipy/reporter/report_manager.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def start_suite(self, sd: SuiteDetails):
128128
try:
129129
reporter.start_suite(sd)
130130
except Exception as e:
131-
_exec_logger.critical(f"Internal error rm.startSuite on {reporter_name}: {e}")
131+
_exec_logger.critical(f"Internal error rm.start_suite on {reporter_name}: {e}")
132132
if self.is_debugcode():
133133
raise
134134
return sd
@@ -155,7 +155,7 @@ def test_info(self, current_test: TestDetails, info: str, level: str = "DEBUG",
155155
try:
156156
reporter.test_info(current_test, info, str(level).upper(), attachment)
157157
except Exception as e:
158-
_exec_logger.critical(f"Internal error rm.testInfo on {reporter_name}: {e}")
158+
_exec_logger.critical(f"Internal error rm.test_info on {reporter_name}: {e}")
159159
if self.is_debugcode():
160160
raise
161161

@@ -169,15 +169,15 @@ def test_step(self, current_test: TestDetails, state: str, reason_of_state: str
169169
try:
170170
self.get_bm().take_screenshot(current_test)
171171
except Exception as e:
172-
_exec_logger.critical(f"Internal error rm.testStep.screenshot on {self.get_bm().name}: {e}")
172+
_exec_logger.critical(f"Internal error rm.test_step.screenshot on {self.get_bm().name}: {e}")
173173
if self.is_debugcode():
174174
raise
175175

176176
for reporter_name, reporter in self._reporters_list.items():
177177
try:
178178
reporter.test_step(current_test, state, reason_of_state=str(reason_of_state), description=str(description), take_screenshot=take_screenshot, qty=qty, exc_value=exc_value)
179179
except Exception as e:
180-
_exec_logger.critical(f"Internal error rm.testStep on {reporter_name}: {e}")
180+
_exec_logger.critical(f"Internal error rm.test_step on {reporter_name}: {e}")
181181
if self.is_debugcode():
182182
raise
183183

@@ -202,7 +202,7 @@ def end_test(self, current_test: TestDetails, state: str = enums_data.STATE_PASS
202202
try:
203203
reporter.end_test(current_test, state, reason_of_state, exc_value)
204204
except Exception as e:
205-
_exec_logger.critical(f"Internal error rm.endTest({state}) on {reporter_name}: {e}")
205+
_exec_logger.critical(f"Internal error rm.end_test({state}) on {reporter_name}: {e}")
206206
if self.is_debugcode():
207207
raise
208208

@@ -213,7 +213,7 @@ def end_suite(self, sd: SuiteDetails):
213213
try:
214214
reporter.end_suite(sd)
215215
except Exception as e:
216-
_exec_logger.critical(f"Internal error rm.endSuite on {reporter_name}: {e}")
216+
_exec_logger.critical(f"Internal error rm.end_suite on {reporter_name}: {e}")
217217
if self.is_debugcode():
218218
raise
219219

@@ -224,7 +224,7 @@ def end_package(self, pd: PackageDetails):
224224
try:
225225
reporter.end_package(pd)
226226
except Exception as e:
227-
_exec_logger.critical(f"Internal error rm.endPackage on {reporter_name}: {e}")
227+
_exec_logger.critical(f"Internal error rm.end_package on {reporter_name}: {e}")
228228
if self.is_debugcode():
229229
raise
230230

@@ -234,7 +234,7 @@ def show_status(self, message: str):
234234
try:
235235
reporter.show_status(message)
236236
except Exception as e:
237-
_exec_logger.critical(f"Internal error rm.showStatus on {reporter_name}: {e}")
237+
_exec_logger.critical(f"Internal error rm.show_status on {reporter_name}: {e}")
238238
if self.is_debugcode():
239239
raise
240240

@@ -244,7 +244,7 @@ def show_alert_message(self, message: str):
244244
try:
245245
reporter.show_alert_message(message)
246246
except Exception as e:
247-
_exec_logger.critical(f"Internal error rm.showMessage on {reporter_name}: {e}")
247+
_exec_logger.critical(f"Internal error rm.show_alert_message on {reporter_name}: {e}")
248248
if self.is_debugcode():
249249
raise
250250

@@ -257,7 +257,7 @@ def input_prompt_message(self, message: str, default_value: str = "") -> str:
257257
if result is None and res:
258258
result = res
259259
except Exception as e:
260-
_exec_logger.critical(f"Internal error rm.inputMessage on {reporter_name}: {e}")
260+
_exec_logger.critical(f"Internal error rm.input_prompt_message on {reporter_name}: {e}")
261261
if self.is_debugcode():
262262
raise
263263

testipy/reporter/reporters/reporter_excel.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ def end_test(self, current_test: TestDetails, ending_state: str, end_reason: str
112112
package_name = current_test.suite.package.get_name()
113113
package_cycle = current_test.suite.package.get_cycle()
114114

115-
suite_name = current_test.get_name()
116-
suite_cycle = current_test.get_cycle()
115+
suite_name = current_test.suite.get_name()
116+
suite_cycle = current_test.suite.get_cycle()
117117

118118
test_name = current_test.get_name()
119119
test_cycle = current_test.get_cycle()

0 commit comments

Comments
 (0)