orionis 0.592.0__py3-none-any.whl → 0.594.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/foundation/config/testing/entities/testing.py +0 -16
- orionis/metadata/framework.py +1 -1
- orionis/test/contracts/unit_test.py +128 -7
- orionis/test/core/unit_test.py +6 -3
- orionis/test/output/printer.py +97 -68
- {orionis-0.592.0.dist-info → orionis-0.594.0.dist-info}/METADATA +1 -1
- {orionis-0.592.0.dist-info → orionis-0.594.0.dist-info}/RECORD +10 -10
- {orionis-0.592.0.dist-info → orionis-0.594.0.dist-info}/WHEEL +0 -0
- {orionis-0.592.0.dist-info → orionis-0.594.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.592.0.dist-info → orionis-0.594.0.dist-info}/top_level.txt +0 -0
@@ -19,8 +19,6 @@ class Testing(BaseEntity):
|
|
19
19
|
Maximum number of worker threads/processes for parallel execution (default: calculated by Workers).
|
20
20
|
fail_fast : bool, optional
|
21
21
|
If True, stop execution after the first test failure (default: False).
|
22
|
-
print_result : bool, optional
|
23
|
-
If True, print test results to the console (default: True).
|
24
22
|
throw_exception : bool, optional
|
25
23
|
If True, raise an exception on test failure (default: False).
|
26
24
|
base_path : str, optional
|
@@ -75,14 +73,6 @@ class Testing(BaseEntity):
|
|
75
73
|
}
|
76
74
|
)
|
77
75
|
|
78
|
-
print_result: bool = field(
|
79
|
-
default = True,
|
80
|
-
metadata = {
|
81
|
-
"description": "Whether to print the test results to the console. Default is True.",
|
82
|
-
"default": True
|
83
|
-
}
|
84
|
-
)
|
85
|
-
|
86
76
|
throw_exception: bool = field(
|
87
77
|
default = False,
|
88
78
|
metadata = {
|
@@ -206,12 +196,6 @@ class Testing(BaseEntity):
|
|
206
196
|
f"Invalid type for 'fail_fast': {type(self.fail_fast).__name__}. It must be a boolean (True or False)."
|
207
197
|
)
|
208
198
|
|
209
|
-
# Validate print_result attribute
|
210
|
-
if not isinstance(self.print_result, bool):
|
211
|
-
raise OrionisIntegrityException(
|
212
|
-
f"Invalid type for 'print_result': {type(self.print_result).__name__}. It must be a boolean (True or False)."
|
213
|
-
)
|
214
|
-
|
215
199
|
# Validate throw_exception attribute
|
216
200
|
if not isinstance(self.throw_exception, bool):
|
217
201
|
raise OrionisIntegrityException(
|
orionis/metadata/framework.py
CHANGED
@@ -1,20 +1,141 @@
|
|
1
|
+
import unittest
|
1
2
|
from abc import ABC, abstractmethod
|
2
|
-
from
|
3
|
-
from typing import Any, Dict, List, Optional
|
4
|
-
from orionis.foundation.config.testing.enums import ExecutionMode
|
5
|
-
from orionis.foundation.config.testing.enums.drivers import PersistentDrivers
|
6
|
-
from orionis.foundation.config.testing.enums.verbosity import VerbosityMode
|
3
|
+
from typing import Any, Dict, List
|
7
4
|
|
8
5
|
class IUnitTest(ABC):
|
9
6
|
|
10
7
|
@abstractmethod
|
11
8
|
def run(self) -> Dict[str, Any]:
|
12
9
|
"""
|
13
|
-
Execute
|
10
|
+
Execute the test suite and return a summary of the results.
|
14
11
|
|
15
12
|
Returns
|
16
13
|
-------
|
17
14
|
dict
|
18
|
-
|
15
|
+
Dictionary summarizing the test results, including statistics and execution time.
|
16
|
+
|
17
|
+
Raises
|
18
|
+
------
|
19
|
+
OrionisTestFailureException
|
20
|
+
If the test suite execution fails and throw_exception is True.
|
21
|
+
"""
|
22
|
+
pass
|
23
|
+
|
24
|
+
@abstractmethod
|
25
|
+
def getDiscoveredTestCases(
|
26
|
+
self
|
27
|
+
) -> List[unittest.TestCase]:
|
28
|
+
"""
|
29
|
+
Return a list of all discovered test case classes in the test suite.
|
30
|
+
|
31
|
+
This method provides access to all unique test case classes that have been discovered
|
32
|
+
during test suite initialization and loading. It does not execute any tests, but simply
|
33
|
+
reports the discovered test case classes.
|
34
|
+
|
35
|
+
Returns
|
36
|
+
-------
|
37
|
+
List[unittest.TestCase]
|
38
|
+
A list of unique `unittest.TestCase` classes that have been discovered in the suite.
|
39
|
+
|
40
|
+
Notes
|
41
|
+
-----
|
42
|
+
- The returned list contains the test case classes, not instances or names.
|
43
|
+
- The classes are derived from the `__class__` attribute of each discovered test case.
|
44
|
+
- This method is useful for introspection or reporting purposes.
|
45
|
+
"""
|
46
|
+
pass
|
47
|
+
|
48
|
+
@abstractmethod
|
49
|
+
def getDiscoveredModules(
|
50
|
+
self
|
51
|
+
) -> List:
|
52
|
+
"""
|
53
|
+
Return a list of all discovered test module names in the test suite.
|
54
|
+
|
55
|
+
This method provides access to all unique test modules that have been discovered
|
56
|
+
during test suite initialization and loading. It does not execute any tests, but simply
|
57
|
+
reports the discovered module names.
|
58
|
+
|
59
|
+
Parameters
|
60
|
+
----------
|
61
|
+
None
|
62
|
+
|
63
|
+
Returns
|
64
|
+
-------
|
65
|
+
List[str]
|
66
|
+
A list of unique module names (as strings) that have been discovered in the suite.
|
67
|
+
|
68
|
+
Notes
|
69
|
+
-----
|
70
|
+
- The returned list contains the module names, not module objects.
|
71
|
+
- The module names are derived from the `__module__` attribute of each discovered test case.
|
72
|
+
- This method is useful for introspection or reporting purposes.
|
73
|
+
"""
|
74
|
+
pass
|
75
|
+
|
76
|
+
@abstractmethod
|
77
|
+
def getTestIds(
|
78
|
+
self
|
79
|
+
) -> List[str]:
|
80
|
+
"""
|
81
|
+
Return a list of all unique test IDs discovered in the test suite.
|
82
|
+
|
83
|
+
This method provides access to the unique identifiers (IDs) of all test cases
|
84
|
+
that have been discovered and loaded into the suite. The IDs are collected from
|
85
|
+
each `unittest.TestCase` instance during test discovery and are returned as a list
|
86
|
+
of strings. This is useful for introspection, reporting, or filtering purposes.
|
87
|
+
|
88
|
+
Parameters
|
89
|
+
----------
|
90
|
+
None
|
91
|
+
|
92
|
+
Returns
|
93
|
+
-------
|
94
|
+
List[str]
|
95
|
+
A list of strings, where each string is the unique ID of a discovered test case.
|
96
|
+
The IDs are generated by the `id()` method of each `unittest.TestCase` instance.
|
97
|
+
|
98
|
+
Notes
|
99
|
+
-----
|
100
|
+
- The returned list contains only unique test IDs.
|
101
|
+
- This method does not execute any tests; it only reports the discovered IDs.
|
102
|
+
- The IDs typically include the module, class, and method name for each test case.
|
103
|
+
"""
|
104
|
+
pass
|
105
|
+
|
106
|
+
@abstractmethod
|
107
|
+
def getTestCount(
|
108
|
+
self
|
109
|
+
) -> int:
|
110
|
+
"""
|
111
|
+
Return the total number of individual test cases discovered in the test suite.
|
112
|
+
|
113
|
+
This method calculates and returns the total number of test cases that have been
|
114
|
+
discovered and loaded into the suite, including all modules and filtered tests.
|
115
|
+
It uses the internal metadata collected during test discovery to provide an accurate count.
|
116
|
+
|
117
|
+
Returns
|
118
|
+
-------
|
119
|
+
int
|
120
|
+
The total number of individual test cases discovered and loaded in the suite.
|
121
|
+
|
122
|
+
Notes
|
123
|
+
-----
|
124
|
+
- The count reflects all tests after applying any name pattern or folder filtering.
|
125
|
+
- This method does not execute any tests; it only reports the discovered count.
|
126
|
+
"""
|
127
|
+
pass
|
128
|
+
|
129
|
+
@abstractmethod
|
130
|
+
def getResult(
|
131
|
+
self
|
132
|
+
) -> dict:
|
133
|
+
"""
|
134
|
+
Get the results of the executed test suite.
|
135
|
+
|
136
|
+
Returns
|
137
|
+
-------
|
138
|
+
dict
|
139
|
+
Result of the executed test suite.
|
19
140
|
"""
|
20
141
|
pass
|
orionis/test/core/unit_test.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import io
|
2
2
|
import json
|
3
|
+
import logging
|
3
4
|
import os
|
4
5
|
import re
|
5
6
|
import time
|
@@ -34,7 +35,6 @@ from orionis.test.validators import (
|
|
34
35
|
ValidPattern,
|
35
36
|
ValidPersistentDriver,
|
36
37
|
ValidPersistent,
|
37
|
-
ValidPrintResult,
|
38
38
|
ValidThrowException,
|
39
39
|
ValidVerbosity,
|
40
40
|
ValidWebReport,
|
@@ -96,6 +96,9 @@ class UnitTest(IUnitTest):
|
|
96
96
|
- Output buffers, paths, configuration, modules, and tests are loaded in sequence to prepare the test manager.
|
97
97
|
"""
|
98
98
|
|
99
|
+
# Suppress overly verbose asyncio logging during test execution
|
100
|
+
logging.getLogger("asyncio").setLevel(logging.ERROR)
|
101
|
+
|
99
102
|
# Store the application instance for dependency injection and configuration access
|
100
103
|
self.__app: IApplication = app
|
101
104
|
|
@@ -233,7 +236,7 @@ class UnitTest(IUnitTest):
|
|
233
236
|
|
234
237
|
# Initialize the printer for console output
|
235
238
|
self.__printer = TestPrinter(
|
236
|
-
|
239
|
+
verbosity=self.__verbosity
|
237
240
|
)
|
238
241
|
|
239
242
|
# Set the file name pattern for test discovery
|
@@ -1011,7 +1014,7 @@ class UnitTest(IUnitTest):
|
|
1011
1014
|
# Return the TestSuite containing the resolved test case
|
1012
1015
|
return suite
|
1013
1016
|
|
1014
|
-
except Exception
|
1017
|
+
except Exception:
|
1015
1018
|
|
1016
1019
|
# On any error, return the original test case without injection
|
1017
1020
|
return test_case
|
orionis/test/output/printer.py
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
import io
|
2
1
|
import re
|
3
2
|
from datetime import datetime
|
4
|
-
from typing import Any, Dict, List, Tuple
|
5
3
|
import unittest
|
4
|
+
from typing import Any, Dict, List
|
6
5
|
from rich.console import Console
|
7
6
|
from rich.live import Live
|
8
7
|
from rich.panel import Panel
|
8
|
+
from rich.progress import Progress, BarColumn, TextColumn, TaskProgressColumn
|
9
9
|
from rich.syntax import Syntax
|
10
10
|
from rich.table import Table
|
11
|
-
from rich.progress import Progress, BarColumn, TextColumn, TaskProgressColumn
|
12
11
|
from rich.text import Text
|
12
|
+
from orionis.foundation.config.testing.enums.verbosity import VerbosityMode
|
13
13
|
from orionis.test.contracts.printer import ITestPrinter
|
14
14
|
from orionis.test.entities.result import TestResult
|
15
15
|
from orionis.test.enums import TestStatus
|
@@ -18,37 +18,58 @@ class TestPrinter(ITestPrinter):
|
|
18
18
|
|
19
19
|
def __init__(
|
20
20
|
self,
|
21
|
-
|
21
|
+
verbosity: VerbosityMode | int = VerbosityMode.DETAILED,
|
22
22
|
title: str = "🧪 Orionis Framework - Component Test Suite",
|
23
23
|
width: int = 75
|
24
24
|
) -> None:
|
25
25
|
"""
|
26
|
-
|
26
|
+
Initializes a TestPrinter instance for formatted test output using the Rich library.
|
27
27
|
|
28
28
|
Parameters
|
29
29
|
----------
|
30
30
|
print_result : bool, optional
|
31
|
-
|
31
|
+
If True, enables printing of test results to the console. If False, suppresses all output.
|
32
|
+
verbosity : VerbosityMode or int, optional
|
33
|
+
Specifies the verbosity level for output. Accepts either a VerbosityMode enum or an integer value.
|
34
|
+
Default is VerbosityMode.DETAILED.
|
32
35
|
title : str, optional
|
33
|
-
The title
|
36
|
+
The title displayed in the output panel. Default is "🧪 Orionis Framework - Component Test Suite".
|
34
37
|
width : int, optional
|
35
|
-
The width of the output panel as a percentage of the console width
|
38
|
+
The width of the output panel as a percentage of the console width. Must be between 10 and 100.
|
39
|
+
Default is 75.
|
36
40
|
|
37
41
|
Returns
|
38
42
|
-------
|
39
43
|
None
|
44
|
+
This constructor does not return any value. It initializes the TestPrinter instance.
|
45
|
+
|
46
|
+
Raises
|
47
|
+
------
|
48
|
+
ValueError
|
49
|
+
If any of the input parameters are of invalid type or out of allowed range.
|
50
|
+
|
51
|
+
Notes
|
52
|
+
-----
|
53
|
+
- The Rich Console instance is created for rendering output.
|
54
|
+
- The verbosity level, panel width, panel title, and print_result flag are validated and set.
|
40
55
|
"""
|
41
56
|
# Create a Rich Console instance for output rendering
|
42
57
|
self.__rich_console = Console()
|
43
58
|
|
44
|
-
#
|
45
|
-
|
59
|
+
# Validate and set verbosity level
|
60
|
+
if not isinstance(verbosity, (int, VerbosityMode)):
|
61
|
+
raise ValueError("The 'verbosity' parameter must be an integer or VerbosityMode enum.")
|
62
|
+
self.__verbosity: int = verbosity if isinstance(verbosity, int) else verbosity.value
|
46
63
|
|
47
|
-
#
|
64
|
+
# Validate and set panel width (must be between 10% and 100% of console width)
|
65
|
+
if not isinstance(width, int) or not (10 <= width <= 100):
|
66
|
+
raise ValueError("The 'width' parameter must be an integer between 10 and 100.")
|
48
67
|
self.__panel_width: int = int(self.__rich_console.width * (width / 100))
|
49
68
|
|
50
|
-
#
|
51
|
-
|
69
|
+
# Validate and set panel title
|
70
|
+
if not isinstance(title, str):
|
71
|
+
raise ValueError("The 'title' parameter must be a string.")
|
72
|
+
self.__panel_title: str = title
|
52
73
|
|
53
74
|
def print(
|
54
75
|
self,
|
@@ -76,7 +97,7 @@ class TestPrinter(ITestPrinter):
|
|
76
97
|
"""
|
77
98
|
|
78
99
|
# If printing results is disabled, do not output anything
|
79
|
-
if self.
|
100
|
+
if self.__verbosity == VerbosityMode.SILENT.value:
|
80
101
|
return
|
81
102
|
|
82
103
|
# Print string values directly
|
@@ -114,7 +135,7 @@ class TestPrinter(ITestPrinter):
|
|
114
135
|
"""
|
115
136
|
|
116
137
|
# If printing results is disabled, do not output anything
|
117
|
-
if self.
|
138
|
+
if self.__verbosity == VerbosityMode.SILENT.value:
|
118
139
|
return
|
119
140
|
|
120
141
|
# Print the specified number of blank lines
|
@@ -139,7 +160,7 @@ class TestPrinter(ITestPrinter):
|
|
139
160
|
- The message is displayed in a Rich panel with a yellow border and centered title.
|
140
161
|
"""
|
141
162
|
# If printing results is disabled, do not output anything
|
142
|
-
if self.
|
163
|
+
if self.__verbosity == VerbosityMode.SILENT.value:
|
143
164
|
return
|
144
165
|
|
145
166
|
# Print a styled panel to indicate that no tests were found
|
@@ -189,7 +210,7 @@ class TestPrinter(ITestPrinter):
|
|
189
210
|
"""
|
190
211
|
|
191
212
|
# If printing results is disabled, do not output anything
|
192
|
-
if self.
|
213
|
+
if self.__verbosity == VerbosityMode.SILENT.value:
|
193
214
|
return
|
194
215
|
|
195
216
|
# Format the execution mode text for display
|
@@ -245,14 +266,17 @@ class TestPrinter(ITestPrinter):
|
|
245
266
|
- The progress bar is suitable for tracking the progress of tasks such as test execution.
|
246
267
|
"""
|
247
268
|
|
269
|
+
# Flag to disable the progress bar if printing is off or verbosity is silent/minimal
|
270
|
+
disable = self.__verbosity <= VerbosityMode.MINIMAL.value
|
271
|
+
|
248
272
|
# Create and return a Rich Progress bar instance with custom columns and settings
|
249
273
|
return Progress(
|
250
|
-
TextColumn("[cyan]{task.description}"),
|
251
|
-
BarColumn(),
|
252
|
-
TaskProgressColumn(),
|
253
|
-
console=self.__rich_console,
|
254
|
-
transient=True,
|
255
|
-
disable=
|
274
|
+
TextColumn("[cyan]{task.description}"), # Task description in cyan
|
275
|
+
BarColumn(), # Visual progress bar
|
276
|
+
TaskProgressColumn(), # Percentage completion indicator
|
277
|
+
console=self.__rich_console, # Output to the configured Rich console
|
278
|
+
transient=True, # Remove the bar after completion
|
279
|
+
disable=disable # Disable if printing is off
|
256
280
|
)
|
257
281
|
|
258
282
|
def finishMessage(
|
@@ -276,7 +300,7 @@ class TestPrinter(ITestPrinter):
|
|
276
300
|
None
|
277
301
|
"""
|
278
302
|
# If not printing results, return early
|
279
|
-
if self.
|
303
|
+
if self.__verbosity == VerbosityMode.SILENT.value:
|
280
304
|
return
|
281
305
|
|
282
306
|
# Determine status icon based on failures and errors
|
@@ -335,7 +359,7 @@ class TestPrinter(ITestPrinter):
|
|
335
359
|
raise ValueError("The 'func' parameter must be a callable (function or method).")
|
336
360
|
|
337
361
|
# Only display output if printing results is enabled
|
338
|
-
if self.
|
362
|
+
if self.__verbosity != VerbosityMode.SILENT.value:
|
339
363
|
|
340
364
|
# If live_console is True, use a live panel for dynamic updates
|
341
365
|
if live_console:
|
@@ -366,6 +390,7 @@ class TestPrinter(ITestPrinter):
|
|
366
390
|
return func()
|
367
391
|
|
368
392
|
else:
|
393
|
+
|
369
394
|
# If result printing is disabled, execute the callable without any panel
|
370
395
|
return func()
|
371
396
|
|
@@ -386,7 +411,7 @@ class TestPrinter(ITestPrinter):
|
|
386
411
|
None
|
387
412
|
"""
|
388
413
|
# If not printing results, do not display the link
|
389
|
-
if self.
|
414
|
+
if self.__verbosity == VerbosityMode.SILENT.value:
|
390
415
|
return
|
391
416
|
|
392
417
|
# Create the base invitation text with a green style
|
@@ -425,7 +450,7 @@ class TestPrinter(ITestPrinter):
|
|
425
450
|
None
|
426
451
|
"""
|
427
452
|
# If result printing is disabled, do not display the summary table
|
428
|
-
if self.
|
453
|
+
if self.__verbosity == VerbosityMode.SILENT.value:
|
429
454
|
return
|
430
455
|
|
431
456
|
# Create a Rich Table with headers and styling
|
@@ -482,7 +507,7 @@ class TestPrinter(ITestPrinter):
|
|
482
507
|
None
|
483
508
|
"""
|
484
509
|
# If result printing is disabled, do not display results
|
485
|
-
if
|
510
|
+
if self.__verbosity == VerbosityMode.SILENT.value:
|
486
511
|
return
|
487
512
|
|
488
513
|
# Print one blank line before the summary
|
@@ -491,18 +516,17 @@ class TestPrinter(ITestPrinter):
|
|
491
516
|
# Print the summary table of test results
|
492
517
|
self.summaryTable(summary)
|
493
518
|
|
494
|
-
#
|
519
|
+
# Get the list of individual test results
|
495
520
|
test_details: List[Dict] = summary.get("test_details", [])
|
521
|
+
|
522
|
+
# Iterate through each test result to display failures and errors
|
496
523
|
for test in test_details:
|
497
524
|
|
498
525
|
# If there are no failures or errors, skip to the next test
|
499
526
|
if test["status"] in (TestStatus.FAILED.name, TestStatus.ERRORED.name):
|
500
527
|
|
501
528
|
# Determine the status icon based on the test status
|
502
|
-
if test["status"] == TestStatus.FAILED.name:
|
503
|
-
status_icon = "❌ FAILED: "
|
504
|
-
else:
|
505
|
-
status_icon = "💥 ERRORED: "
|
529
|
+
status_icon = "❌ FAILED:" if test["status"] == TestStatus.FAILED.name else "💥 ERRORED:"
|
506
530
|
|
507
531
|
# Print separator line before each test result with class name and method name
|
508
532
|
self.__rich_console.rule(title=f'🧪 {test["class"]}.{test["method"]}()', align="left")
|
@@ -516,7 +540,6 @@ class TestPrinter(ITestPrinter):
|
|
516
540
|
_file = last_trace_frame.get('file')
|
517
541
|
_line = last_trace_frame.get('line')
|
518
542
|
_code = last_trace_frame.get('code')
|
519
|
-
_function = last_trace_frame.get('function')
|
520
543
|
|
521
544
|
# Print the file and line number if available
|
522
545
|
text = Text("📂 ")
|
@@ -524,43 +547,48 @@ class TestPrinter(ITestPrinter):
|
|
524
547
|
self.__rich_console.print(text)
|
525
548
|
|
526
549
|
# Print the error message with better formatting
|
527
|
-
text = Text(status_icon, style="red")
|
550
|
+
text = Text(f"{status_icon} ", style="red")
|
528
551
|
error_msg = test["error_message"] if test["error_message"] else "Unknown error"
|
529
552
|
text.append(error_msg, style="yellow")
|
530
553
|
self.__rich_console.print(text)
|
531
554
|
|
532
|
-
#
|
533
|
-
|
534
|
-
|
535
|
-
# Open the file and read its lines
|
536
|
-
with open(_file, 'r', encoding='utf-8') as f:
|
537
|
-
file_lines = f.readlines()
|
538
|
-
|
539
|
-
# Convert to 0-based index
|
540
|
-
error_line_num = int(_line) - 1
|
541
|
-
start_line = max(0, error_line_num - 1)
|
542
|
-
end_line = min(len(file_lines), error_line_num + 3)
|
543
|
-
|
544
|
-
# Create a code block with syntax highlighting
|
545
|
-
code_lines = []
|
546
|
-
for i in range(start_line, end_line):
|
547
|
-
line_num = i + 1
|
548
|
-
line_content = file_lines[i].rstrip()
|
549
|
-
if line_num == int(_line):
|
550
|
-
# Highlight the error line
|
551
|
-
code_lines.append(f"* {line_num:3d} | {line_content}")
|
552
|
-
else:
|
553
|
-
code_lines.append(f" {line_num:3d} | {line_content}")
|
554
|
-
|
555
|
-
code_block = '\n'.join(code_lines)
|
556
|
-
syntax = Syntax(code_block, "python", theme="monokai", line_numbers=False)
|
557
|
-
self.__rich_console.print(syntax)
|
555
|
+
# If verbosity is detailed, include file path, line number, error message, and traceback
|
556
|
+
if self.__verbosity == VerbosityMode.DETAILED.value:
|
558
557
|
|
559
|
-
|
558
|
+
try:
|
560
559
|
|
561
|
-
|
562
|
-
|
563
|
-
|
560
|
+
# Open the file and read its lines
|
561
|
+
if isinstance(_file, str) and _file:
|
562
|
+
with open(_file, 'r', encoding='utf-8') as f:
|
563
|
+
file_lines = f.readlines()
|
564
|
+
else:
|
565
|
+
raise ValueError(f"Invalid file path: {_file}")
|
566
|
+
|
567
|
+
# Convert to 0-based index
|
568
|
+
error_line_num = int(_line) - 1
|
569
|
+
start_line = max(0, error_line_num - 1)
|
570
|
+
end_line = min(len(file_lines), error_line_num + 3)
|
571
|
+
|
572
|
+
# Create a code block with syntax highlighting
|
573
|
+
code_lines = []
|
574
|
+
for i in range(start_line, end_line):
|
575
|
+
line_num = i + 1
|
576
|
+
line_content = file_lines[i].rstrip()
|
577
|
+
if line_num == int(_line):
|
578
|
+
# Highlight the error line
|
579
|
+
code_lines.append(f"* {line_num:3d} | {line_content}")
|
580
|
+
else:
|
581
|
+
code_lines.append(f" {line_num:3d} | {line_content}")
|
582
|
+
|
583
|
+
code_block = '\n'.join(code_lines)
|
584
|
+
syntax = Syntax(code_block, "python", theme="monokai", line_numbers=False)
|
585
|
+
self.__rich_console.print(syntax)
|
586
|
+
|
587
|
+
except Exception:
|
588
|
+
|
589
|
+
# Fallback to original behavior if file cannot be read
|
590
|
+
text = Text(f"{_line} | {_code}", style="dim")
|
591
|
+
self.__rich_console.print(text)
|
564
592
|
|
565
593
|
else:
|
566
594
|
|
@@ -570,7 +598,7 @@ class TestPrinter(ITestPrinter):
|
|
570
598
|
self.__rich_console.print(text)
|
571
599
|
|
572
600
|
# Print the error message with better formatting
|
573
|
-
text = Text(status_icon, style="bold red")
|
601
|
+
text = Text(f"{status_icon} ", style="bold red")
|
574
602
|
self.__rich_console.print(text)
|
575
603
|
|
576
604
|
# Print traceback if available
|
@@ -583,7 +611,8 @@ class TestPrinter(ITestPrinter):
|
|
583
611
|
self.__rich_console.print(syntax)
|
584
612
|
|
585
613
|
# Print a separator line after each test result
|
586
|
-
self.
|
614
|
+
if self.__verbosity == VerbosityMode.DETAILED.value:
|
615
|
+
self.__rich_console.rule()
|
587
616
|
|
588
617
|
# Print one blank line after the results
|
589
618
|
self.__rich_console.line(1)
|
@@ -608,7 +637,7 @@ class TestPrinter(ITestPrinter):
|
|
608
637
|
None
|
609
638
|
"""
|
610
639
|
# If result printing is disabled, do not display results
|
611
|
-
if
|
640
|
+
if self.__verbosity < VerbosityMode.DETAILED.value:
|
612
641
|
return
|
613
642
|
|
614
643
|
# Determine the status icon and label based on the test result
|
@@ -191,7 +191,7 @@ orionis/foundation/config/session/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-
|
|
191
191
|
orionis/foundation/config/session/helpers/secret_key.py,sha256=yafjzQ9KVQdXzCQCMthpgizlNCo5F5UTLtAnInipUMk,447
|
192
192
|
orionis/foundation/config/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
193
193
|
orionis/foundation/config/testing/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
194
|
-
orionis/foundation/config/testing/entities/testing.py,sha256=
|
194
|
+
orionis/foundation/config/testing/entities/testing.py,sha256=OkgaZ4lCeU3bTUUVHl73PEbdlXjMsI16iuD9Pwkc5vg,11587
|
195
195
|
orionis/foundation/config/testing/enums/__init__.py,sha256=aFh5kBxlh5kqHK-9W7qgdykF5-qou5SVRzorRBazqYw,196
|
196
196
|
orionis/foundation/config/testing/enums/drivers.py,sha256=mwv47FcKDXEOxydQXAGtkdIY9S6qCAW1cD22oCFy3xw,355
|
197
197
|
orionis/foundation/config/testing/enums/mode.py,sha256=IbFpauu7J-iSAfmC8jDbmTEYl8eZr-AexL-lyOh8_74,337
|
@@ -217,7 +217,7 @@ orionis/foundation/providers/scheduler_provider.py,sha256=irwkjMiq-HpsbJxAOnhjji
|
|
217
217
|
orionis/foundation/providers/testing_provider.py,sha256=2akFnabtH_cV_7z_2cCL7u8cPCGvCJAmlhMcnlCrc4c,3742
|
218
218
|
orionis/foundation/providers/workers_provider.py,sha256=P_YtJuPNrdJAQJkAqI11KI0c6GSB9NqIuuCKpRytE0g,3937
|
219
219
|
orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
220
|
-
orionis/metadata/framework.py,sha256=
|
220
|
+
orionis/metadata/framework.py,sha256=QBxCwK8RQb3eyByXhYfD9zhhx-zJjfQg4fFDbk8PLhE,4109
|
221
221
|
orionis/metadata/package.py,sha256=k7Yriyp5aUcR-iR8SK2ec_lf0_Cyc-C7JczgXa-I67w,16039
|
222
222
|
orionis/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
223
223
|
orionis/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -370,9 +370,9 @@ orionis/test/contracts/logs.py,sha256=kRH3TGQcTNI0kRxFyEs13Y7NOPP9x9WGitPexnoLzQ
|
|
370
370
|
orionis/test/contracts/printer.py,sha256=iBz8wHAGaS21VBsHlZQVcx0xu9Bqusb-CLAjj-R1Sjg,3412
|
371
371
|
orionis/test/contracts/render.py,sha256=wpDQzUtT0r8KFZ7zPcxWHXQ1EVNKxzA_rZ6ZKUcZO1c,744
|
372
372
|
orionis/test/contracts/test_result.py,sha256=SNXJ2UerkweYn7uCT0i0HmMGP0XBrL_9KJs-0ZvIYU4,4002
|
373
|
-
orionis/test/contracts/unit_test.py,sha256=
|
373
|
+
orionis/test/contracts/unit_test.py,sha256=EyidHoOPJItwgkBWGYY1TymbNklyn2EUXnghVvW4htc,4652
|
374
374
|
orionis/test/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
375
|
-
orionis/test/core/unit_test.py,sha256=
|
375
|
+
orionis/test/core/unit_test.py,sha256=WrV4WDU-oNhwzeDeJIqQbyNYNwoO8CL3C0cD7IHtUMM,72952
|
376
376
|
orionis/test/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
377
377
|
orionis/test/entities/result.py,sha256=eZ6UIqGmFW8FZ9x8PB_MZbLAc-SAuUyi4FUcMYIZzGo,4777
|
378
378
|
orionis/test/enums/__init__.py,sha256=M3imAgMvKFTKg55FbtVoY3zxj7QRY9AfaUWxiSZVvn4,66
|
@@ -385,7 +385,7 @@ orionis/test/exceptions/runtime.py,sha256=h9gQ0pS8tJTmuXNG-GHky8tTqpdz-cNqkntOOl
|
|
385
385
|
orionis/test/exceptions/value.py,sha256=CoqYOkViU_RaKCMNpB82tgEsR3XhI1pw6YQ8sH8CJh4,588
|
386
386
|
orionis/test/output/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
387
387
|
orionis/test/output/dumper.py,sha256=qJDyVvl3MO0Uinr6z9TYYdDTqHNwwM0PcoDNNkTpAnA,5908
|
388
|
-
orionis/test/output/printer.py,sha256=
|
388
|
+
orionis/test/output/printer.py,sha256=M33HhDQBRxB-C-myOqPFSkTvfLyDCc424uVqJg40NYc,29575
|
389
389
|
orionis/test/records/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
390
390
|
orionis/test/records/logs.py,sha256=N5MczDDZ8HqyTCLgb4ikzAQzyzl2JhKHNVd-KGzAG20,22081
|
391
391
|
orionis/test/validators/__init__.py,sha256=2e862DM9aRnPajv2nxMujewe9dZ-1PyCamJKDcF-hGc,944
|
@@ -406,8 +406,8 @@ orionis/test/validators/workers.py,sha256=rWcdRexINNEmGaO7mnc1MKUxkHKxrTsVuHgbnI
|
|
406
406
|
orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
407
407
|
orionis/test/view/render.py,sha256=R55ykeRs0wDKcdTf4O1YZ8GDHTFmJ0IK6VQkbJkYUvo,5571
|
408
408
|
orionis/test/view/report.stub,sha256=QLqqCdRoENr3ECiritRB3DO_MOjRQvgBh5jxZ3Hs1r0,28189
|
409
|
-
orionis-0.
|
410
|
-
orionis-0.
|
411
|
-
orionis-0.
|
412
|
-
orionis-0.
|
413
|
-
orionis-0.
|
409
|
+
orionis-0.594.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
|
410
|
+
orionis-0.594.0.dist-info/METADATA,sha256=b5WUz7L2LJm1-S-W1s40bw_gZwt2hbLaDY1zZVKlAzU,4801
|
411
|
+
orionis-0.594.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
412
|
+
orionis-0.594.0.dist-info/top_level.txt,sha256=lyXi6jArpqJ-0zzNqd_uwsH-z9TCEBVBL-pC3Ekv7hU,8
|
413
|
+
orionis-0.594.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|