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.
- orionis/__init__.py +4 -2
- orionis/container/facades/facade.py +10 -8
- orionis/container/resolver/resolver.py +3 -3
- orionis/foundation/application.py +25 -0
- orionis/metadata/framework.py +1 -1
- orionis/services/introspection/dependencies/entities/callable_dependencies.py +6 -6
- orionis/services/introspection/dependencies/entities/class_dependencies.py +7 -7
- orionis/services/introspection/dependencies/entities/{resolved_dependencies.py → known_dependencies.py} +1 -1
- orionis/services/introspection/dependencies/entities/method_dependencies.py +6 -6
- orionis/services/introspection/dependencies/reflection.py +4 -4
- orionis/test/arguments/parser.py +187 -0
- orionis/test/cases/asynchronous.py +145 -0
- orionis/test/cases/synchronous.py +135 -0
- orionis/test/contracts/kernel.py +134 -0
- orionis/test/contracts/logs.py +125 -0
- orionis/test/contracts/parser.py +43 -0
- orionis/test/contracts/render.py +30 -0
- orionis/test/contracts/unit_test.py +21 -0
- orionis/test/core/unit_test.py +104 -23
- orionis/test/entities/arguments.py +38 -0
- orionis/test/kernel.py +336 -0
- orionis/test/output/dumper.py +3 -4
- orionis/test/output/printer.py +22 -0
- orionis/test/{logs → record}/history.py +25 -9
- orionis/test/records/__init__.py +0 -0
- orionis/test/records/logs.py +385 -0
- orionis/test/view/render.py +8 -5
- {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/METADATA +1 -1
- {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/RECORD +93 -88
- tests/example/test_example.py +4 -3
- tests/foundation/config/app/test_foundation_config_app.py +2 -2
- tests/foundation/config/auth/test_foundation_config_auth.py +2 -2
- tests/foundation/config/cache/test_foundation_config_cache.py +2 -2
- tests/foundation/config/cache/test_foundation_config_cache_file.py +2 -2
- tests/foundation/config/cache/test_foundation_config_cache_stores.py +2 -2
- tests/foundation/config/cors/test_foundation_config_cors.py +2 -2
- tests/foundation/config/database/test_foundation_config_database.py +2 -2
- tests/foundation/config/database/test_foundation_config_database_connections.py +2 -2
- tests/foundation/config/database/test_foundation_config_database_mysql.py +2 -2
- tests/foundation/config/database/test_foundation_config_database_oracle.py +2 -2
- tests/foundation/config/database/test_foundation_config_database_pgsql.py +2 -2
- tests/foundation/config/database/test_foundation_config_database_sqlite.py +2 -2
- tests/foundation/config/filesystems/test_foundation_config_filesystems.py +2 -2
- tests/foundation/config/filesystems/test_foundation_config_filesystems_aws.py +2 -2
- tests/foundation/config/filesystems/test_foundation_config_filesystems_disks.py +2 -2
- tests/foundation/config/filesystems/test_foundation_config_filesystems_local.py +2 -2
- tests/foundation/config/filesystems/test_foundation_config_filesystems_public.py +2 -2
- tests/foundation/config/logging/test_foundation_config_logging.py +2 -2
- tests/foundation/config/logging/test_foundation_config_logging_channels.py +2 -2
- tests/foundation/config/logging/test_foundation_config_logging_chunked.py +2 -2
- tests/foundation/config/logging/test_foundation_config_logging_daily.py +2 -2
- tests/foundation/config/logging/test_foundation_config_logging_hourly.py +2 -2
- tests/foundation/config/logging/test_foundation_config_logging_monthly.py +2 -2
- tests/foundation/config/logging/test_foundation_config_logging_stack.py +2 -2
- tests/foundation/config/logging/test_foundation_config_logging_weekly.py +2 -2
- tests/foundation/config/mail/test_foundation_config_mail.py +2 -2
- tests/foundation/config/mail/test_foundation_config_mail_file.py +2 -2
- tests/foundation/config/mail/test_foundation_config_mail_mailers.py +2 -2
- tests/foundation/config/mail/test_foundation_config_mail_smtp.py +2 -2
- tests/foundation/config/queue/test_foundation_config_queue.py +2 -5
- tests/foundation/config/queue/test_foundation_config_queue_brokers.py +2 -2
- tests/foundation/config/queue/test_foundation_config_queue_database.py +3 -2
- tests/foundation/config/root/test_foundation_config_root_paths.py +3 -3
- tests/foundation/config/session/test_foundation_config_session.py +4 -3
- tests/foundation/config/startup/test_foundation_config_startup.py +4 -3
- tests/foundation/config/testing/test_foundation_config_testing.py +3 -3
- tests/foundation/exceptions/test_foundation_config_exceptions.py +3 -3
- tests/metadata/test_metadata_framework.py +2 -2
- tests/metadata/test_metadata_package.py +3 -2
- tests/services/asynchrony/test_services_asynchrony_coroutine.py +2 -2
- tests/services/environment/test_services_environment.py +2 -2
- tests/services/inspection/dependencies/test_reflect_dependencies.py +22 -22
- tests/services/inspection/reflection/test_reflection_abstract.py +2 -2
- tests/services/inspection/reflection/test_reflection_callable.py +2 -2
- tests/services/inspection/reflection/test_reflection_concrete.py +2 -2
- tests/services/inspection/reflection/test_reflection_instance.py +2 -2
- tests/services/inspection/reflection/test_reflection_module.py +2 -2
- tests/services/inspection/test_reflection.py +2 -2
- tests/services/path/test_services_resolver.py +2 -2
- tests/services/system/test_services_system_imports.py +2 -2
- tests/services/system/test_services_system_workers.py +3 -2
- tests/support/parsers/test_services_parser_exceptions.py +2 -2
- tests/support/patterns/singleton/test_patterns_singleton.py +2 -2
- tests/support/standard/test_services_std.py +2 -2
- tests/support/wrapper/test_services_wrapper_docdict.py +2 -2
- tests/testing/test_testing_result.py +4 -6
- tests/testing/test_testing_unit.py +9 -10
- orionis/test/cases/test_async.py +0 -55
- orionis/test/cases/test_case.py +0 -42
- orionis/test/cases/test_sync.py +0 -33
- orionis/test/contracts/history.py +0 -54
- orionis/test/test_suite.py +0 -142
- orionis/unittesting.py +0 -64
- /orionis/test/{logs → arguments}/__init__.py +0 -0
- /orionis/test/entities/{test_result.py → result.py} +0 -0
- {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/WHEEL +0 -0
- {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.372.0.dist-info → orionis-0.374.0.dist-info}/top_level.txt +0 -0
- {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,
|
orionis/test/core/unit_test.py
CHANGED
|
@@ -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.
|
|
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
|
|
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__(
|
|
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
|
|
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
|
|
1133
|
-
history =
|
|
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'
|