orionis 0.588.0__py3-none-any.whl → 0.590.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/console/core/reactor.py +4 -2
- orionis/foundation/application.py +52 -13
- orionis/foundation/config/testing/entities/testing.py +0 -23
- orionis/foundation/contracts/application.py +27 -0
- orionis/metadata/framework.py +1 -1
- orionis/support/performance/contracts/counter.py +102 -5
- orionis/support/performance/counter.py +118 -8
- orionis/test/contracts/unit_test.py +0 -156
- orionis/test/core/unit_test.py +351 -409
- orionis/test/kernel.py +45 -60
- orionis/test/validators/__init__.py +0 -2
- {orionis-0.588.0.dist-info → orionis-0.590.0.dist-info}/METADATA +1 -1
- {orionis-0.588.0.dist-info → orionis-0.590.0.dist-info}/RECORD +16 -17
- orionis/test/validators/tags.py +0 -36
- {orionis-0.588.0.dist-info → orionis-0.590.0.dist-info}/WHEEL +0 -0
- {orionis-0.588.0.dist-info → orionis-0.590.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.588.0.dist-info → orionis-0.590.0.dist-info}/top_level.txt +0 -0
orionis/console/core/reactor.py
CHANGED
@@ -850,7 +850,8 @@ class Reactor(IReactor):
|
|
850
850
|
output = self.__app.call(command_instance, command.method)
|
851
851
|
|
852
852
|
# Calculate elapsed time and log completion with DONE state if command.timestamps are enabled
|
853
|
-
|
853
|
+
self.__performance_counter.stop()
|
854
|
+
elapsed_time = round(self.__performance_counter.getSeconds(), 2)
|
854
855
|
if command.timestamps:
|
855
856
|
self.__executer.done(program=signature, time=f"{elapsed_time}s")
|
856
857
|
|
@@ -866,7 +867,8 @@ class Reactor(IReactor):
|
|
866
867
|
self.__logger.error(f"Command '{signature}' execution failed: {e}")
|
867
868
|
|
868
869
|
# Calculate elapsed time and log failure with ERROR state if command.timestamps are enabled
|
869
|
-
|
870
|
+
self.__performance_counter.stop()
|
871
|
+
elapsed_time = round(self.__performance_counter.getSeconds(), 2)
|
870
872
|
if command.timestamps:
|
871
873
|
self.__executer.fail(program=signature, time=f"{elapsed_time}s")
|
872
874
|
|
@@ -1912,21 +1912,22 @@ class Application(Container, IApplication):
|
|
1912
1912
|
"""
|
1913
1913
|
|
1914
1914
|
# Create a local copy of the configuration to avoid mutating the original
|
1915
|
-
|
1915
|
+
if not hasattr(self, '_Application__runtime_config') or self.__runtime_config is None:
|
1916
|
+
self.__runtime_config = self.__config.copy()
|
1916
1917
|
|
1917
1918
|
# Remove 'path' from the local copy to ensure path config is not returned here
|
1918
|
-
if 'path' in
|
1919
|
-
del
|
1919
|
+
if 'path' in self.__runtime_config:
|
1920
|
+
del self.__runtime_config['path']
|
1920
1921
|
|
1921
1922
|
# Ensure the application is booted before accessing configuration
|
1922
|
-
if not
|
1923
|
+
if not self.__runtime_config:
|
1923
1924
|
raise OrionisRuntimeError(
|
1924
1925
|
"Application configuration is not initialized. Please call create() before accessing configuration."
|
1925
1926
|
)
|
1926
1927
|
|
1927
1928
|
# If no key is provided, return the entire configuration (excluding 'path')
|
1928
1929
|
if key is None:
|
1929
|
-
return
|
1930
|
+
return self.__runtime_config
|
1930
1931
|
|
1931
1932
|
# Ensure the key is a string
|
1932
1933
|
if not isinstance(key, str):
|
@@ -1938,7 +1939,7 @@ class Application(Container, IApplication):
|
|
1938
1939
|
parts = key.split('.')
|
1939
1940
|
|
1940
1941
|
# Start with the full config and traverse according to the key parts
|
1941
|
-
config_value =
|
1942
|
+
config_value = self.__runtime_config
|
1942
1943
|
for part in parts:
|
1943
1944
|
# If the part exists in the current config_value, go deeper
|
1944
1945
|
if isinstance(config_value, dict) and part in config_value:
|
@@ -1992,10 +1993,11 @@ class Application(Container, IApplication):
|
|
1992
1993
|
"""
|
1993
1994
|
|
1994
1995
|
# Create a local copy of the path configuration to avoid mutation
|
1995
|
-
|
1996
|
+
if not hasattr(self, '_Application__runtime_path_config') or self.__runtime_path_config is None:
|
1997
|
+
self.__runtime_path_config = self.__config.get('path', {}).copy() if self.__config else {}
|
1996
1998
|
|
1997
1999
|
# Ensure the application is booted before accessing configuration
|
1998
|
-
if not
|
2000
|
+
if not self.__runtime_path_config:
|
1999
2001
|
raise OrionisRuntimeError(
|
2000
2002
|
"Application configuration is not initialized. Please call create() before accessing path configuration."
|
2001
2003
|
)
|
@@ -2003,7 +2005,7 @@ class Application(Container, IApplication):
|
|
2003
2005
|
# If no key is provided, return all paths as a dictionary of Path objects
|
2004
2006
|
if key is None:
|
2005
2007
|
path_resolved: Dict[str, Path] = {}
|
2006
|
-
for k, v in
|
2008
|
+
for k, v in self.__runtime_path_config.items():
|
2007
2009
|
# Convert each path string to a Path object
|
2008
2010
|
path_resolved[k] = Path(v)
|
2009
2011
|
return path_resolved
|
@@ -2015,8 +2017,8 @@ class Application(Container, IApplication):
|
|
2015
2017
|
)
|
2016
2018
|
|
2017
2019
|
# Direct key match: return the resolved Path object if the key exists
|
2018
|
-
if key in
|
2019
|
-
return Path(
|
2020
|
+
if key in self.__runtime_path_config:
|
2021
|
+
return Path(self.__runtime_path_config[key])
|
2020
2022
|
|
2021
2023
|
# If the key is not found, return None
|
2022
2024
|
return None
|
@@ -2078,7 +2080,7 @@ class Application(Container, IApplication):
|
|
2078
2080
|
# Mark as booted
|
2079
2081
|
self.__booted = True
|
2080
2082
|
|
2081
|
-
# Load core framework kernels
|
2083
|
+
# Load core framework kernels with app booted
|
2082
2084
|
self.__loadFrameworksKernel()
|
2083
2085
|
|
2084
2086
|
# Retrieve logger and console instances from the container
|
@@ -2094,4 +2096,41 @@ class Application(Container, IApplication):
|
|
2094
2096
|
logger.info(boot_message)
|
2095
2097
|
|
2096
2098
|
# Return the application instance for method chaining
|
2097
|
-
return self
|
2099
|
+
return self
|
2100
|
+
|
2101
|
+
def isProduction(
|
2102
|
+
self
|
2103
|
+
) -> bool:
|
2104
|
+
"""
|
2105
|
+
Check if the application is running in a production environment.
|
2106
|
+
|
2107
|
+
This method determines whether the current application environment is set to 'production'.
|
2108
|
+
It checks the 'app.env' configuration value to make this determination.
|
2109
|
+
|
2110
|
+
Returns
|
2111
|
+
-------
|
2112
|
+
bool
|
2113
|
+
True if the application environment is 'production', False otherwise.
|
2114
|
+
|
2115
|
+
Raises
|
2116
|
+
------
|
2117
|
+
OrionisRuntimeError
|
2118
|
+
If the application configuration has not been initialized (i.e., if `create()` has not been called).
|
2119
|
+
|
2120
|
+
Notes
|
2121
|
+
-----
|
2122
|
+
The environment is typically defined in the application configuration and can be set to values such as 'development', 'testing', or 'production'.
|
2123
|
+
This method is useful for conditionally executing code based on the environment, such as enabling/disabling debug features or logging verbosity.
|
2124
|
+
"""
|
2125
|
+
|
2126
|
+
# Retrieve the current application environment from configuration
|
2127
|
+
app_env = self.config('app.env')
|
2128
|
+
|
2129
|
+
# Ensure the application is booted before accessing configuration
|
2130
|
+
if app_env is None:
|
2131
|
+
raise OrionisRuntimeError(
|
2132
|
+
"Application configuration is not initialized. Please call create() before checking the environment."
|
2133
|
+
)
|
2134
|
+
|
2135
|
+
# Return True if the environment is 'production', otherwise False
|
2136
|
+
return str(app_env).lower() == 'production'
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from dataclasses import dataclass, field
|
2
|
-
from typing import List
|
3
2
|
from orionis.support.entities.base import BaseEntity
|
4
3
|
from orionis.foundation.config.testing.enums import ExecutionMode, PersistentDrivers, VerbosityMode
|
5
4
|
from orionis.foundation.exceptions import OrionisIntegrityException
|
@@ -32,8 +31,6 @@ class Testing(BaseEntity):
|
|
32
31
|
Filename pattern to identify test files (default: 'test_*.py').
|
33
32
|
test_name_pattern : str or None, optional
|
34
33
|
Pattern to match specific test names (default: None).
|
35
|
-
tags : list of str or None, optional
|
36
|
-
List of tags to filter tests (default: empty list).
|
37
34
|
persistent : bool, optional
|
38
35
|
If True, keep test results persistent (default: False).
|
39
36
|
persistent_driver : str or PersistentDrivers, optional
|
@@ -118,14 +115,6 @@ class Testing(BaseEntity):
|
|
118
115
|
}
|
119
116
|
)
|
120
117
|
|
121
|
-
tags: List[str] | None = field(
|
122
|
-
default_factory = lambda: [],
|
123
|
-
metadata = {
|
124
|
-
"description": "A list of tags to filter tests. Default is an empty list.",
|
125
|
-
"default": []
|
126
|
-
}
|
127
|
-
)
|
128
|
-
|
129
118
|
persistent: bool = field(
|
130
119
|
default = False,
|
131
120
|
metadata = {
|
@@ -255,18 +244,6 @@ class Testing(BaseEntity):
|
|
255
244
|
f"Invalid type for 'test_name_pattern': {type(self.test_name_pattern).__name__}. It must be a string or None."
|
256
245
|
)
|
257
246
|
|
258
|
-
# Validate tags attribute
|
259
|
-
if self.tags is not None:
|
260
|
-
if not isinstance(self.tags, list):
|
261
|
-
raise OrionisIntegrityException(
|
262
|
-
f"Invalid type for 'tags': {type(self.tags).__name__}. It must be a list of strings or None."
|
263
|
-
)
|
264
|
-
for i, tag in enumerate(self.tags):
|
265
|
-
if not isinstance(tag, str):
|
266
|
-
raise OrionisIntegrityException(
|
267
|
-
f"Invalid type for tag at index {i} in 'tags': {type(tag).__name__}. Each tag must be a string."
|
268
|
-
)
|
269
|
-
|
270
247
|
# Validate persistent attribute
|
271
248
|
if not isinstance(self.persistent, bool):
|
272
249
|
raise OrionisIntegrityException(
|
@@ -1245,4 +1245,31 @@ class IApplication(IContainer):
|
|
1245
1245
|
duplicate initialization. The startup time is calculated and logged
|
1246
1246
|
for performance monitoring purposes.
|
1247
1247
|
"""
|
1248
|
+
pass
|
1249
|
+
|
1250
|
+
@abstractmethod
|
1251
|
+
def isProduction(
|
1252
|
+
self
|
1253
|
+
) -> bool:
|
1254
|
+
"""
|
1255
|
+
Check if the application is running in a production environment.
|
1256
|
+
|
1257
|
+
This method determines whether the current application environment is set to 'production'.
|
1258
|
+
It checks the 'app.env' configuration value to make this determination.
|
1259
|
+
|
1260
|
+
Returns
|
1261
|
+
-------
|
1262
|
+
bool
|
1263
|
+
True if the application environment is 'production', False otherwise.
|
1264
|
+
|
1265
|
+
Raises
|
1266
|
+
------
|
1267
|
+
OrionisRuntimeError
|
1268
|
+
If the application configuration has not been initialized (i.e., if `create()` has not been called).
|
1269
|
+
|
1270
|
+
Notes
|
1271
|
+
-----
|
1272
|
+
The environment is typically defined in the application configuration and can be set to values such as 'development', 'testing', or 'production'.
|
1273
|
+
This method is useful for conditionally executing code based on the environment, such as enabling/disabling debug features or logging verbosity.
|
1274
|
+
"""
|
1248
1275
|
pass
|
orionis/metadata/framework.py
CHANGED
@@ -9,7 +9,7 @@ class IPerformanceCounter(ABC):
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
@abstractmethod
|
12
|
-
def start(self) ->
|
12
|
+
def start(self) -> 'IPerformanceCounter':
|
13
13
|
"""
|
14
14
|
Start the performance counter.
|
15
15
|
|
@@ -18,13 +18,13 @@ class IPerformanceCounter(ABC):
|
|
18
18
|
|
19
19
|
Returns
|
20
20
|
-------
|
21
|
-
|
22
|
-
The
|
21
|
+
IPerformanceCounter
|
22
|
+
The instance of the performance counter for method chaining.
|
23
23
|
"""
|
24
24
|
pass
|
25
25
|
|
26
26
|
@abstractmethod
|
27
|
-
def stop(self) ->
|
27
|
+
def stop(self) -> 'IPerformanceCounter':
|
28
28
|
"""
|
29
29
|
Stop the performance counter and calculate the elapsed time.
|
30
30
|
|
@@ -32,9 +32,106 @@ class IPerformanceCounter(ABC):
|
|
32
32
|
the elapsed time since `start()` was called. The elapsed time is the
|
33
33
|
difference between the end and start timestamps.
|
34
34
|
|
35
|
+
Returns
|
36
|
+
-------
|
37
|
+
IPerformanceCounter
|
38
|
+
The instance of the performance counter for method chaining.
|
39
|
+
"""
|
40
|
+
pass
|
41
|
+
|
42
|
+
@abstractmethod
|
43
|
+
def elapsedTime(self) -> float:
|
44
|
+
"""
|
45
|
+
Get the elapsed time between the last start and stop calls.
|
46
|
+
|
47
|
+
This method returns the elapsed time calculated during the last
|
48
|
+
`stop()` call. If the counter has not been started and stopped,
|
49
|
+
it raises an exception.
|
50
|
+
|
51
|
+
Returns
|
52
|
+
-------
|
53
|
+
float
|
54
|
+
The elapsed time in seconds (as a float) between the last `start()` and `stop()` calls.
|
55
|
+
|
56
|
+
Raises
|
57
|
+
------
|
58
|
+
ValueError
|
59
|
+
If the counter has not been started and stopped properly.
|
60
|
+
"""
|
61
|
+
pass
|
62
|
+
|
63
|
+
@abstractmethod
|
64
|
+
def getMicroseconds(self) -> float:
|
65
|
+
"""
|
66
|
+
Get the elapsed time in microseconds.
|
67
|
+
|
68
|
+
This method returns the elapsed time in microseconds by converting
|
69
|
+
the value obtained from `elapsedTime()`.
|
70
|
+
|
71
|
+
Returns
|
72
|
+
-------
|
73
|
+
float
|
74
|
+
The elapsed time in microseconds (as a float).
|
75
|
+
"""
|
76
|
+
pass
|
77
|
+
|
78
|
+
@abstractmethod
|
79
|
+
def getMilliseconds(self) -> float:
|
80
|
+
"""
|
81
|
+
Get the elapsed time in milliseconds.
|
82
|
+
|
83
|
+
This method returns the elapsed time in milliseconds by converting
|
84
|
+
the value obtained from `elapsedTime()`.
|
85
|
+
|
86
|
+
Returns
|
87
|
+
-------
|
88
|
+
float
|
89
|
+
The elapsed time in milliseconds (as a float).
|
90
|
+
"""
|
91
|
+
pass
|
92
|
+
|
93
|
+
@abstractmethod
|
94
|
+
def getSeconds(self) -> float:
|
95
|
+
"""
|
96
|
+
Get the elapsed time in seconds.
|
97
|
+
|
98
|
+
This method returns the elapsed time in seconds, which is the same
|
99
|
+
value as obtained from `elapsedTime()`.
|
100
|
+
|
101
|
+
Returns
|
102
|
+
-------
|
103
|
+
float
|
104
|
+
The elapsed time in seconds (as a float).
|
105
|
+
"""
|
106
|
+
pass
|
107
|
+
|
108
|
+
@abstractmethod
|
109
|
+
def getMinutes(self) -> float:
|
110
|
+
"""
|
111
|
+
Get the elapsed time in minutes.
|
112
|
+
|
113
|
+
This method returns the elapsed time in minutes by converting
|
114
|
+
the value obtained from `elapsedTime()`.
|
115
|
+
|
116
|
+
Returns
|
117
|
+
-------
|
118
|
+
float
|
119
|
+
The elapsed time in minutes (as a float).
|
120
|
+
"""
|
121
|
+
pass
|
122
|
+
|
123
|
+
@abstractmethod
|
124
|
+
def restart(self) -> float:
|
125
|
+
"""
|
126
|
+
Restart the performance counter.
|
127
|
+
|
128
|
+
This method resets the start and end times to None and starts the counter again.
|
129
|
+
It is useful for measuring a new interval without creating a new instance of
|
130
|
+
PerformanceCounter.
|
131
|
+
|
35
132
|
Returns
|
36
133
|
-------
|
37
134
|
float
|
38
|
-
The
|
135
|
+
The timestamp (in fractional seconds) at which the counter was restarted.
|
39
136
|
"""
|
40
137
|
pass
|
@@ -49,7 +49,10 @@ class PerformanceCounter(IPerformanceCounter):
|
|
49
49
|
# Time when the counter is stopped; initialized to None
|
50
50
|
self.__end_time = None
|
51
51
|
|
52
|
-
|
52
|
+
# Difference between end time and start time; initialized to None
|
53
|
+
self.__diff_time = None
|
54
|
+
|
55
|
+
def start(self) -> 'PerformanceCounter':
|
53
56
|
"""
|
54
57
|
Start the performance counter.
|
55
58
|
|
@@ -58,15 +61,15 @@ class PerformanceCounter(IPerformanceCounter):
|
|
58
61
|
|
59
62
|
Returns
|
60
63
|
-------
|
61
|
-
|
62
|
-
The
|
64
|
+
IPerformanceCounter
|
65
|
+
The instance of the performance counter for method chaining.
|
63
66
|
"""
|
64
67
|
|
65
68
|
# Record the current time as the start time
|
66
69
|
self.__start_time = time.perf_counter()
|
67
|
-
return self
|
70
|
+
return self
|
68
71
|
|
69
|
-
def stop(self) ->
|
72
|
+
def stop(self) -> 'PerformanceCounter':
|
70
73
|
"""
|
71
74
|
Stop the performance counter and calculate the elapsed time.
|
72
75
|
|
@@ -76,12 +79,119 @@ class PerformanceCounter(IPerformanceCounter):
|
|
76
79
|
|
77
80
|
Returns
|
78
81
|
-------
|
79
|
-
|
80
|
-
The
|
82
|
+
IPerformanceCounter
|
83
|
+
The instance of the performance counter for method chaining.
|
81
84
|
"""
|
82
85
|
|
83
86
|
# Record the current time as the end time
|
84
87
|
self.__end_time = time.perf_counter()
|
85
88
|
|
86
89
|
# Calculate and return the elapsed time
|
87
|
-
|
90
|
+
self.__diff_time = self.__end_time - self.__start_time
|
91
|
+
return self
|
92
|
+
|
93
|
+
def elapsedTime(self) -> float:
|
94
|
+
"""
|
95
|
+
Get the elapsed time between the last start and stop calls.
|
96
|
+
|
97
|
+
This method returns the elapsed time calculated during the last
|
98
|
+
`stop()` call. If the counter has not been started and stopped,
|
99
|
+
it raises an exception.
|
100
|
+
|
101
|
+
Returns
|
102
|
+
-------
|
103
|
+
float
|
104
|
+
The elapsed time in seconds (as a float) between the last `start()` and `stop()` calls.
|
105
|
+
|
106
|
+
Raises
|
107
|
+
------
|
108
|
+
ValueError
|
109
|
+
If the counter has not been started and stopped properly.
|
110
|
+
"""
|
111
|
+
|
112
|
+
if self.__diff_time is None:
|
113
|
+
raise ValueError("Counter has not been started and stopped properly.")
|
114
|
+
|
115
|
+
return self.__diff_time
|
116
|
+
|
117
|
+
def getMicroseconds(self) -> float:
|
118
|
+
"""
|
119
|
+
Get the elapsed time in microseconds.
|
120
|
+
|
121
|
+
This method returns the elapsed time in microseconds by converting
|
122
|
+
the value obtained from `elapsedTime()`.
|
123
|
+
|
124
|
+
Returns
|
125
|
+
-------
|
126
|
+
float
|
127
|
+
The elapsed time in microseconds (as a float).
|
128
|
+
"""
|
129
|
+
|
130
|
+
return self.elapsedTime() * 1_000_000
|
131
|
+
|
132
|
+
def getMilliseconds(self) -> float:
|
133
|
+
"""
|
134
|
+
Get the elapsed time in milliseconds.
|
135
|
+
|
136
|
+
This method returns the elapsed time in milliseconds by converting
|
137
|
+
the value obtained from `elapsedTime()`.
|
138
|
+
|
139
|
+
Returns
|
140
|
+
-------
|
141
|
+
float
|
142
|
+
The elapsed time in milliseconds (as a float).
|
143
|
+
"""
|
144
|
+
|
145
|
+
return self.elapsedTime() * 1_000
|
146
|
+
|
147
|
+
def getSeconds(self) -> float:
|
148
|
+
"""
|
149
|
+
Get the elapsed time in seconds.
|
150
|
+
|
151
|
+
This method returns the elapsed time in seconds, which is the same
|
152
|
+
value as obtained from `elapsedTime()`.
|
153
|
+
|
154
|
+
Returns
|
155
|
+
-------
|
156
|
+
float
|
157
|
+
The elapsed time in seconds (as a float).
|
158
|
+
"""
|
159
|
+
|
160
|
+
return self.elapsedTime()
|
161
|
+
|
162
|
+
def getMinutes(self) -> float:
|
163
|
+
"""
|
164
|
+
Get the elapsed time in minutes.
|
165
|
+
|
166
|
+
This method returns the elapsed time in minutes by converting
|
167
|
+
the value obtained from `elapsedTime()`.
|
168
|
+
|
169
|
+
Returns
|
170
|
+
-------
|
171
|
+
float
|
172
|
+
The elapsed time in minutes (as a float).
|
173
|
+
"""
|
174
|
+
|
175
|
+
return self.elapsedTime() / 60
|
176
|
+
|
177
|
+
def restart(self) -> float:
|
178
|
+
"""
|
179
|
+
Restart the performance counter.
|
180
|
+
|
181
|
+
This method resets the start and end times to None and starts the counter again.
|
182
|
+
It is useful for measuring a new interval without creating a new instance of
|
183
|
+
PerformanceCounter.
|
184
|
+
|
185
|
+
Returns
|
186
|
+
-------
|
187
|
+
float
|
188
|
+
The timestamp (in fractional seconds) at which the counter was restarted.
|
189
|
+
"""
|
190
|
+
|
191
|
+
# Reset start and end times
|
192
|
+
self.__start_time = None
|
193
|
+
self.__end_time = None
|
194
|
+
self.__diff_time = None
|
195
|
+
|
196
|
+
# Start the counter again
|
197
|
+
return self.start()
|
@@ -7,162 +7,6 @@ from orionis.foundation.config.testing.enums.verbosity import VerbosityMode
|
|
7
7
|
|
8
8
|
class IUnitTest(ABC):
|
9
9
|
|
10
|
-
@abstractmethod
|
11
|
-
def configure(
|
12
|
-
self,
|
13
|
-
*,
|
14
|
-
verbosity: int | VerbosityMode,
|
15
|
-
execution_mode: str | ExecutionMode,
|
16
|
-
max_workers: int,
|
17
|
-
fail_fast: bool,
|
18
|
-
print_result: bool,
|
19
|
-
throw_exception: bool,
|
20
|
-
persistent: bool,
|
21
|
-
persistent_driver: str | PersistentDrivers,
|
22
|
-
web_report: bool
|
23
|
-
) -> 'IUnitTest':
|
24
|
-
"""
|
25
|
-
Configure the unit test runner with the provided options.
|
26
|
-
|
27
|
-
Parameters
|
28
|
-
----------
|
29
|
-
verbosity : int or VerbosityMode
|
30
|
-
Verbosity level for test output.
|
31
|
-
execution_mode : str or ExecutionMode
|
32
|
-
Execution mode for running tests.
|
33
|
-
max_workers : int
|
34
|
-
Maximum number of worker threads or processes.
|
35
|
-
fail_fast : bool
|
36
|
-
Whether to stop on the first test failure.
|
37
|
-
print_result : bool
|
38
|
-
Whether to print test results to the console.
|
39
|
-
throw_exception : bool
|
40
|
-
Whether to raise exceptions on test failures.
|
41
|
-
persistent : bool
|
42
|
-
Whether to enable persistent storage for test results.
|
43
|
-
persistent_driver : str or PersistentDrivers
|
44
|
-
Persistent storage driver to use.
|
45
|
-
web_report : bool
|
46
|
-
Whether to generate a web-based test report.
|
47
|
-
|
48
|
-
Returns
|
49
|
-
-------
|
50
|
-
IUnitTest
|
51
|
-
The configured unit test runner instance.
|
52
|
-
"""
|
53
|
-
pass
|
54
|
-
|
55
|
-
@abstractmethod
|
56
|
-
def discoverTests(
|
57
|
-
self,
|
58
|
-
base_path: str | Path,
|
59
|
-
folder_path: str | List[str],
|
60
|
-
pattern: str,
|
61
|
-
test_name_pattern: Optional[str] = None,
|
62
|
-
tags: Optional[List[str]] = None
|
63
|
-
) -> 'IUnitTest':
|
64
|
-
"""
|
65
|
-
Discover test cases from specified folders using flexible path discovery.
|
66
|
-
|
67
|
-
This method provides a convenient way to discover and load test cases from multiple folders
|
68
|
-
based on various path specifications. It supports wildcard discovery, single folder loading,
|
69
|
-
and multiple folder loading. The method automatically resolves paths relative to the base
|
70
|
-
directory and discovers all folders containing files matching the specified pattern.
|
71
|
-
|
72
|
-
Parameters
|
73
|
-
----------
|
74
|
-
base_path : str or Path
|
75
|
-
Base directory path for resolving relative folder paths. This serves as the root
|
76
|
-
directory from which all folder searches are conducted.
|
77
|
-
folder_path : str or list of str
|
78
|
-
Specification of folders to search for test cases. Can be:
|
79
|
-
- '*' : Discover all folders containing matching files within base_path
|
80
|
-
- str : Single folder path relative to base_path
|
81
|
-
- list of str : Multiple folder paths relative to base_path
|
82
|
-
pattern : str
|
83
|
-
File name pattern to match test files, supporting wildcards (* and ?).
|
84
|
-
Examples: 'test_*.py', '*_test.py', 'test*.py'
|
85
|
-
test_name_pattern : str, optional
|
86
|
-
Regular expression pattern to filter test method names. Only tests whose
|
87
|
-
names match this pattern will be included. Default is None (no filtering).
|
88
|
-
tags : list of str, optional
|
89
|
-
List of tags to filter tests. Only tests decorated with matching tags
|
90
|
-
will be included. Default is None (no tag filtering).
|
91
|
-
|
92
|
-
Returns
|
93
|
-
-------
|
94
|
-
UnitTest
|
95
|
-
The current UnitTest instance with discovered tests added to the suite,
|
96
|
-
enabling method chaining.
|
97
|
-
|
98
|
-
Notes
|
99
|
-
-----
|
100
|
-
- All paths are resolved as absolute paths relative to the base_path
|
101
|
-
- When folder_path is '*', the method searches recursively through all subdirectories
|
102
|
-
- The method uses the existing discoverTestsInFolder method for actual test discovery
|
103
|
-
- Duplicate folders are automatically eliminated using a set data structure
|
104
|
-
- The method does not validate the existence of specified folders; validation
|
105
|
-
occurs during the actual test discovery process
|
106
|
-
"""
|
107
|
-
pass
|
108
|
-
|
109
|
-
@abstractmethod
|
110
|
-
def discoverTestsInFolder(
|
111
|
-
self,
|
112
|
-
*,
|
113
|
-
base_path: str | Path,
|
114
|
-
folder_path: str,
|
115
|
-
pattern: str,
|
116
|
-
test_name_pattern: Optional[str] = None,
|
117
|
-
tags: Optional[List[str]] = None
|
118
|
-
) -> 'IUnitTest':
|
119
|
-
"""
|
120
|
-
Discover test cases within a specified folder.
|
121
|
-
|
122
|
-
Parameters
|
123
|
-
----------
|
124
|
-
base_path : str or Path
|
125
|
-
Base directory for test discovery.
|
126
|
-
folder_path : str
|
127
|
-
Path to the folder containing test files.
|
128
|
-
pattern : str
|
129
|
-
File pattern to match test files.
|
130
|
-
test_name_pattern : str, optional
|
131
|
-
Pattern to match test function or class names.
|
132
|
-
tags : list of str, optional
|
133
|
-
Tags to filter discovered tests.
|
134
|
-
|
135
|
-
Returns
|
136
|
-
-------
|
137
|
-
IUnitTest
|
138
|
-
The unit test runner instance with discovered tests.
|
139
|
-
"""
|
140
|
-
pass
|
141
|
-
|
142
|
-
@abstractmethod
|
143
|
-
def discoverTestsInModule(
|
144
|
-
self,
|
145
|
-
*,
|
146
|
-
module_name: str,
|
147
|
-
test_name_pattern: Optional[str] = None
|
148
|
-
) -> 'IUnitTest':
|
149
|
-
"""
|
150
|
-
Discover test cases within a specified module.
|
151
|
-
|
152
|
-
Parameters
|
153
|
-
----------
|
154
|
-
module_name : str
|
155
|
-
Name of the module to search for tests.
|
156
|
-
test_name_pattern : str, optional
|
157
|
-
Pattern to match test function or class names.
|
158
|
-
|
159
|
-
Returns
|
160
|
-
-------
|
161
|
-
IUnitTest
|
162
|
-
The unit test runner instance with discovered tests.
|
163
|
-
"""
|
164
|
-
pass
|
165
|
-
|
166
10
|
@abstractmethod
|
167
11
|
def run(self) -> Dict[str, Any]:
|
168
12
|
"""
|