orionis 0.313.0__py3-none-any.whl → 0.315.0__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.
- orionis/container/container.py +433 -56
- orionis/metadata/framework.py +1 -1
- orionis/services/introspection/instances/reflection_instance.py +73 -5
- orionis/services/introspection/reflection.py +373 -23
- orionis/test/contracts/printer.py +188 -0
- orionis/test/contracts/test_unit.py +42 -16
- orionis/test/output/printer.py +448 -0
- orionis/test/suite/test_unit.py +576 -656
- {orionis-0.313.0.dist-info → orionis-0.315.0.dist-info}/METADATA +1 -1
- {orionis-0.313.0.dist-info → orionis-0.315.0.dist-info}/RECORD +16 -13
- tests/services/inspection/test_reflection.py +462 -0
- tests/testing/test_testing_unit.py +4 -9
- {orionis-0.313.0.dist-info → orionis-0.315.0.dist-info}/WHEEL +0 -0
- {orionis-0.313.0.dist-info → orionis-0.315.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.313.0.dist-info → orionis-0.315.0.dist-info}/top_level.txt +0 -0
- {orionis-0.313.0.dist-info → orionis-0.315.0.dist-info}/zip-safe +0 -0
@@ -1,3 +1,4 @@
|
|
1
|
+
import inspect
|
1
2
|
from typing import Any, Type
|
2
3
|
from orionis.services.introspection.abstract.reflection_abstract import ReflectionAbstract
|
3
4
|
from orionis.services.introspection.concretes.reflection_concrete import ReflectionConcrete
|
@@ -11,80 +12,429 @@ class Reflection:
|
|
11
12
|
This class offers factory methods to obtain specialized reflection objects for instances,
|
12
13
|
abstract classes, concrete classes, and modules. Each method returns an object that
|
13
14
|
encapsulates the target and provides introspection capabilities.
|
14
|
-
|
15
|
-
Methods
|
16
|
-
-------
|
17
|
-
instance(instance: Any) -> ReflectionInstance
|
18
|
-
Create a reflection object for a class instance.
|
19
|
-
abstract(abstract: Type) -> ReflectionAbstract
|
20
|
-
Create a reflection object for an abstract class.
|
21
|
-
concrete(concrete: Type) -> ReflectionConcrete
|
22
|
-
Create a reflection object for a concrete class.
|
23
|
-
module(module: str) -> ReflectionModule
|
24
|
-
Create a reflection object for a module.
|
25
15
|
"""
|
26
16
|
|
27
17
|
@staticmethod
|
28
18
|
def instance(instance: Any) -> 'ReflectionInstance':
|
29
19
|
"""
|
30
|
-
Create a
|
20
|
+
Create a ReflectionInstance for the given object instance.
|
31
21
|
|
32
22
|
Parameters
|
33
23
|
----------
|
34
24
|
instance : Any
|
35
|
-
The instance to reflect
|
25
|
+
The object instance to reflect.
|
36
26
|
|
37
27
|
Returns
|
38
28
|
-------
|
39
29
|
ReflectionInstance
|
40
|
-
A reflection object
|
30
|
+
A reflection object for the given instance.
|
41
31
|
"""
|
42
32
|
return ReflectionInstance(instance)
|
43
33
|
|
44
34
|
@staticmethod
|
45
35
|
def abstract(abstract: Type) -> 'ReflectionAbstract':
|
46
|
-
"""
|
36
|
+
"""
|
37
|
+
Create a ReflectionAbstract for the given abstract class.
|
47
38
|
|
48
39
|
Parameters
|
49
40
|
----------
|
50
41
|
abstract : Type
|
51
|
-
The abstract class to reflect
|
42
|
+
The abstract class to reflect.
|
52
43
|
|
53
44
|
Returns
|
54
45
|
-------
|
55
46
|
ReflectionAbstract
|
56
|
-
A reflection object
|
47
|
+
A reflection object for the given abstract class.
|
57
48
|
"""
|
58
49
|
return ReflectionAbstract(abstract)
|
59
50
|
|
60
51
|
@staticmethod
|
61
52
|
def concrete(concrete: Type) -> 'ReflectionConcrete':
|
62
|
-
"""
|
53
|
+
"""
|
54
|
+
Create a ReflectionConcrete for the given concrete class.
|
63
55
|
|
64
56
|
Parameters
|
65
57
|
----------
|
66
58
|
concrete : Type
|
67
|
-
The concrete class to reflect
|
59
|
+
The concrete class to reflect.
|
68
60
|
|
69
61
|
Returns
|
70
62
|
-------
|
71
63
|
ReflectionConcrete
|
72
|
-
A reflection object
|
64
|
+
A reflection object for the given concrete class.
|
73
65
|
"""
|
74
66
|
return ReflectionConcrete(concrete)
|
75
67
|
|
76
68
|
@staticmethod
|
77
69
|
def module(module: str) -> 'ReflectionModule':
|
78
|
-
"""
|
70
|
+
"""
|
71
|
+
Create a ReflectionModule for the given module name.
|
79
72
|
|
80
73
|
Parameters
|
81
74
|
----------
|
82
75
|
module : str
|
83
|
-
The module
|
76
|
+
The name of the module to reflect.
|
84
77
|
|
85
78
|
Returns
|
86
79
|
-------
|
87
80
|
ReflectionModule
|
88
|
-
A reflection object
|
81
|
+
A reflection object for the given module.
|
89
82
|
"""
|
90
83
|
return ReflectionModule(module)
|
84
|
+
|
85
|
+
@staticmethod
|
86
|
+
def isAbstract(obj: Any) -> bool:
|
87
|
+
"""
|
88
|
+
Check if the object is an abstract base class.
|
89
|
+
|
90
|
+
Parameters
|
91
|
+
----------
|
92
|
+
obj : Any
|
93
|
+
The object to check.
|
94
|
+
|
95
|
+
Returns
|
96
|
+
-------
|
97
|
+
bool
|
98
|
+
True if the object is abstract, False otherwise.
|
99
|
+
"""
|
100
|
+
return inspect.isabstract(obj)
|
101
|
+
|
102
|
+
@staticmethod
|
103
|
+
def isAsyncGen(obj: Any) -> bool:
|
104
|
+
"""
|
105
|
+
Check if the object is an asynchronous generator.
|
106
|
+
|
107
|
+
Parameters
|
108
|
+
----------
|
109
|
+
obj : Any
|
110
|
+
The object to check.
|
111
|
+
|
112
|
+
Returns
|
113
|
+
-------
|
114
|
+
bool
|
115
|
+
True if the object is an async generator, False otherwise.
|
116
|
+
"""
|
117
|
+
return inspect.isasyncgen(obj)
|
118
|
+
|
119
|
+
@staticmethod
|
120
|
+
def isAsyncGenFunction(obj: Any) -> bool:
|
121
|
+
"""
|
122
|
+
Check if the object is an asynchronous generator function.
|
123
|
+
|
124
|
+
Parameters
|
125
|
+
----------
|
126
|
+
obj : Any
|
127
|
+
The object to check.
|
128
|
+
|
129
|
+
Returns
|
130
|
+
-------
|
131
|
+
bool
|
132
|
+
True if the object is an async generator function, False otherwise.
|
133
|
+
"""
|
134
|
+
return inspect.isasyncgenfunction(obj)
|
135
|
+
|
136
|
+
@staticmethod
|
137
|
+
def isAwaitable(obj: Any) -> bool:
|
138
|
+
"""
|
139
|
+
Check if the object can be awaited.
|
140
|
+
|
141
|
+
Parameters
|
142
|
+
----------
|
143
|
+
obj : Any
|
144
|
+
The object to check.
|
145
|
+
|
146
|
+
Returns
|
147
|
+
-------
|
148
|
+
bool
|
149
|
+
True if the object is awaitable, False otherwise.
|
150
|
+
"""
|
151
|
+
return inspect.isawaitable(obj)
|
152
|
+
|
153
|
+
@staticmethod
|
154
|
+
def isBuiltin(obj: Any) -> bool:
|
155
|
+
"""
|
156
|
+
Check if the object is a built-in function or method.
|
157
|
+
|
158
|
+
Parameters
|
159
|
+
----------
|
160
|
+
obj : Any
|
161
|
+
The object to check.
|
162
|
+
|
163
|
+
Returns
|
164
|
+
-------
|
165
|
+
bool
|
166
|
+
True if the object is a built-in, False otherwise.
|
167
|
+
"""
|
168
|
+
return inspect.isbuiltin(obj)
|
169
|
+
|
170
|
+
@staticmethod
|
171
|
+
def isClass(obj: Any) -> bool:
|
172
|
+
"""
|
173
|
+
Check if the object is a class.
|
174
|
+
|
175
|
+
Parameters
|
176
|
+
----------
|
177
|
+
obj : Any
|
178
|
+
The object to check.
|
179
|
+
|
180
|
+
Returns
|
181
|
+
-------
|
182
|
+
bool
|
183
|
+
True if the object is a class, False otherwise.
|
184
|
+
"""
|
185
|
+
return inspect.isclass(obj)
|
186
|
+
|
187
|
+
@staticmethod
|
188
|
+
def isCode(obj: Any) -> bool:
|
189
|
+
"""
|
190
|
+
Check if the object is a code object.
|
191
|
+
|
192
|
+
Parameters
|
193
|
+
----------
|
194
|
+
obj : Any
|
195
|
+
The object to check.
|
196
|
+
|
197
|
+
Returns
|
198
|
+
-------
|
199
|
+
bool
|
200
|
+
True if the object is a code object, False otherwise.
|
201
|
+
"""
|
202
|
+
return inspect.iscode(obj)
|
203
|
+
|
204
|
+
@staticmethod
|
205
|
+
def isCoroutine(obj: Any) -> bool:
|
206
|
+
"""
|
207
|
+
Check if the object is a coroutine.
|
208
|
+
|
209
|
+
Parameters
|
210
|
+
----------
|
211
|
+
obj : Any
|
212
|
+
The object to check.
|
213
|
+
|
214
|
+
Returns
|
215
|
+
-------
|
216
|
+
bool
|
217
|
+
True if the object is a coroutine, False otherwise.
|
218
|
+
"""
|
219
|
+
return inspect.iscoroutine(obj)
|
220
|
+
|
221
|
+
@staticmethod
|
222
|
+
def isCoroutineFunction(obj: Any) -> bool:
|
223
|
+
"""
|
224
|
+
Check if the object is a coroutine function.
|
225
|
+
|
226
|
+
Parameters
|
227
|
+
----------
|
228
|
+
obj : Any
|
229
|
+
The object to check.
|
230
|
+
|
231
|
+
Returns
|
232
|
+
-------
|
233
|
+
bool
|
234
|
+
True if the object is a coroutine function, False otherwise.
|
235
|
+
"""
|
236
|
+
return inspect.iscoroutinefunction(obj)
|
237
|
+
|
238
|
+
@staticmethod
|
239
|
+
def isDataDescriptor(obj: Any) -> bool:
|
240
|
+
"""
|
241
|
+
Check if the object is a data descriptor.
|
242
|
+
|
243
|
+
Parameters
|
244
|
+
----------
|
245
|
+
obj : Any
|
246
|
+
The object to check.
|
247
|
+
|
248
|
+
Returns
|
249
|
+
-------
|
250
|
+
bool
|
251
|
+
True if the object is a data descriptor, False otherwise.
|
252
|
+
"""
|
253
|
+
return inspect.isdatadescriptor(obj)
|
254
|
+
|
255
|
+
@staticmethod
|
256
|
+
def isFrame(obj: Any) -> bool:
|
257
|
+
"""
|
258
|
+
Check if the object is a frame object.
|
259
|
+
|
260
|
+
Parameters
|
261
|
+
----------
|
262
|
+
obj : Any
|
263
|
+
The object to check.
|
264
|
+
|
265
|
+
Returns
|
266
|
+
-------
|
267
|
+
bool
|
268
|
+
True if the object is a frame object, False otherwise.
|
269
|
+
"""
|
270
|
+
return inspect.isframe(obj)
|
271
|
+
|
272
|
+
@staticmethod
|
273
|
+
def isFunction(obj: Any) -> bool:
|
274
|
+
"""
|
275
|
+
Check if the object is a Python function.
|
276
|
+
|
277
|
+
Parameters
|
278
|
+
----------
|
279
|
+
obj : Any
|
280
|
+
The object to check.
|
281
|
+
|
282
|
+
Returns
|
283
|
+
-------
|
284
|
+
bool
|
285
|
+
True if the object is a function, False otherwise.
|
286
|
+
"""
|
287
|
+
return inspect.isfunction(obj)
|
288
|
+
|
289
|
+
@staticmethod
|
290
|
+
def isGenerator(obj: Any) -> bool:
|
291
|
+
"""
|
292
|
+
Check if the object is a generator.
|
293
|
+
|
294
|
+
Parameters
|
295
|
+
----------
|
296
|
+
obj : Any
|
297
|
+
The object to check.
|
298
|
+
|
299
|
+
Returns
|
300
|
+
-------
|
301
|
+
bool
|
302
|
+
True if the object is a generator, False otherwise.
|
303
|
+
"""
|
304
|
+
return inspect.isgenerator(obj)
|
305
|
+
|
306
|
+
@staticmethod
|
307
|
+
def isGeneratorFunction(obj: Any) -> bool:
|
308
|
+
"""
|
309
|
+
Check if the object is a generator function.
|
310
|
+
|
311
|
+
Parameters
|
312
|
+
----------
|
313
|
+
obj : Any
|
314
|
+
The object to check.
|
315
|
+
|
316
|
+
Returns
|
317
|
+
-------
|
318
|
+
bool
|
319
|
+
True if the object is a generator function, False otherwise.
|
320
|
+
"""
|
321
|
+
return inspect.isgeneratorfunction(obj)
|
322
|
+
|
323
|
+
@staticmethod
|
324
|
+
def isGetSetDescriptor(obj: Any) -> bool:
|
325
|
+
"""
|
326
|
+
Check if the object is a getset descriptor.
|
327
|
+
|
328
|
+
Parameters
|
329
|
+
----------
|
330
|
+
obj : Any
|
331
|
+
The object to check.
|
332
|
+
|
333
|
+
Returns
|
334
|
+
-------
|
335
|
+
bool
|
336
|
+
True if the object is a getset descriptor, False otherwise.
|
337
|
+
"""
|
338
|
+
return inspect.isgetsetdescriptor(obj)
|
339
|
+
|
340
|
+
@staticmethod
|
341
|
+
def isMemberDescriptor(obj: Any) -> bool:
|
342
|
+
"""
|
343
|
+
Check if the object is a member descriptor.
|
344
|
+
|
345
|
+
Parameters
|
346
|
+
----------
|
347
|
+
obj : Any
|
348
|
+
The object to check.
|
349
|
+
|
350
|
+
Returns
|
351
|
+
-------
|
352
|
+
bool
|
353
|
+
True if the object is a member descriptor, False otherwise.
|
354
|
+
"""
|
355
|
+
return inspect.ismemberdescriptor(obj)
|
356
|
+
|
357
|
+
@staticmethod
|
358
|
+
def isMethod(obj: Any) -> bool:
|
359
|
+
"""
|
360
|
+
Check if the object is a method.
|
361
|
+
|
362
|
+
Parameters
|
363
|
+
----------
|
364
|
+
obj : Any
|
365
|
+
The object to check.
|
366
|
+
|
367
|
+
Returns
|
368
|
+
-------
|
369
|
+
bool
|
370
|
+
True if the object is a method, False otherwise.
|
371
|
+
"""
|
372
|
+
return inspect.ismethod(obj)
|
373
|
+
|
374
|
+
@staticmethod
|
375
|
+
def isMethodDescriptor(obj: Any) -> bool:
|
376
|
+
"""
|
377
|
+
Check if the object is a method descriptor.
|
378
|
+
|
379
|
+
Parameters
|
380
|
+
----------
|
381
|
+
obj : Any
|
382
|
+
The object to check.
|
383
|
+
|
384
|
+
Returns
|
385
|
+
-------
|
386
|
+
bool
|
387
|
+
True if the object is a method descriptor, False otherwise.
|
388
|
+
"""
|
389
|
+
return inspect.ismethoddescriptor(obj)
|
390
|
+
|
391
|
+
@staticmethod
|
392
|
+
def isModule(obj: Any) -> bool:
|
393
|
+
"""
|
394
|
+
Check if the object is a module.
|
395
|
+
|
396
|
+
Parameters
|
397
|
+
----------
|
398
|
+
obj : Any
|
399
|
+
The object to check.
|
400
|
+
|
401
|
+
Returns
|
402
|
+
-------
|
403
|
+
bool
|
404
|
+
True if the object is a module, False otherwise.
|
405
|
+
"""
|
406
|
+
return inspect.ismodule(obj)
|
407
|
+
|
408
|
+
@staticmethod
|
409
|
+
def isRoutine(obj: Any) -> bool:
|
410
|
+
"""
|
411
|
+
Check if the object is a user-defined or built-in function or method.
|
412
|
+
|
413
|
+
Parameters
|
414
|
+
----------
|
415
|
+
obj : Any
|
416
|
+
The object to check.
|
417
|
+
|
418
|
+
Returns
|
419
|
+
-------
|
420
|
+
bool
|
421
|
+
True if the object is a routine, False otherwise.
|
422
|
+
"""
|
423
|
+
return inspect.isroutine(obj)
|
424
|
+
|
425
|
+
@staticmethod
|
426
|
+
def isTraceback(obj: Any) -> bool:
|
427
|
+
"""
|
428
|
+
Check if the object is a traceback object.
|
429
|
+
|
430
|
+
Parameters
|
431
|
+
----------
|
432
|
+
obj : Any
|
433
|
+
The object to check.
|
434
|
+
|
435
|
+
Returns
|
436
|
+
-------
|
437
|
+
bool
|
438
|
+
True if the object is a traceback object, False otherwise.
|
439
|
+
"""
|
440
|
+
return inspect.istraceback(obj)
|
@@ -0,0 +1,188 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from typing import Any, Dict
|
3
|
+
|
4
|
+
class ITestPrinter(ABC):
|
5
|
+
|
6
|
+
@abstractmethod
|
7
|
+
def print(
|
8
|
+
self,
|
9
|
+
value: Any
|
10
|
+
) -> None:
|
11
|
+
"""
|
12
|
+
Prints a value to the console using the rich console.
|
13
|
+
Parameters
|
14
|
+
----------
|
15
|
+
value : Any
|
16
|
+
The value to be printed. It can be a string, object, or any other type.
|
17
|
+
Notes
|
18
|
+
-----
|
19
|
+
- If the value is a string, it is printed directly.
|
20
|
+
- If the value is an object, its string representation is printed.
|
21
|
+
- If the value is a list, each item is printed on a new line.
|
22
|
+
"""
|
23
|
+
pass
|
24
|
+
|
25
|
+
@abstractmethod
|
26
|
+
def startMessage(
|
27
|
+
self,
|
28
|
+
*,
|
29
|
+
print_result: bool,
|
30
|
+
length_tests: int,
|
31
|
+
execution_mode: str,
|
32
|
+
max_workers: int
|
33
|
+
):
|
34
|
+
"""
|
35
|
+
Displays a formatted start message for the test execution session.
|
36
|
+
|
37
|
+
Parameters
|
38
|
+
----------
|
39
|
+
print_result : bool
|
40
|
+
Whether to print the start message.
|
41
|
+
length_tests : int
|
42
|
+
The total number of tests to be executed.
|
43
|
+
execution_mode : str
|
44
|
+
The mode of execution, either "parallel" or "sequential".
|
45
|
+
max_workers : int
|
46
|
+
The number of worker threads/processes for parallel execution.
|
47
|
+
|
48
|
+
Side Effects
|
49
|
+
------------
|
50
|
+
Prints a styled panel with test session information to the console if `print_result` is True.
|
51
|
+
"""
|
52
|
+
pass
|
53
|
+
|
54
|
+
@abstractmethod
|
55
|
+
def finishMessage(
|
56
|
+
self,
|
57
|
+
*,
|
58
|
+
print_result: bool,
|
59
|
+
summary: Dict[str, Any]
|
60
|
+
) -> None:
|
61
|
+
"""
|
62
|
+
Display a summary message for the test suite execution.
|
63
|
+
|
64
|
+
Parameters
|
65
|
+
----------
|
66
|
+
summary : dict
|
67
|
+
Dictionary containing the test suite summary, including keys such as
|
68
|
+
'failed', 'errors', and 'total_time'.
|
69
|
+
|
70
|
+
Notes
|
71
|
+
-----
|
72
|
+
- If `self.print_result` is False, the method returns without displaying anything.
|
73
|
+
- Shows a status icon (✅ for success, ❌ for failure) based on the presence of
|
74
|
+
failures or errors in the test suite.
|
75
|
+
- Formats and prints the message within a styled panel using the `rich` library.
|
76
|
+
"""
|
77
|
+
pass
|
78
|
+
|
79
|
+
@abstractmethod
|
80
|
+
def executePanel(
|
81
|
+
self,
|
82
|
+
*,
|
83
|
+
print_result: bool,
|
84
|
+
flatten_test_suite: list,
|
85
|
+
callable: callable
|
86
|
+
):
|
87
|
+
"""
|
88
|
+
Executes a test suite panel with optional live console output.
|
89
|
+
|
90
|
+
Parameters
|
91
|
+
----------
|
92
|
+
print_result : bool
|
93
|
+
If True, displays a running message panel while executing the test suite.
|
94
|
+
flatten_test_suite : list
|
95
|
+
The flattened list of test cases or test suite items to be executed.
|
96
|
+
callable : callable
|
97
|
+
The function or method to execute the test suite.
|
98
|
+
|
99
|
+
Returns
|
100
|
+
-------
|
101
|
+
Any
|
102
|
+
The result returned by the provided callable after execution.
|
103
|
+
|
104
|
+
Notes
|
105
|
+
-----
|
106
|
+
This method manages the display of a running message panel using the Rich library,
|
107
|
+
depending on whether debugging is enabled in the test suite and whether results should be printed.
|
108
|
+
If debugging or dump calls are detected in the test code, a live console is used to display
|
109
|
+
real-time updates. Otherwise, a static panel is shown before executing the test suite.
|
110
|
+
"""
|
111
|
+
pass
|
112
|
+
|
113
|
+
@abstractmethod
|
114
|
+
def linkWebReport(
|
115
|
+
self,
|
116
|
+
path: str
|
117
|
+
):
|
118
|
+
"""
|
119
|
+
Prints an elegant invitation to view the test results, with an underlined path.
|
120
|
+
|
121
|
+
Parameters
|
122
|
+
----------
|
123
|
+
path : str or Path
|
124
|
+
The path to the test results report.
|
125
|
+
"""
|
126
|
+
pass
|
127
|
+
|
128
|
+
@abstractmethod
|
129
|
+
def summaryTable(
|
130
|
+
self,
|
131
|
+
summary: Dict[str, Any]
|
132
|
+
) -> None:
|
133
|
+
"""
|
134
|
+
Prints a summary table of test results using the Rich library.
|
135
|
+
|
136
|
+
Parameters
|
137
|
+
----------
|
138
|
+
summary : dict
|
139
|
+
Dictionary with the test summary data. Must contain the following keys:
|
140
|
+
total_tests : int
|
141
|
+
Total number of tests executed.
|
142
|
+
passed : int
|
143
|
+
Number of tests that passed.
|
144
|
+
failed : int
|
145
|
+
Number of tests that failed.
|
146
|
+
errors : int
|
147
|
+
Number of tests that had errors.
|
148
|
+
skipped : int
|
149
|
+
Number of tests that were skipped.
|
150
|
+
total_time : float
|
151
|
+
Total duration of the test execution in seconds.
|
152
|
+
success_rate : float
|
153
|
+
Percentage of tests that passed.
|
154
|
+
|
155
|
+
Returns
|
156
|
+
-------
|
157
|
+
None
|
158
|
+
"""
|
159
|
+
pass
|
160
|
+
|
161
|
+
@abstractmethod
|
162
|
+
def displayResults(
|
163
|
+
self,
|
164
|
+
*,
|
165
|
+
print_result: bool,
|
166
|
+
summary: Dict[str, Any]
|
167
|
+
) -> None:
|
168
|
+
"""
|
169
|
+
Display the results of the test execution, including a summary table and detailed
|
170
|
+
information about failed or errored tests grouped by their test classes.
|
171
|
+
|
172
|
+
Parameters
|
173
|
+
----------
|
174
|
+
summary : dict
|
175
|
+
Dictionary containing the summary of the test execution, including test details,
|
176
|
+
statuses, and execution times.
|
177
|
+
|
178
|
+
Notes
|
179
|
+
-----
|
180
|
+
- Prints a summary table of the test results.
|
181
|
+
- Groups failed and errored tests by their test class and displays them in a structured
|
182
|
+
format using panels.
|
183
|
+
- For each failed or errored test, displays the traceback in a syntax-highlighted panel
|
184
|
+
with additional metadata such as the test method name and execution time.
|
185
|
+
- Uses different icons and border colors to distinguish between failed and errored tests.
|
186
|
+
- Calls a finishing message method after displaying all results.
|
187
|
+
"""
|
188
|
+
pass
|