orionis 0.245.0__py3-none-any.whl → 0.246.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.
Files changed (37) hide show
  1. orionis/framework.py +1 -1
  2. orionis/luminate/config/contracts/__init__.py +0 -0
  3. orionis/luminate/config/contracts/config.py +27 -0
  4. orionis/luminate/config/entities/__init__.py +0 -0
  5. orionis/luminate/config/entities/testing.py +37 -0
  6. orionis/luminate/support/environment/env.py +1 -0
  7. orionis/luminate/support/introspection/abstracts/entities/__init__.py +0 -0
  8. orionis/luminate/support/introspection/abstracts/entities/abstract_class_attributes.py +11 -0
  9. orionis/luminate/support/introspection/abstracts/reflect_abstract.py +154 -16
  10. orionis/luminate/support/introspection/instances/reflection_instance.py +2 -2
  11. orionis/luminate/test/core/contracts/test_unit.py +100 -60
  12. orionis/luminate/test/core/test_suite.py +52 -45
  13. orionis/luminate/test/core/test_unit.py +774 -197
  14. orionis/luminate/test/entities/test_result.py +6 -2
  15. orionis/luminate/test/enums/test_mode.py +16 -0
  16. orionis/luminate/test/exceptions/test_config_exception.py +28 -0
  17. orionis/luminate/test/exceptions/test_exception.py +40 -33
  18. orionis/luminate/test/output/test_std_out.py +55 -13
  19. {orionis-0.245.0.dist-info → orionis-0.246.0.dist-info}/METADATA +1 -1
  20. {orionis-0.245.0.dist-info → orionis-0.246.0.dist-info}/RECORD +37 -29
  21. tests/support/inspection/fakes/fake_reflect_abstract.py +61 -5
  22. tests/support/inspection/test_reflect_abstract.py +62 -1
  23. tests/support/inspection/test_reflect_instance.py +0 -1
  24. /orionis/luminate/config/{app.py → entities/app.py} +0 -0
  25. /orionis/luminate/config/{auth.py → entities/auth.py} +0 -0
  26. /orionis/luminate/config/{cache.py → entities/cache.py} +0 -0
  27. /orionis/luminate/config/{cors.py → entities/cors.py} +0 -0
  28. /orionis/luminate/config/{database.py → entities/database.py} +0 -0
  29. /orionis/luminate/config/{filesystems.py → entities/filesystems.py} +0 -0
  30. /orionis/luminate/config/{logging.py → entities/logging.py} +0 -0
  31. /orionis/luminate/config/{mail.py → entities/mail.py} +0 -0
  32. /orionis/luminate/config/{queue.py → entities/queue.py} +0 -0
  33. /orionis/luminate/config/{session.py → entities/session.py} +0 -0
  34. {orionis-0.245.0.dist-info → orionis-0.246.0.dist-info}/LICENCE +0 -0
  35. {orionis-0.245.0.dist-info → orionis-0.246.0.dist-info}/WHEEL +0 -0
  36. {orionis-0.245.0.dist-info → orionis-0.246.0.dist-info}/entry_points.txt +0 -0
  37. {orionis-0.245.0.dist-info → orionis-0.246.0.dist-info}/top_level.txt +0 -0
orionis/framework.py CHANGED
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.245.0"
8
+ VERSION = "0.246.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
File without changes
@@ -0,0 +1,27 @@
1
+ from abc import ABC
2
+ from dataclasses import dataclass
3
+
4
+ @dataclass
5
+ class EmptyData:
6
+ """
7
+ A placeholder dataclass that can be used as a default or empty configuration.
8
+ This class doesn't have any fields or data, but serves as a default value
9
+ for the 'config' attribute in classes implementing IConfig.
10
+ """
11
+ pass
12
+
13
+ class IConfig(ABC):
14
+ """
15
+ An abstract base class that defines an interface for classes that must have
16
+ a `config` attribute.
17
+
18
+ The subclass is required to implement the `config` attribute, which should be
19
+ a dataclass instance representing the configuration data.
20
+
21
+ Attributes
22
+ ----------
23
+ config : object
24
+ A dataclass instance representing the configuration.
25
+ """
26
+
27
+ config = EmptyData()
File without changes
@@ -0,0 +1,37 @@
1
+ from dataclasses import dataclass
2
+ from typing import List
3
+
4
+ @dataclass(frozen=True, kw_only=True)
5
+ class Testing:
6
+ """
7
+ Testing is a dataclass that holds configuration options for running tests.
8
+
9
+ Attributes:
10
+ verbosity (int): The verbosity level of the test output. Default is 2.
11
+ - 0: Silent
12
+ - 1: Minimal output
13
+ - 2: Detailed output (default)
14
+ execution_mode (ExecutionMode): The mode of test execution. Default is ExecutionMode.SEQUENTIAL.
15
+ - ExecutionMode.SEQUENTIAL: Tests are executed one after another.
16
+ - ExecutionMode.PARALLEL: Tests are executed in parallel.
17
+ max_workers (int): The maximum number of worker threads/processes to use when running tests in parallel. Default is 4.
18
+ fail_fast (bool): Whether to stop execution after the first test failure. Default is False.
19
+ print_result (bool): Whether to print the test results to the console. Default is True.
20
+ throw_exception (bool): Whether to throw an exception if a test fails. Default is False.
21
+ base_path (str): The base directory where tests are located. Default is 'tests'.
22
+ folder_path (str): The folder path pattern to search for tests. Default is '*'.
23
+ pattern (str): The filename pattern to identify test files. Default is 'test_*.py'.
24
+ test_name_pattern (str | None): A pattern to match specific test names. Default is None.
25
+ tags (List[str] | None): A list of tags to filter tests. Default is None.
26
+ """
27
+ verbosity: int = 2
28
+ execution_mode: str = 'sequential'
29
+ max_workers: int = 4
30
+ fail_fast: bool = False
31
+ print_result: bool = True
32
+ throw_exception: bool = False
33
+ base_path: str = 'tests'
34
+ folder_path: str = '*'
35
+ pattern: str = 'test_*.py'
36
+ test_name_pattern: str | None = None,
37
+ tags: List[str] | None = None
@@ -8,6 +8,7 @@ from orionis.luminate.support.environment.functions import (
8
8
  _serialize_value,
9
9
  _delete_file
10
10
  )
11
+ from orionis.luminate.support.patterns.singleton import SingletonMeta
11
12
 
12
13
  class Env(IEnv):
13
14
  """
@@ -0,0 +1,11 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any, Dict
3
+
4
+ @dataclass(frozen=True, kw_only=True)
5
+ class AbstractClassAttributes:
6
+ """
7
+ A class to represent the attributes of an entity.
8
+ """
9
+ public: Dict[str, Any]
10
+ private: Dict[str, Any]
11
+ protected: Dict[str, Any]
@@ -3,11 +3,11 @@ import ast
3
3
  import inspect
4
4
  import types
5
5
  from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, TypeVar
6
- from orionis.luminate.support.introspection.contracts.reflexion_abstract import IReflexionAbstract
6
+ from orionis.luminate.support.introspection.abstracts.entities.abstract_class_attributes import AbstractClassAttributes
7
7
 
8
8
  ABC = TypeVar('ABC', bound=abc.ABC)
9
9
 
10
- class ReflexionAbstract(IReflexionAbstract):
10
+ class ReflexionAbstract:
11
11
  """A reflection object encapsulating an abstract class.
12
12
 
13
13
  Parameters
@@ -64,7 +64,7 @@ class ReflexionAbstract(IReflexionAbstract):
64
64
  """
65
65
  return self._abstract.__module__
66
66
 
67
- def getAllAttributes(self) -> Dict[str, Any]:
67
+ def getAllAttributes(self) -> AbstractClassAttributes:
68
68
  """
69
69
  Get all attributes of the abstract class.
70
70
 
@@ -93,11 +93,161 @@ class ReflexionAbstract(IReflexionAbstract):
93
93
  else:
94
94
  public[attr] = value
95
95
 
96
- return {"public": public, "protected": protected, "private": private}
96
+ return AbstractClassAttributes(
97
+ public=public,
98
+ private=private,
99
+ protected=protected
100
+ )
97
101
 
102
+ def getAttributes(self) -> Dict[str, Any]:
103
+ """
104
+ Get all attributes of the instance.
98
105
 
106
+ Returns
107
+ -------
108
+ Dict[str, Any]
109
+ Dictionary of attribute names and their values
110
+ """
111
+ attr = self.getAllAttributes()
112
+ return {**attr.public, **attr.private, **attr.protected}
99
113
 
114
+ def getPublicAttributes(self) -> Dict[str, Any]:
115
+ """
116
+ Get all public attributes of the instance.
100
117
 
118
+ Returns
119
+ -------
120
+ Dict[str, Any]
121
+ Dictionary of public attribute names and their values
122
+ """
123
+ attr = self.getAllAttributes()
124
+ return attr.public
125
+
126
+ def getPrivateAttributes(self) -> Dict[str, Any]:
127
+ """
128
+ Get all private attributes of the instance.
129
+
130
+ Returns
131
+ -------
132
+ Dict[str, Any]
133
+ Dictionary of private attribute names and their values
134
+ """
135
+ attr = self.getAllAttributes()
136
+ return attr.private
137
+
138
+ def getProtectedAttributes(self) -> Dict[str, Any]:
139
+ """
140
+ Get all Protected attributes of the instance.
141
+
142
+ Returns
143
+ -------
144
+ Dict[str, Any]
145
+ Dictionary of Protected attribute names and their values
146
+ """
147
+ attr = self.getAllAttributes()
148
+ return attr.protected
149
+
150
+ def getAllMethods(self) -> Dict[str, List[str]]:
151
+ """
152
+ Categorize all methods and relevant members of the abstract class into public, private, protected,
153
+ static, asynchronous, synchronous, class methods, magic methods, abstract methods, and properties.
154
+
155
+ Returns
156
+ -------
157
+ Dict[str, List[str]]
158
+ A dictionary categorizing methods and attributes into various types.
159
+ """
160
+ class_name = self.getClassName()
161
+ private_prefix = f"_{class_name}"
162
+ attributes = set(self.getAttributes().keys()) | {attr for attr in dir(self._abstract) if attr.startswith('_abc_')}
163
+
164
+ result = {
165
+ "public": [],
166
+ "private": [],
167
+ "protected": [],
168
+ "static": [],
169
+ "asynchronous": [],
170
+ "synchronous": [],
171
+ "class_methods": [],
172
+ "asynchronous_static": [],
173
+ "synchronous_static": [],
174
+ "magic": [],
175
+ "abstract": [],
176
+ "abstract_class_methods": [],
177
+ "abstract_static_methods": []
178
+ }
179
+
180
+ # Precompute all members once
181
+ members = inspect.getmembers(self._abstract)
182
+ static_attrs = {}
183
+
184
+ # First pass to collect all relevant information
185
+ for name, attr in members:
186
+ if name in attributes:
187
+ continue
188
+
189
+ # Get static attribute once
190
+ static_attr = inspect.getattr_static(self._abstract, name)
191
+ static_attrs[name] = static_attr
192
+
193
+ # Magic methods
194
+ if name.startswith("__") and name.endswith("__"):
195
+ result["magic"].append(name)
196
+ continue
197
+
198
+ # Static and class methods
199
+ if isinstance(static_attr, staticmethod):
200
+ result["static"].append(name)
201
+ elif isinstance(static_attr, classmethod):
202
+ result["class_methods"].append(name)
203
+
204
+ # Private, protected, public
205
+ if name.startswith(private_prefix):
206
+ clean_name = name.replace(private_prefix, "")
207
+ result["private"].append(clean_name)
208
+ elif name.startswith("_"):
209
+ result["protected"].append(name)
210
+ else:
211
+ result["public"].append(name)
212
+
213
+ # Async methods
214
+ if inspect.iscoroutinefunction(attr):
215
+ clean_name = name.replace(private_prefix, "")
216
+ if name in result["static"]:
217
+ result["asynchronous_static"].append(clean_name)
218
+ else:
219
+ result["asynchronous"].append(clean_name)
220
+
221
+ # Second pass for synchronous methods (needs info from first pass)
222
+ for name, attr in members:
223
+ if name in attributes or name in result["magic"] or name in result["class_methods"] or name in result["static"]:
224
+ continue
225
+
226
+ if inspect.isfunction(attr):
227
+ clean_name = name.replace(private_prefix, "")
228
+ if clean_name not in result["asynchronous"]:
229
+ result["synchronous"].append(clean_name)
230
+
231
+ # Synchronous static methods
232
+ for name in result["static"]:
233
+ if name not in attributes and name not in result["asynchronous_static"] and name not in result["class_methods"]:
234
+ result["synchronous_static"].append(name)
235
+
236
+ # Abstract methods
237
+ abstract_methods = getattr(self._abstract, "__abstractmethods__", set())
238
+ for name in abstract_methods:
239
+ if name in attributes:
240
+ continue
241
+
242
+ static_attr = static_attrs.get(name, inspect.getattr_static(self._abstract, name))
243
+ if isinstance(static_attr, staticmethod):
244
+ result["abstract_static_methods"].append(name)
245
+ elif isinstance(static_attr, classmethod):
246
+ result["abstract_class_methods"].append(name)
247
+ elif not isinstance(static_attr, property):
248
+ result["abstract"].append(name)
249
+
250
+ return result
101
251
 
102
252
 
103
253
 
@@ -109,19 +259,7 @@ class ReflexionAbstract(IReflexionAbstract):
109
259
 
110
260
 
111
261
 
112
- def getAbstractMethods(self) -> Set[str]:
113
- """Get all abstract method names required by the class.
114
262
 
115
- Returns
116
- -------
117
- Set[str]
118
- Set of abstract method names
119
- """
120
- methods = []
121
- for method in self._abstract.__abstractmethods__:
122
- if not isinstance(getattr(self._abstract, method), property):
123
- methods.append(method)
124
- return set(methods)
125
263
 
126
264
  def getAbstractProperties(self) -> Set[str]:
127
265
  """Get all abstract property names required by the class.
@@ -171,8 +171,8 @@ class ReflectionInstance(IReflectionInstance):
171
171
  def getAllMethods(self):
172
172
  """
173
173
  Retrieves and categorizes all methods of the instance's class into various classifications.
174
- This method inspects the instance's class and its methods, categorizing them into public, private,
175
- protected, static, asynchronous, synchronous, class methods, asynchronous static, synchronous static,
174
+ This method inspects the instance's class and its methods, categorizing them into public, private,
175
+ protected, static, asynchronous, synchronous, class methods, asynchronous static, synchronous static,
176
176
  and magic methods.
177
177
  Returns
178
178
  -------
@@ -1,82 +1,122 @@
1
- from typing import Any, Dict, Optional
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Dict, List, Optional
3
+ from orionis.luminate.test.enums.test_mode import ExecutionMode
2
4
 
3
- class IUnitTest:
4
- """
5
- Advanced unit testing utility for discovering, executing, and reporting test results
6
- with support for folder-based discovery, regex filtering, and customizable output.
5
+ class IUnitTest(ABC):
7
6
 
8
- Attributes
9
- ----------
10
- loader : unittest.TestLoader
11
- Internal loader for test discovery.
12
- suite : unittest.TestSuite
13
- The aggregated test suite to be executed.
14
- test_results : List[TestResult]
15
- List of captured results per test, including status and errors.
16
- start_time : float
17
- Timestamp when the test execution started.
18
- """
7
+ @abstractmethod
8
+ def configure(
9
+ self,
10
+ verbosity: int = None,
11
+ execution_mode: ExecutionMode = None,
12
+ max_workers: int = None,
13
+ fail_fast: bool = None,
14
+ print_result: bool = None
15
+ ):
16
+ """
17
+ Configures the UnitTest instance with the specified parameters.
18
+
19
+ Parameters:
20
+ verbosity (int, optional): The verbosity level for test output. Defaults to None.
21
+ execution_mode (ExecutionMode, optional): The mode in which the tests will be executed. Defaults to None.
22
+ max_workers (int, optional): The maximum number of workers to use for parallel execution. Defaults to None.
23
+ fail_fast (bool, optional): Whether to stop execution upon the first failure. Defaults to None.
24
+ print_result (bool, optional): Whether to print the test results after execution. Defaults to None.
25
+
26
+ Returns:
27
+ UnitTest: The configured UnitTest instance.
28
+ """
29
+ pass
19
30
 
31
+ @abstractmethod
20
32
  def discoverTestsInFolder(
21
33
  self,
22
34
  folder_path: str,
23
35
  base_path: str = "tests",
24
36
  pattern: str = "test_*.py",
25
- test_name_pattern: Optional[str] = None
37
+ test_name_pattern: Optional[str] = None,
38
+ tags: Optional[List[str]] = None
26
39
  ):
27
40
  """
28
- Discover and add test cases from a given folder to the test suite.
41
+ Discovers and loads unit tests from a specified folder.
42
+ Args:
43
+ folder_path (str): The relative path to the folder containing the tests.
44
+ base_path (str, optional): The base directory where the test folder is located. Defaults to "tests".
45
+ pattern (str, optional): The filename pattern to match test files. Defaults to "test_*.py".
46
+ test_name_pattern (Optional[str], optional): A pattern to filter test names. Defaults to None.
47
+ tags (Optional[List[str]], optional): A list of tags to filter tests. Defaults to None.
48
+ Returns:
49
+ UnitTest: The current instance of the UnitTest class with the discovered tests added.
50
+ Raises:
51
+ ValueError: If the test folder does not exist, no tests are found, or an error occurs during test discovery.
52
+ """
53
+ pass
54
+
55
+ @abstractmethod
56
+ def discoverTestsInModule(self, module_name: str, test_name_pattern: Optional[str] = None):
57
+ """
58
+ Discovers and loads tests from a specified module, optionally filtering them
59
+ by a test name pattern, and adds them to the test suite.
60
+ Args:
61
+ module_name (str): The name of the module to discover tests from.
62
+ test_name_pattern (Optional[str]): A pattern to filter test names. Only
63
+ tests matching this pattern will be included. Defaults to None.
64
+ Returns:
65
+ UnitTest: The current instance of the UnitTest class, allowing method chaining.
66
+ Raises:
67
+ ValueError: If the specified module cannot be imported.
68
+ """
69
+ pass
70
+
71
+ @abstractmethod
72
+ def run(self, print_result: bool = None, throw_exception: bool = False) -> Dict[str, Any]:
73
+ """
74
+ Executes the test suite and processes the results.
75
+ Args:
76
+ print_result (bool, optional): If provided, overrides the instance's
77
+ `print_result` attribute to determine whether to print the test results.
78
+ throw_exception (bool, optional): If True, raises an exception if any
79
+ test failures or errors are detected.
80
+ Returns:
81
+ Dict[str, Any]: A summary of the test execution, including details such as
82
+ execution time, test results, and a timestamp.
83
+ Raises:
84
+ OrionisTestFailureException: If `throw_exception` is True and there are
85
+ test failures or errors.
86
+ """
87
+ pass
29
88
 
30
- Parameters
31
- ----------
32
- folder_path : str
33
- Relative path to the folder containing test files.
34
- base_path : str, default="tests"
35
- Base path used to resolve full path to test modules.
36
- pattern : str, default="test_*.py"
37
- Glob pattern to match test filenames.
38
- test_name_pattern : Optional[str], optional
39
- Regex pattern to filter discovered test method names.
89
+ @abstractmethod
90
+ def getTestNames(self) -> List[str]:
91
+ """
92
+ Retrieves a list of test names from the test suite.
40
93
 
41
- Returns
42
- -------
43
- UnitTest
44
- Self instance for chaining.
94
+ This method flattens the test suite and extracts the unique identifier
95
+ (`id`) of each test case.
45
96
 
46
- Raises
47
- ------
48
- ValueError
49
- If folder is invalid or no tests are found.
97
+ Returns:
98
+ List[str]: A list of test names (unique identifiers) from the test suite.
50
99
  """
51
100
  pass
52
101
 
53
- def run(self, print_result:bool = True, throw_exception:bool = False) -> Dict[str, Any]:
102
+ @abstractmethod
103
+ def getTestCount(self) -> int:
54
104
  """
55
- Run all added tests and return a summary of the results.
105
+ Calculate the total number of tests in the test suite.
56
106
 
57
- Parameters
58
- ----------
59
- print_result : bool, default=True
60
- Whether to print a formatted report to the console.
61
- throw_exception : bool, default=False
62
- Raise an exception if there are failures or errors.
107
+ This method flattens the test suite structure and counts the total
108
+ number of individual test cases.
63
109
 
64
- Returns
65
- -------
66
- Dict[str, Any]
67
- Summary including:
68
- - total_tests : int
69
- - passed : int
70
- - failed : int
71
- - errors : int
72
- - skipped : int
73
- - total_time : str (e.g., '1.234 seconds')
74
- - success_rate : str (e.g., '87.5%')
75
- - test_details : List[Dict[str, Any]]
110
+ Returns:
111
+ int: The total number of test cases in the test suite.
112
+ """
113
+ pass
114
+
115
+ @abstractmethod
116
+ def clearTests(self) -> None:
117
+ """
118
+ Clears the current test suite by reinitializing it to an empty `unittest.TestSuite`.
76
119
 
77
- Raises
78
- ------
79
- OrionisTestFailureException
80
- If any test fails or errors occur and `throw_exception=True`.
120
+ This method is used to reset the test suite, removing any previously added tests.
81
121
  """
82
122
  pass
@@ -1,53 +1,61 @@
1
1
  import re
2
2
  from os import walk
3
- from orionis.luminate.test.core.contracts.test_suite import ITestSuite
4
- from orionis.luminate.test.core.test_unit import UnitTest as UnitTestClass
3
+ from orionis.luminate.config.entities.testing import Testing
4
+ from orionis.luminate.test.core.test_unit import UnitTest
5
+ from orionis.luminate.test.exceptions.test_config_exception import OrionisTestConfigException
5
6
 
6
- class TestSuite(ITestSuite):
7
- """
8
- A class containing test utility methods.
9
- """
7
+ class TestSuite:
10
8
 
11
9
  @staticmethod
12
- def load(
13
- base_path: str = 'tests',
14
- folder_path: list | str = '*',
15
- pattern: str = 'test_*.py'
16
- ) -> UnitTestClass:
10
+ def config(config:Testing) -> UnitTest:
11
+ """
12
+ Configures and initializes a test suite based on the provided configuration.
13
+ Args:
14
+ config (Testing): An instance of the `Testing` class containing configuration
15
+ parameters for the test suite.
16
+ Returns:
17
+ UnitTest: An initialized test suite configured with the provided settings.
18
+ Raises:
19
+ OrionisTestConfigException: If the `config` parameter is not an instance of
20
+ the `Testing` class.
21
+ The function performs the following steps:
22
+ 1. Validates that the `config` parameter is an instance of the `Testing` class.
23
+ 2. Initializes a `UnitTest` object and assigns configuration values to it.
24
+ 3. Extracts configuration values such as `base_path`, `folder_path`, and `pattern`.
25
+ 4. Discovers folders matching the specified `folder_path` and `pattern`:
26
+ - If `folder_path` is '*', all matching folders in the `base_path` are discovered.
27
+ - If `folder_path` is a list, matching folders in each path are discovered.
28
+ - Otherwise, matching folders in the specified `folder_path` are discovered.
29
+ 5. Adds discovered folders to the test suite by calling `discoverTestsInFolder`.
30
+ Notes:
31
+ - The `list_matching_folders` helper function is used to find folders matching
32
+ the specified pattern.
33
+ - The `pattern` supports wildcard characters (`*` and `?`) for flexible matching.
34
+ - The `test_name_pattern` and `tags` from the `config` are used when adding
35
+ folders to the test suite.
17
36
  """
18
- Discover and initialize a test suite from the specified folder(s).
19
37
 
20
- This method scans the provided folder(s) for test files matching the given pattern
21
- and initializes a test suite with the discovered files.
38
+ # Check if the config is an instance of Testing
39
+ if not isinstance(config, Testing):
40
+ raise OrionisTestConfigException("The config parameter must be an instance of the Testing class.")
22
41
 
23
- Parameters
24
- ----------
25
- base_path : str, optional
26
- The base path for the tests. Defaults to 'tests'.
27
- folder_path : str or list of str, optional
28
- Path(s) to the folder(s) containing test files. Use '*' to scan all folders
29
- under the base path. Defaults to '*'.
30
- pattern : str, optional
31
- File pattern to match test files. Defaults to 'test_*.py'.
42
+ # Initialize the test suite
43
+ tests = UnitTest()
32
44
 
33
- Returns
34
- -------
35
- UnitTestClass
36
- An initialized test suite containing the discovered test files.
45
+ # Assign config values to the test suite
46
+ tests.configure(
47
+ verbosity=config.verbosity,
48
+ execution_mode=config.execution_mode,
49
+ max_workers=config.max_workers,
50
+ fail_fast=config.fail_fast,
51
+ print_result=config.print_result,
52
+ throw_exception=config.throw_exception
53
+ )
37
54
 
38
- Raises
39
- ------
40
- TypeError
41
- If `base_path` is not a string, `folder_path` is not a string or list, or
42
- `pattern` is not a string.
43
- """
44
- # Validate parameters
45
- if not isinstance(base_path, str):
46
- raise TypeError("base_path must be a string")
47
- if not isinstance(folder_path, (str, list)):
48
- raise TypeError("folder_path must be a string or a list")
49
- if not isinstance(pattern, str):
50
- raise TypeError("pattern must be a string")
55
+ # Extract configuration values
56
+ base_path = config.base_path
57
+ folder_path = config.folder_path
58
+ pattern = config.pattern
51
59
 
52
60
  # Helper function to list folders matching the pattern
53
61
  def list_matching_folders(custom_path: str, pattern: str):
@@ -70,15 +78,14 @@ class TestSuite(ITestSuite):
70
78
  else:
71
79
  discovered_folders.extend(list_matching_folders(folder_path, pattern))
72
80
 
73
- # Initialize the test suite
74
- tests = UnitTestClass()
75
-
76
81
  # Add discovered folders to the test suite
77
82
  for folder in discovered_folders:
78
83
  tests.discoverTestsInFolder(
79
- base_path=base_path,
80
84
  folder_path=folder,
81
- pattern=pattern
85
+ base_path=base_path,
86
+ pattern=pattern,
87
+ test_name_pattern=config.test_name_pattern if config.test_name_pattern else None,
88
+ tags=config.tags if config.tags else None
82
89
  )
83
90
 
84
91
  # Return the initialized test suite