orionis 0.372.0__py3-none-any.whl → 0.374.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 (99) hide show
  1. orionis/__init__.py +4 -2
  2. orionis/container/facades/facade.py +10 -8
  3. orionis/container/resolver/resolver.py +3 -3
  4. orionis/foundation/application.py +25 -0
  5. orionis/metadata/framework.py +1 -1
  6. orionis/services/introspection/dependencies/entities/callable_dependencies.py +6 -6
  7. orionis/services/introspection/dependencies/entities/class_dependencies.py +7 -7
  8. orionis/services/introspection/dependencies/entities/{resolved_dependencies.py → known_dependencies.py} +1 -1
  9. orionis/services/introspection/dependencies/entities/method_dependencies.py +6 -6
  10. orionis/services/introspection/dependencies/reflection.py +4 -4
  11. orionis/test/arguments/parser.py +187 -0
  12. orionis/test/cases/asynchronous.py +145 -0
  13. orionis/test/cases/synchronous.py +135 -0
  14. orionis/test/contracts/kernel.py +134 -0
  15. orionis/test/contracts/logs.py +125 -0
  16. orionis/test/contracts/parser.py +43 -0
  17. orionis/test/contracts/render.py +30 -0
  18. orionis/test/contracts/unit_test.py +21 -0
  19. orionis/test/core/unit_test.py +104 -23
  20. orionis/test/entities/arguments.py +38 -0
  21. orionis/test/kernel.py +336 -0
  22. orionis/test/output/dumper.py +3 -4
  23. orionis/test/output/printer.py +22 -0
  24. orionis/test/{logs → record}/history.py +25 -9
  25. orionis/test/records/__init__.py +0 -0
  26. orionis/test/records/logs.py +385 -0
  27. orionis/test/view/render.py +8 -5
  28. {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/METADATA +1 -1
  29. {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/RECORD +93 -88
  30. tests/example/test_example.py +4 -3
  31. tests/foundation/config/app/test_foundation_config_app.py +2 -2
  32. tests/foundation/config/auth/test_foundation_config_auth.py +2 -2
  33. tests/foundation/config/cache/test_foundation_config_cache.py +2 -2
  34. tests/foundation/config/cache/test_foundation_config_cache_file.py +2 -2
  35. tests/foundation/config/cache/test_foundation_config_cache_stores.py +2 -2
  36. tests/foundation/config/cors/test_foundation_config_cors.py +2 -2
  37. tests/foundation/config/database/test_foundation_config_database.py +2 -2
  38. tests/foundation/config/database/test_foundation_config_database_connections.py +2 -2
  39. tests/foundation/config/database/test_foundation_config_database_mysql.py +2 -2
  40. tests/foundation/config/database/test_foundation_config_database_oracle.py +2 -2
  41. tests/foundation/config/database/test_foundation_config_database_pgsql.py +2 -2
  42. tests/foundation/config/database/test_foundation_config_database_sqlite.py +2 -2
  43. tests/foundation/config/filesystems/test_foundation_config_filesystems.py +2 -2
  44. tests/foundation/config/filesystems/test_foundation_config_filesystems_aws.py +2 -2
  45. tests/foundation/config/filesystems/test_foundation_config_filesystems_disks.py +2 -2
  46. tests/foundation/config/filesystems/test_foundation_config_filesystems_local.py +2 -2
  47. tests/foundation/config/filesystems/test_foundation_config_filesystems_public.py +2 -2
  48. tests/foundation/config/logging/test_foundation_config_logging.py +2 -2
  49. tests/foundation/config/logging/test_foundation_config_logging_channels.py +2 -2
  50. tests/foundation/config/logging/test_foundation_config_logging_chunked.py +2 -2
  51. tests/foundation/config/logging/test_foundation_config_logging_daily.py +2 -2
  52. tests/foundation/config/logging/test_foundation_config_logging_hourly.py +2 -2
  53. tests/foundation/config/logging/test_foundation_config_logging_monthly.py +2 -2
  54. tests/foundation/config/logging/test_foundation_config_logging_stack.py +2 -2
  55. tests/foundation/config/logging/test_foundation_config_logging_weekly.py +2 -2
  56. tests/foundation/config/mail/test_foundation_config_mail.py +2 -2
  57. tests/foundation/config/mail/test_foundation_config_mail_file.py +2 -2
  58. tests/foundation/config/mail/test_foundation_config_mail_mailers.py +2 -2
  59. tests/foundation/config/mail/test_foundation_config_mail_smtp.py +2 -2
  60. tests/foundation/config/queue/test_foundation_config_queue.py +2 -5
  61. tests/foundation/config/queue/test_foundation_config_queue_brokers.py +2 -2
  62. tests/foundation/config/queue/test_foundation_config_queue_database.py +3 -2
  63. tests/foundation/config/root/test_foundation_config_root_paths.py +3 -3
  64. tests/foundation/config/session/test_foundation_config_session.py +4 -3
  65. tests/foundation/config/startup/test_foundation_config_startup.py +4 -3
  66. tests/foundation/config/testing/test_foundation_config_testing.py +3 -3
  67. tests/foundation/exceptions/test_foundation_config_exceptions.py +3 -3
  68. tests/metadata/test_metadata_framework.py +2 -2
  69. tests/metadata/test_metadata_package.py +3 -2
  70. tests/services/asynchrony/test_services_asynchrony_coroutine.py +2 -2
  71. tests/services/environment/test_services_environment.py +2 -2
  72. tests/services/inspection/dependencies/test_reflect_dependencies.py +22 -22
  73. tests/services/inspection/reflection/test_reflection_abstract.py +2 -2
  74. tests/services/inspection/reflection/test_reflection_callable.py +2 -2
  75. tests/services/inspection/reflection/test_reflection_concrete.py +2 -2
  76. tests/services/inspection/reflection/test_reflection_instance.py +2 -2
  77. tests/services/inspection/reflection/test_reflection_module.py +2 -2
  78. tests/services/inspection/test_reflection.py +2 -2
  79. tests/services/path/test_services_resolver.py +2 -2
  80. tests/services/system/test_services_system_imports.py +2 -2
  81. tests/services/system/test_services_system_workers.py +3 -2
  82. tests/support/parsers/test_services_parser_exceptions.py +2 -2
  83. tests/support/patterns/singleton/test_patterns_singleton.py +2 -2
  84. tests/support/standard/test_services_std.py +2 -2
  85. tests/support/wrapper/test_services_wrapper_docdict.py +2 -2
  86. tests/testing/test_testing_result.py +4 -6
  87. tests/testing/test_testing_unit.py +9 -10
  88. orionis/test/cases/test_async.py +0 -55
  89. orionis/test/cases/test_case.py +0 -42
  90. orionis/test/cases/test_sync.py +0 -33
  91. orionis/test/contracts/history.py +0 -54
  92. orionis/test/test_suite.py +0 -142
  93. orionis/unittesting.py +0 -64
  94. /orionis/test/{logs → arguments}/__init__.py +0 -0
  95. /orionis/test/entities/{test_result.py → result.py} +0 -0
  96. {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/WHEEL +0 -0
  97. {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/licenses/LICENCE +0 -0
  98. {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/top_level.txt +0 -0
  99. {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/zip-safe +0 -0
@@ -0,0 +1,135 @@
1
+ import unittest
2
+ from orionis.test.output.dumper import TestDumper
3
+
4
+ class SyncTestCase(unittest.TestCase, TestDumper):
5
+ """
6
+ Base test case class for synchronous unit testing.
7
+
8
+ This class provides a foundation for writing synchronous unit tests within
9
+ the Orionis framework. It extends unittest.TestCase and includes TestDumper
10
+ functionality for enhanced test output and debugging capabilities.
11
+
12
+ The class provides hooks for custom setup and teardown logic through the
13
+ onSetup() and onTeardown() methods, which can be overridden by subclasses
14
+ to implement test-specific initialization and cleanup procedures.
15
+
16
+ Attributes
17
+ ----------
18
+ None
19
+
20
+ Methods
21
+ -------
22
+ setUp()
23
+ Initialize test environment before each test method execution.
24
+ tearDown()
25
+ Clean up test environment after each test method execution.
26
+ onSetup()
27
+ Hook method for subclass-specific setup logic.
28
+ onTeardown()
29
+ Hook method for subclass-specific teardown logic.
30
+
31
+ Examples
32
+ --------
33
+ >>> class MyTest(SyncTestCase):
34
+ ... def onSetup(self):
35
+ ... self.data = [1, 2, 3]
36
+ ...
37
+ ... def testExample(self):
38
+ ... self.assertEqual(len(self.data), 3)
39
+ """
40
+
41
+ def setUp(self):
42
+ """
43
+ Initialize the test environment before each test method.
44
+
45
+ This method is automatically called by the unittest framework before
46
+ each test method execution. It performs the standard unittest setup
47
+ and then calls the onSetup() hook for custom initialization.
48
+
49
+ Parameters
50
+ ----------
51
+ None
52
+
53
+ Returns
54
+ -------
55
+ None
56
+
57
+ Notes
58
+ -----
59
+ This method should not be overridden directly. Use onSetup() instead
60
+ for custom setup logic.
61
+ """
62
+ super().setUp()
63
+ self.onSetup()
64
+
65
+ def tearDown(self):
66
+ """
67
+ Clean up the test environment after each test method.
68
+
69
+ This method is automatically called by the unittest framework after
70
+ each test method execution. It calls the onTeardown() hook for custom
71
+ cleanup and then performs the standard unittest teardown.
72
+
73
+ Parameters
74
+ ----------
75
+ None
76
+
77
+ Returns
78
+ -------
79
+ None
80
+
81
+ Notes
82
+ -----
83
+ This method should not be overridden directly. Use onTeardown() instead
84
+ for custom teardown logic.
85
+ """
86
+ self.onTeardown()
87
+ super().tearDown()
88
+
89
+ def onSetup(self):
90
+ """
91
+ Hook method for subclass-specific setup logic.
92
+
93
+ This method is called during the setUp() phase and is intended to be
94
+ overridden by subclasses that need to perform custom initialization
95
+ before each test method execution.
96
+
97
+ Parameters
98
+ ----------
99
+ None
100
+
101
+ Returns
102
+ -------
103
+ None
104
+
105
+ Examples
106
+ --------
107
+ >>> def onSetup(self):
108
+ ... self.mock_service = MockService()
109
+ ... self.test_data = {"key": "value"}
110
+ """
111
+ pass
112
+
113
+ def onTeardown(self):
114
+ """
115
+ Hook method for subclass-specific teardown logic.
116
+
117
+ This method is called during the tearDown() phase and is intended to be
118
+ overridden by subclasses that need to perform custom cleanup after
119
+ each test method execution.
120
+
121
+ Parameters
122
+ ----------
123
+ None
124
+
125
+ Returns
126
+ -------
127
+ None
128
+
129
+ Examples
130
+ --------
131
+ >>> def onTeardown(self):
132
+ ... self.mock_service.cleanup()
133
+ ... del self.test_data
134
+ """
135
+ pass
@@ -0,0 +1,134 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any
3
+ from orionis.foundation.config.testing.entities.testing import Testing as Configuration
4
+ from orionis.test.core.unit_test import UnitTest
5
+
6
+ class ITestKernel(ABC):
7
+ """
8
+ Abstract interface for test kernel implementations.
9
+
10
+ This contract defines the required methods that any test kernel implementation
11
+ must provide for the Orionis testing framework. It ensures consistent behavior
12
+ across different test kernel implementations.
13
+
14
+ The test kernel is responsible for:
15
+ - Managing application context for testing
16
+ - Validating and handling test configuration
17
+ - Orchestrating test discovery and execution
18
+ - Providing a unified interface for test operations
19
+ """
20
+
21
+ @abstractmethod
22
+ def handle(
23
+ self,
24
+ config: Configuration = None,
25
+ **kwargs: Any
26
+ ) -> UnitTest:
27
+ """
28
+ Execute the complete test discovery and execution pipeline.
29
+
30
+ This is the main entry point for running tests. Implementations must:
31
+ 1. Validate the provided configuration
32
+ 2. Discover test files based on configuration
33
+ 3. Configure and execute the test suite
34
+ 4. Return the test results
35
+
36
+ Parameters
37
+ ----------
38
+ config : Configuration, optional
39
+ A pre-configured Testing configuration instance. If None,
40
+ implementations should create one from kwargs.
41
+ **kwargs : Any
42
+ Keyword arguments to create a Configuration instance if config is None.
43
+ Common parameters include:
44
+ - base_path : str, base directory for test discovery
45
+ - folder_path : str or list, specific folders to search
46
+ - pattern : str, file pattern for test discovery
47
+ - verbosity : int, output verbosity level
48
+ - execution_mode : str, test execution mode
49
+ - max_workers : int, maximum number of worker threads
50
+ - fail_fast : bool, stop on first failure
51
+
52
+ Returns
53
+ -------
54
+ UnitTest
55
+ The configured and executed test suite instance containing all results.
56
+
57
+ Raises
58
+ ------
59
+ OrionisTestConfigException
60
+ If the configuration validation fails.
61
+ """
62
+ pass
63
+
64
+ @abstractmethod
65
+ def handleCLI(
66
+ self,
67
+ sys_argv: list[str]
68
+ ) -> UnitTest:
69
+ """
70
+ Process command line arguments for test execution.
71
+
72
+ This method configures and runs tests based on command line arguments. It parses
73
+ the provided sys_argv list into a TestArguments object, extracts configuration
74
+ values, executes the tests, and handles output generation.
75
+
76
+ Parameters
77
+ ----------
78
+ sys_argv : list[str]
79
+ Command line arguments list including script name. The script name
80
+ (first element) will be automatically removed before parsing.
81
+
82
+ Returns
83
+ -------
84
+ UnitTest
85
+ The test suite instance containing all test results.
86
+
87
+ Raises
88
+ ------
89
+ OrionisTestConfigException
90
+ If the provided sys_argv is not a valid list or if argument parsing fails.
91
+
92
+ Notes
93
+ -----
94
+ The method supports various test execution options including parallel/sequential
95
+ execution mode, fail fast behavior, result output configuration, and web reporting.
96
+ """
97
+ pass
98
+
99
+ @abstractmethod
100
+ def exit(
101
+ self,
102
+ code: int = 0
103
+ ) -> None:
104
+ """
105
+ Terminate the test execution process and free associated resources.
106
+
107
+ This method performs a clean shutdown of the test kernel by explicitly
108
+ triggering garbage collection to release memory resources and then
109
+ terminating the process with the provided exit code. It ensures that any
110
+ remaining file handles, threads, or other resources are properly released.
111
+
112
+ Parameters
113
+ ----------
114
+ code : int
115
+ The exit code to return to the operating system. Should be 0 for
116
+ successful execution or a non-zero value to indicate an error.
117
+
118
+ Returns
119
+ -------
120
+ None
121
+ This method does not return as it terminates the process.
122
+
123
+ Raises
124
+ ------
125
+ ValueError
126
+ If the provided code is not a valid integer or outside the allowed range.
127
+
128
+ Notes
129
+ -----
130
+ Using os._exit() bypasses normal Python cleanup mechanisms and
131
+ immediately terminates the process. This can be necessary when
132
+ normal sys.exit() would be caught by exception handlers.
133
+ """
134
+ pass
@@ -0,0 +1,125 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Dict, List, Optional, Tuple
3
+
4
+ class ITestLogs(ABC):
5
+ """
6
+ Abstract base class for test logging and report persistence.
7
+
8
+ This interface defines the contract for managing test reports in a persistent
9
+ storage system. Implementations should provide functionality to create, retrieve,
10
+ and reset test report data while maintaining proper data validation and error
11
+ handling.
12
+
13
+ The interface supports chronological retrieval of reports and provides methods
14
+ for database management operations.
15
+
16
+ Methods
17
+ -------
18
+ create(report)
19
+ Create and store a new test report in the persistence layer.
20
+ reset()
21
+ Reset the storage by clearing all existing test reports.
22
+ get(first, last)
23
+ Retrieve test reports with optional chronological filtering.
24
+ """
25
+
26
+ @abstractmethod
27
+ def create(self, report: Dict) -> bool:
28
+ """
29
+ Create a new test report in the history database.
30
+
31
+ This method persists a test report containing execution results and
32
+ metadata to the underlying storage system. The report should include
33
+ all necessary fields for proper tracking and analysis.
34
+
35
+ Parameters
36
+ ----------
37
+ report : Dict
38
+ A dictionary containing the test report data. Must include fields
39
+ such as total_tests, passed, failed, errors, skipped, total_time,
40
+ success_rate, and timestamp.
41
+
42
+ Returns
43
+ -------
44
+ bool
45
+ True if the report was successfully created and stored, False otherwise.
46
+
47
+ Raises
48
+ ------
49
+ OrionisTestValueError
50
+ If the report structure is invalid or missing required fields.
51
+ OrionisTestPersistenceError
52
+ If there is an error during the storage operation.
53
+ """
54
+ pass
55
+
56
+ @abstractmethod
57
+ def reset(self) -> bool:
58
+ """
59
+ Reset the history database by dropping the existing table.
60
+
61
+ This method clears all stored test reports and resets the storage
62
+ system to its initial state. Use with caution as this operation
63
+ is irreversible and will result in permanent data loss.
64
+
65
+ Returns
66
+ -------
67
+ bool
68
+ True if the database was successfully reset, False otherwise.
69
+
70
+ Raises
71
+ ------
72
+ OrionisTestPersistenceError
73
+ If there is an error during the reset operation.
74
+
75
+ Notes
76
+ -----
77
+ This operation is destructive and cannot be undone. Ensure that
78
+ any important historical data is backed up before calling this method.
79
+ """
80
+ pass
81
+
82
+ @abstractmethod
83
+ def get(
84
+ self,
85
+ first: Optional[int] = None,
86
+ last: Optional[int] = None
87
+ ) -> List[Tuple]:
88
+ """
89
+ Retrieve test reports from the history database.
90
+
91
+ This method allows for chronological retrieval of test reports with
92
+ optional filtering. You can retrieve either the earliest or most recent
93
+ reports, but not both in a single call.
94
+
95
+ Parameters
96
+ ----------
97
+ first : Optional[int], default=None
98
+ The number of earliest reports to retrieve, ordered ascending by ID.
99
+ Must be a positive integer if specified.
100
+ last : Optional[int], default=None
101
+ The number of latest reports to retrieve, ordered descending by ID.
102
+ Must be a positive integer if specified.
103
+
104
+ Returns
105
+ -------
106
+ List[Tuple]
107
+ A list of tuples representing the retrieved reports. Each tuple
108
+ contains the report data in the order: (id, json, total_tests,
109
+ passed, failed, errors, skipped, total_time, success_rate, timestamp).
110
+
111
+ Raises
112
+ ------
113
+ OrionisTestValueError
114
+ If both 'first' and 'last' are specified, or if either parameter
115
+ is not a positive integer when provided.
116
+ OrionisTestPersistenceError
117
+ If there is an error retrieving reports from the storage system.
118
+
119
+ Notes
120
+ -----
121
+ Only one of 'first' or 'last' parameters can be specified in a single
122
+ call. The returned results are ordered chronologically based on the
123
+ selected parameter.
124
+ """
125
+ pass
@@ -0,0 +1,43 @@
1
+ from abc import ABC, abstractmethod
2
+ from orionis.test.entities.arguments import TestArguments
3
+
4
+ class ITestArgumentParser(ABC):
5
+ """
6
+ A parser class for handling test command-line arguments.
7
+
8
+ This class encapsulates the logic for creating and configuring the argument parser
9
+ for the Orionis test runner, providing a clean interface for parsing test arguments.
10
+ """
11
+
12
+ @abstractmethod
13
+ def parse(
14
+ self,
15
+ sys_argv: list[str]
16
+ ) -> TestArguments:
17
+ """
18
+ Parse command line arguments and return TestArguments object.
19
+
20
+ Parameters
21
+ ----------
22
+ sys_argv : list[str]
23
+ Command line arguments including script name. The script name (first element)
24
+ will be automatically removed before parsing.
25
+
26
+ Returns
27
+ -------
28
+ TestArguments
29
+ Parsed test arguments object containing all configuration options for test execution.
30
+
31
+ Raises
32
+ ------
33
+ SystemExit
34
+ If argument parsing fails or help is requested.
35
+ """
36
+ pass
37
+
38
+ @abstractmethod
39
+ def help(
40
+ self
41
+ ) -> None:
42
+ """Print help message for the test runner."""
43
+ pass
@@ -0,0 +1,30 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ class ITestingResultRender(ABC):
4
+
5
+ @abstractmethod
6
+ def render(
7
+ self
8
+ ) -> str:
9
+ """
10
+ Otherwise, uses the current test result stored in memory. The method replaces placeholders in a
11
+ template file with the test results and the persistence mode, then writes the rendered content
12
+ to a report file.
13
+
14
+ Parameters
15
+ ----------
16
+ None
17
+
18
+ Returns
19
+ -------
20
+ str
21
+ The full path to the generated report file.
22
+
23
+ Notes
24
+ -----
25
+ - If persistence is enabled, the last 10 reports are fetched from the SQLite database.
26
+ - If persistence is not enabled, only the current test result in memory is used.
27
+ - The method reads a template file, replaces placeholders with the test results and persistence mode,
28
+ and writes the final content to the report file.
29
+ """
30
+ pass
@@ -1,5 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from typing import Any, Dict, List, Optional
3
+ from orionis.foundation.contracts.application import IApplication
3
4
  from orionis.services.system.workers import Workers
4
5
  from orionis.test.enums.execution_mode import ExecutionMode
5
6
 
@@ -48,6 +49,26 @@ class IUnitTest(ABC):
48
49
  """
49
50
  pass
50
51
 
52
+ @abstractmethod
53
+ def setApplication(
54
+ self,
55
+ app: 'IApplication'
56
+ ):
57
+ """
58
+ Set the application instance for the UnitTest.
59
+ This method allows the UnitTest to access the application instance, which is necessary for resolving dependencies and executing tests.
60
+
61
+ Parameters
62
+ ----------
63
+ app : IApplication
64
+ The application instance to be set for the UnitTest.
65
+
66
+ Returns
67
+ -------
68
+ UnitTest
69
+ """
70
+ pass
71
+
51
72
  @abstractmethod
52
73
  def discoverTestsInFolder(
53
74
  self,
@@ -10,9 +10,10 @@ from contextlib import redirect_stdout, redirect_stderr
10
10
  from datetime import datetime
11
11
  from pathlib import Path
12
12
  from typing import Any, Dict, List, Optional, Tuple
13
+ from orionis.foundation.contracts.application import IApplication
13
14
  from orionis.services.introspection.instances.reflection import ReflectionInstance
14
15
  from orionis.services.system.workers import Workers
15
- from orionis.test.entities.test_result import TestResult
16
+ from orionis.test.entities.result import TestResult
16
17
  from orionis.test.enums import (
17
18
  ExecutionMode,
18
19
  TestStatus
@@ -22,7 +23,7 @@ from orionis.test.exceptions import (
22
23
  OrionisTestPersistenceError,
23
24
  OrionisTestValueError
24
25
  )
25
- from orionis.test.logs.history import TestHistory
26
+ from orionis.test.records.logs import TestLogs
26
27
  from orionis.test.contracts.unit_test import IUnitTest
27
28
  from orionis.test.output.printer import TestPrinter
28
29
  from orionis.test.view.render import TestingResultRender
@@ -42,7 +43,9 @@ class UnitTest(IUnitTest):
42
43
  This is an especially suitable choice for those seeking greater robustness, traceability, and visibility in their automated testing processes, offering advantages often missing from other alternatives.
43
44
  """
44
45
 
45
- def __init__(self) -> None:
46
+ def __init__(
47
+ self
48
+ ) -> None:
46
49
  """
47
50
  Initializes the test suite configuration and supporting components.
48
51
 
@@ -100,28 +103,30 @@ class UnitTest(IUnitTest):
100
103
  Result of the test execution.
101
104
  """
102
105
 
106
+ # Value for application instance
107
+ self.app: Optional[IApplication] = None
108
+
103
109
  # Values for configuration
104
- self.verbosity: int
105
- self.execution_mode: str
106
- self.max_workers: int
107
- self.fail_fast: bool
108
- self.print_result: bool
109
- self.throw_exception: bool
110
- self.persistent: bool
111
- self.persistent_driver: str
112
- self.web_report: bool
110
+ self.verbosity: Optional[int] = None
111
+ self.execution_mode: Optional[str] = None
112
+ self.max_workers: Optional[int] = None
113
+ self.fail_fast: Optional[bool] = None
114
+ self.print_result: Optional[bool] = None
115
+ self.throw_exception: Optional[bool] = None
116
+ self.persistent: Optional[bool] = None
117
+ self.persistent_driver: Optional[str] = None
118
+ self.web_report: Optional[bool] = None
113
119
 
114
120
  # Values for discovering tests in folders
115
- self.full_path: Optional[str]
116
- self.folder_path: str
117
- self.base_path: str
118
- self.pattern: str
119
- self.test_name_pattern: Optional[str]
120
- self.tags: Optional[List[str]]
121
+ self.full_path: Optional[str] = None
122
+ self.folder_path: Optional[str] = None
123
+ self.base_path: Optional[str] = None
124
+ self.pattern: Optional[str] = None
125
+ self.test_name_pattern: Optional[str] = None
126
+ self.tags: Optional[List[str]] = None
121
127
 
122
128
  # Values for discovering tests in modules
123
- self.module_name: str
124
- self.test_name_pattern: Optional[str]
129
+ self.module_name: Optional[str] = None
125
130
 
126
131
  # Initialize the test loader and suite
127
132
  self.loader = unittest.TestLoader()
@@ -138,6 +143,33 @@ class UnitTest(IUnitTest):
138
143
  # Result of the test execution
139
144
  self.__result = None
140
145
 
146
+ def setApplication(
147
+ self,
148
+ app: 'IApplication'
149
+ ) -> 'UnitTest':
150
+ """
151
+ Set the application instance for the UnitTest.
152
+ This method allows the UnitTest to access the application instance, which is necessary for resolving dependencies and executing tests.
153
+
154
+ Parameters
155
+ ----------
156
+ app : IApplication
157
+ The application instance to be set for the UnitTest.
158
+
159
+ Returns
160
+ -------
161
+ UnitTest
162
+ """
163
+
164
+ # Validate the provided application instance
165
+ if not isinstance(app, IApplication):
166
+ raise OrionisTestValueError(
167
+ f"The provided application is not a valid instance of IApplication: {type(app).__name__}."
168
+ )
169
+
170
+ # Set the application instance
171
+ self.app = app
172
+
141
173
  def configure(
142
174
  self,
143
175
  *,
@@ -657,6 +689,55 @@ class UnitTest(IUnitTest):
657
689
  # Flatten the suite to avoid duplicate tests
658
690
  flattened_suite = unittest.TestSuite(self.__flattenTestSuite(self.suite))
659
691
 
692
+ # Create a new test suite with tests that have their dependencies resolved
693
+ flattened_suite = unittest.TestSuite()
694
+ app = self.app
695
+
696
+ # Iterate through all test cases
697
+ for test_case in self.__flattenTestSuite(self.suite):
698
+ # Get the test method name
699
+ method_name = getattr(test_case, '_testMethodName', None)
700
+
701
+ # Skip if we can't identify the test method
702
+ if not method_name:
703
+ flattened_suite.addTest(test_case)
704
+ continue
705
+
706
+ # Extract dependencies for the test method
707
+ rsv = ReflectionInstance(test_case).getMethodDependencies(method_name)
708
+
709
+ # If no dependencies to resolve, just add the original test
710
+ if not rsv.resolved and not rsv.unresolved:
711
+ flattened_suite.addTest(test_case)
712
+ continue
713
+
714
+ # Create a specialized test case with resolved dependencies
715
+ test_class = test_case.__class__
716
+ original_method = getattr(test_class, method_name)
717
+
718
+ # Create a dict of resolved dependencies
719
+ args_ = {}
720
+ for k, v in rsv.resolved.items():
721
+ from orionis.services.introspection.dependencies.entities.known_dependencies import KnownDependency
722
+ if isinstance(v, KnownDependency):
723
+ args_[k] = app.make(v.type)
724
+
725
+ # Create a wrapper method that injects dependencies
726
+ def create_test_wrapper(original_test, resolved_args, unresolved_args):
727
+ def wrapper(self_instance):
728
+ args_list = list(resolved_args.values())
729
+ args_list.extend(unresolved_args)
730
+ return original_test(self_instance, *args_list)
731
+ return wrapper
732
+
733
+ # Create a new test case with the wrapped method
734
+ setattr(test_class, f"_wrapped_{method_name}", create_test_wrapper(original_method, args_, rsv.unresolved))
735
+ setattr(test_case, '_testMethodName', f"_wrapped_{method_name}")
736
+
737
+ # Add the modified test case to the suite
738
+ flattened_suite.addTest(test_case)
739
+ # sys.exit(0)
740
+
660
741
  # Create a custom result class to capture detailed test results
661
742
  with redirect_stdout(output_buffer), redirect_stderr(error_buffer):
662
743
  runner = unittest.TextTestRunner(
@@ -1108,7 +1189,7 @@ class UnitTest(IUnitTest):
1108
1189
  Notes
1109
1190
  -----
1110
1191
  Depending on the value of `self.persistent_driver`, the summary is either:
1111
- - Stored in an SQLite database (using the TestHistory class), or
1192
+ - Stored in an SQLite database (using the TestLogs class), or
1112
1193
  - Written to a timestamped JSON file in the specified base path.
1113
1194
 
1114
1195
  Raises
@@ -1129,8 +1210,8 @@ class UnitTest(IUnitTest):
1129
1210
 
1130
1211
  if self.persistent_driver == 'sqlite':
1131
1212
 
1132
- # Initialize the TestHistory class for database operations
1133
- history = TestHistory(
1213
+ # Initialize the TestLogs class for database operations
1214
+ history = TestLogs(
1134
1215
  storage_path=storage_path,
1135
1216
  db_name='tests.sqlite',
1136
1217
  table_name='reports'