orionis 0.432.0__py3-none-any.whl → 0.434.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 (76) hide show
  1. orionis/app.py +17 -0
  2. orionis/metadata/framework.py +1 -1
  3. orionis/support/entities/base.py +18 -37
  4. orionis/support/facades/console.py +3 -9
  5. orionis/support/facades/dumper.py +3 -9
  6. orionis/support/facades/logger.py +3 -9
  7. orionis/support/facades/path_resolver.py +3 -10
  8. orionis/support/facades/progress_bar.py +3 -10
  9. orionis/support/facades/testing.py +4 -10
  10. orionis/support/facades/workers.py +4 -9
  11. orionis/support/formatter/exceptions/contracts/parser.py +10 -7
  12. orionis/support/formatter/exceptions/parser.py +28 -26
  13. orionis/support/formatter/serializer.py +12 -5
  14. orionis/support/patterns/singleton/meta.py +17 -21
  15. orionis/support/standard/contracts/std.py +25 -24
  16. orionis/support/standard/exceptions/value.py +2 -2
  17. orionis/support/standard/std.py +26 -24
  18. orionis/support/wrapper/dot_dict.py +16 -51
  19. orionis/test/cases/asynchronous.py +17 -81
  20. orionis/test/cases/synchronous.py +17 -73
  21. orionis/test/contracts/dumper.py +17 -21
  22. orionis/test/contracts/kernel.py +5 -12
  23. orionis/test/contracts/logs.py +16 -21
  24. orionis/test/contracts/printer.py +70 -8
  25. orionis/test/contracts/render.py +7 -13
  26. orionis/test/contracts/test_result.py +58 -27
  27. orionis/test/contracts/unit_test.py +18 -18
  28. orionis/test/core/unit_test.py +162 -519
  29. orionis/test/entities/result.py +49 -21
  30. orionis/test/enums/status.py +11 -17
  31. orionis/test/exceptions/config.py +4 -8
  32. orionis/test/exceptions/failure.py +2 -18
  33. orionis/test/exceptions/persistence.py +4 -8
  34. orionis/test/exceptions/runtime.py +4 -8
  35. orionis/test/exceptions/value.py +5 -13
  36. orionis/test/kernel.py +14 -42
  37. orionis/test/output/dumper.py +21 -43
  38. orionis/test/output/printer.py +6 -146
  39. orionis/test/records/logs.py +57 -121
  40. orionis/test/validators/base_path.py +8 -6
  41. orionis/test/validators/execution_mode.py +2 -3
  42. orionis/test/validators/fail_fast.py +4 -8
  43. orionis/test/validators/folder_path.py +5 -7
  44. orionis/test/validators/module_name.py +3 -3
  45. orionis/test/validators/name_pattern.py +4 -9
  46. orionis/test/validators/pattern.py +4 -9
  47. orionis/test/validators/persistent.py +4 -14
  48. orionis/test/validators/persistent_driver.py +7 -12
  49. orionis/test/validators/print_result.py +4 -9
  50. orionis/test/validators/tags.py +6 -7
  51. orionis/test/validators/throw_exception.py +7 -14
  52. orionis/test/validators/verbosity.py +15 -5
  53. orionis/test/validators/web_report.py +6 -10
  54. orionis/test/validators/workers.py +9 -4
  55. orionis/test/view/render.py +9 -26
  56. {orionis-0.432.0.dist-info → orionis-0.434.0.dist-info}/METADATA +1 -1
  57. {orionis-0.432.0.dist-info → orionis-0.434.0.dist-info}/RECORD +76 -75
  58. tests/support/entities/mock_dataclass.py +16 -10
  59. tests/support/entities/test_base.py +6 -14
  60. tests/support/patterns/singleton/test_patterns_singleton.py +7 -8
  61. tests/support/standard/test_services_std.py +113 -37
  62. tests/support/wrapper/test_services_wrapper_docdict.py +25 -40
  63. tests/testing/cases/test_testing_asynchronous.py +14 -14
  64. tests/testing/cases/test_testing_synchronous.py +12 -14
  65. tests/testing/entities/test_testing_result.py +12 -51
  66. tests/testing/enums/test_testing_status.py +8 -13
  67. tests/testing/output/test_testing_dumper.py +3 -6
  68. tests/testing/output/test_testing_printer.py +5 -5
  69. tests/testing/records/test_testing_records.py +16 -26
  70. tests/testing/test_testing_unit.py +8 -94
  71. tests/testing/validators/test_testing_validators.py +55 -112
  72. tests/testing/view/test_render.py +4 -5
  73. {orionis-0.432.0.dist-info → orionis-0.434.0.dist-info}/WHEEL +0 -0
  74. {orionis-0.432.0.dist-info → orionis-0.434.0.dist-info}/licenses/LICENCE +0 -0
  75. {orionis-0.432.0.dist-info → orionis-0.434.0.dist-info}/top_level.txt +0 -0
  76. {orionis-0.432.0.dist-info → orionis-0.434.0.dist-info}/zip-safe +0 -0
@@ -51,81 +51,68 @@ class UnitTest(IUnitTest):
51
51
 
52
52
  Advanced unit testing manager for the Orionis framework.
53
53
 
54
- This class offers a robust and extensible solution for discovering, executing, and reporting unit tests with high configurability. It supports both sequential and parallel execution modes, filtering by test name or tags, and provides detailed result tracking including execution times, error messages, and tracebacks.
55
-
56
- Key features:
57
- - Flexible test discovery from folders or modules, with pattern and tag filtering.
58
- - Rich result reporting: console output, persistent storage (SQLite or JSON), and web-based reports.
59
- - Dependency injection for test methods via the application context.
60
- - Customizable verbosity, fail-fast, and exception handling options.
61
- - Designed for easy integration into CI/CD pipelines and adaptable to diverse project requirements.
62
-
63
- Orionis UnitTest is ideal for teams seeking enhanced traceability, reliability, and visibility in automated testing, with capabilities that go beyond standard unittest frameworks.
54
+ This class provides mechanisms for discovering, executing, and reporting unit tests with extensive configurability. It supports sequential and parallel execution, test filtering by name or tags, and detailed result tracking including execution times, error messages, and tracebacks.
55
+
56
+ Attributes
57
+ ----------
58
+ __app : Optional[IApplication]
59
+ Application instance for dependency injection.
60
+ __verbosity : Optional[int]
61
+ Verbosity level for test output.
62
+ __execution_mode : Optional[str]
63
+ Execution mode for tests ('SEQUENTIAL' or 'PARALLEL').
64
+ __max_workers : Optional[int]
65
+ Maximum number of workers for parallel execution.
66
+ __fail_fast : Optional[bool]
67
+ Whether to stop on first failure.
68
+ __throw_exception : Optional[bool]
69
+ Whether to raise exceptions on test failures.
70
+ __persistent : Optional[bool]
71
+ Whether to persist test results.
72
+ __persistent_driver : Optional[str]
73
+ Persistence driver ('sqlite' or 'json').
74
+ __web_report : Optional[bool]
75
+ Whether to generate a web report.
76
+ __folder_path : Optional[str]
77
+ Folder path for test discovery.
78
+ __base_path : Optional[str]
79
+ Base directory for test discovery.
80
+ __pattern : Optional[str]
81
+ File name pattern for test discovery.
82
+ __test_name_pattern : Optional[str]
83
+ Pattern for filtering test names.
84
+ __tags : Optional[List[str]]
85
+ Tags for filtering tests.
86
+ __module_name : Optional[str]
87
+ Module name for test discovery.
88
+ __loader : unittest.TestLoader
89
+ Loader for discovering tests.
90
+ __suite : unittest.TestSuite
91
+ Test suite containing discovered tests.
92
+ __discovered_tests : List
93
+ List of discovered test metadata.
94
+ __printer : Optional[TestPrinter]
95
+ Utility for printing test results.
96
+ __output_buffer : Optional[str]
97
+ Buffer for capturing standard output.
98
+ __error_buffer : Optional[str]
99
+ Buffer for capturing error output.
100
+ __result : Optional[dict]
101
+ Result summary of the test execution.
64
102
  """
65
103
 
66
104
  def __init__(
67
105
  self
68
106
  ) -> None:
69
107
  """
70
- Initialize a new UnitTest instance with default configuration and internal state.
108
+ Initialize a UnitTest instance with default configuration and internal state.
71
109
 
72
- This constructor sets up all internal attributes required for test discovery, execution,
73
- result reporting, and configuration management. It prepares the instance for further
74
- configuration and use, but does not perform any test discovery or execution itself.
75
-
76
- Attributes
77
- ----------
78
- __app : Optional[IApplication]
79
- The application instance used for dependency injection in test cases.
80
- __verbosity : Optional[int]
81
- Verbosity level for test output (None until configured).
82
- __execution_mode : Optional[str]
83
- Test execution mode, e.g., 'SEQUENTIAL' or 'PARALLEL' (None until configured).
84
- __max_workers : Optional[int]
85
- Maximum number of worker threads/processes for parallel execution (None until configured).
86
- __fail_fast : Optional[bool]
87
- If True, stops execution upon the first test failure (None until configured).
88
- __throw_exception : Optional[bool]
89
- If True, raises exceptions on test failures (None until configured).
90
- __persistent : Optional[bool]
91
- If True, enables persistent storage for test results (None until configured).
92
- __persistent_driver : Optional[str]
93
- The driver to use for persistence, e.g., 'sqlite' or 'json' (None until configured).
94
- __web_report : Optional[bool]
95
- If True, enables web-based reporting of test results (None until configured).
96
- __folder_path : Optional[str]
97
- Relative folder path for test discovery (None until set).
98
- __base_path : Optional[str]
99
- Base directory for test discovery (None until set).
100
- __pattern : Optional[str]
101
- File name pattern to match test files (None until set).
102
- __test_name_pattern : Optional[str]
103
- Pattern to filter test names (None until set).
104
- __tags : Optional[List[str]]
105
- List of tags to filter tests (None until set).
106
- __module_name : Optional[str]
107
- Name of the module for test discovery (None until set).
108
- __loader : unittest.TestLoader
109
- Loader for discovering tests.
110
- __suite : unittest.TestSuite
111
- Test suite containing discovered tests.
112
- __discovered_tests : List
113
- List of discovered test metadata.
114
- __printer : Optional[TestPrinter]
115
- Utility for printing test results to the console.
116
- __output_buffer : Optional[str]
117
- Buffer for capturing standard output during tests.
118
- __error_buffer : Optional[str]
119
- Buffer for capturing error output during tests.
120
- __result : Optional[dict]
121
- Result summary of the test execution.
110
+ Sets up all internal attributes required for test discovery, execution, result reporting, and configuration management. Does not perform test discovery or execution.
122
111
 
123
112
  Returns
124
113
  -------
125
114
  None
126
- This constructor does not return a value.
127
115
  """
128
-
129
116
  # Application instance for dependency injection (set via __setApp)
130
117
  self.__app: Optional[IApplication] = None
131
118
 
@@ -181,44 +168,39 @@ class UnitTest(IUnitTest):
181
168
  web_report: bool
182
169
  ) -> 'UnitTest':
183
170
  """
184
- Configures the UnitTest instance with the main execution and reporting parameters.
185
-
186
- This method sets all relevant options for running unit tests in Orionis, including execution mode
187
- (sequential or parallel), verbosity level, maximum number of workers, result persistence, exception
188
- handling, and web report generation.
171
+ Configure the UnitTest instance with execution and reporting parameters.
189
172
 
190
173
  Parameters
191
174
  ----------
192
- verbosity : int | VerbosityMode
193
- Verbosity level for test output. Can be an integer or a VerbosityMode enum member.
194
- execution_mode : str | ExecutionMode
195
- Test execution mode ('SEQUENTIAL' or 'PARALLEL'), as a string or ExecutionMode enum.
175
+ verbosity : int or VerbosityMode
176
+ Verbosity level for test output.
177
+ execution_mode : str or ExecutionMode
178
+ Execution mode ('SEQUENTIAL' or 'PARALLEL').
196
179
  max_workers : int
197
- Maximum number of threads/processes for parallel execution. Must be between 1 and the maximum allowed by Workers.
180
+ Maximum number of workers for parallel execution.
198
181
  fail_fast : bool
199
- If True, stops execution on the first failure.
182
+ Whether to stop on the first failure.
200
183
  print_result : bool
201
- If True, prints results to the console.
184
+ Whether to print results to the console.
202
185
  throw_exception : bool
203
- If True, raises exceptions on test failures.
186
+ Whether to raise exceptions on test failures.
204
187
  persistent : bool
205
- If True, enables result persistence.
188
+ Whether to enable result persistence.
206
189
  persistent_driver : str or PersistentDrivers
207
- Persistence driver to use ('sqlite' or 'json').
190
+ Persistence driver ('sqlite' or 'json').
208
191
  web_report : bool
209
- If True, enables web report generation.
192
+ Whether to enable web report generation.
210
193
 
211
194
  Returns
212
195
  -------
213
196
  UnitTest
214
- The configured UnitTest instance, allowing method chaining.
197
+ The configured UnitTest instance.
215
198
 
216
199
  Raises
217
200
  ------
218
201
  OrionisTestValueError
219
- If any parameter is invalid or does not meet the expected requirements.
202
+ If any parameter is invalid.
220
203
  """
221
-
222
204
  # Validate and assign parameters using specialized validators
223
205
  self.__verbosity = ValidVerbosity(verbosity)
224
206
  self.__execution_mode = ValidExecutionMode(execution_mode)
@@ -249,48 +231,29 @@ class UnitTest(IUnitTest):
249
231
  """
250
232
  Discover and add unit tests from a specified folder to the test suite.
251
233
 
252
- This method searches for test files within a given folder, using a file name pattern,
253
- and optionally filters discovered tests by test name pattern and tags. All matching
254
- tests are added to the internal test suite. The method also records metadata about
255
- the discovery process, such as the folder path and the number of tests found.
256
-
257
234
  Parameters
258
235
  ----------
259
236
  base_path : str or Path
260
- The base directory from which the folder path is resolved.
237
+ Base directory for resolving the folder path.
261
238
  folder_path : str
262
- The relative path to the folder containing test files, relative to `base_path`.
239
+ Relative path to the folder containing test files.
263
240
  pattern : str
264
- The file name pattern to match test files (e.g., 'test_*.py').
241
+ File name pattern to match test files.
265
242
  test_name_pattern : str, optional
266
- A regular expression pattern to filter test names. Only tests whose names match
267
- this pattern will be included. If None, all test names are included.
243
+ Regular expression pattern to filter test names.
268
244
  tags : list of str, optional
269
- A list of tags to filter tests. Only tests decorated or marked with any of these
270
- tags will be included. If None, no tag filtering is applied.
245
+ Tags to filter tests.
271
246
 
272
247
  Returns
273
248
  -------
274
249
  UnitTest
275
- The current instance with the discovered tests added to the suite.
250
+ The current instance with discovered tests added.
276
251
 
277
252
  Raises
278
253
  ------
279
254
  OrionisTestValueError
280
- If any argument is invalid, the folder does not exist, no tests are found,
281
- or if there are import or discovery errors.
282
-
283
- Notes
284
- -----
285
- - The method validates all input parameters using Orionis validators.
286
- - The folder path is resolved relative to the provided base path.
287
- - Test discovery uses Python's unittest loader.
288
- - If `test_name_pattern` is provided, only tests whose names match the pattern are included.
289
- - If `tags` are provided, only tests with matching tags are included.
290
- - If no tests are found after filtering, an exception is raised.
291
- - Metadata about the discovery (folder and test count) is appended to the internal record.
255
+ If arguments are invalid, folder does not exist, no tests are found, or import/discovery errors occur.
292
256
  """
293
-
294
257
  # Validate Parameters
295
258
  self.__base_path = ValidBasePath(base_path)
296
259
  self.__folder_path = ValidFolderPath(folder_path)
@@ -400,40 +363,23 @@ class UnitTest(IUnitTest):
400
363
  """
401
364
  Discover and add unit tests from a specified Python module to the test suite.
402
365
 
403
- This method loads all unit tests defined within the given module and adds them to the internal test suite.
404
- Optionally, it can filter discovered tests by a regular expression pattern applied to test names.
405
-
406
366
  Parameters
407
367
  ----------
408
368
  module_name : str
409
- The fully qualified name of the module from which to discover tests (e.g., 'myproject.tests.test_example').
410
- Must be a non-empty string and importable from the current environment.
411
- test_name_pattern : str or None, optional
412
- A regular expression pattern to filter test names. Only tests whose names match this pattern
413
- will be included in the suite. If None, all discovered tests are included.
369
+ Fully qualified name of the module to discover tests from.
370
+ test_name_pattern : str, optional
371
+ Regular expression pattern to filter test names.
414
372
 
415
373
  Returns
416
374
  -------
417
375
  UnitTest
418
- The current UnitTest instance with the discovered tests added, allowing method chaining.
376
+ The current UnitTest instance with discovered tests added.
419
377
 
420
378
  Raises
421
379
  ------
422
380
  OrionisTestValueError
423
- If `module_name` is invalid, `test_name_pattern` is not a valid regex, the module cannot be imported,
424
- or if no tests are found after filtering.
425
- OrionisTestValueError
426
- For any unexpected error during test discovery, with details about the failure.
427
-
428
- Notes
429
- -----
430
- - Input parameters are validated using Orionis validators before discovery.
431
- - If `test_name_pattern` is provided, only tests matching the pattern are included.
432
- - Metadata about the discovery (module name and test count) is appended to the internal `__discovered_tests` list.
433
- - This method is useful for dynamically loading tests from specific modules, such as in plugin architectures or
434
- when tests are not organized in standard file patterns.
381
+ If module_name is invalid, test_name_pattern is not a valid regex, the module cannot be imported, or no tests are found.
435
382
  """
436
-
437
383
  # Validate input parameters
438
384
  self.__module_name = ValidModuleName(module_name)
439
385
  self.__test_name_pattern = ValidNamePattern(test_name_pattern)
@@ -503,28 +449,16 @@ class UnitTest(IUnitTest):
503
449
  """
504
450
  Execute the test suite and return a summary of the results.
505
451
 
506
- This method manages the full test execution lifecycle: it prints start and finish messages,
507
- executes the test suite, captures output and error buffers, processes the results, and
508
- optionally raises an exception if failures occur and exception throwing is enabled.
509
-
510
452
  Returns
511
453
  -------
512
- Dict[str, Any]
513
- A dictionary summarizing the test results, including statistics and execution time.
454
+ dict
455
+ Dictionary summarizing the test results, including statistics and execution time.
514
456
 
515
457
  Raises
516
458
  ------
517
459
  OrionisTestFailureException
518
- If the test suite execution fails and `throw_exception` is set to True.
519
-
520
- Notes
521
- -----
522
- - Measures total execution time in milliseconds.
523
- - Uses the configured printer to display start, result, and finish messages.
524
- - Captures and stores output and error buffers.
525
- - Raises an exception if tests fail and exception throwing is enabled.
460
+ If the test suite execution fails and throw_exception is True.
526
461
  """
527
-
528
462
  # Record the start time in nanoseconds
529
463
  start_time = time.time_ns()
530
464
 
@@ -569,230 +503,146 @@ class UnitTest(IUnitTest):
569
503
  suite: unittest.TestSuite
570
504
  ) -> List[unittest.TestCase]:
571
505
  """
572
- Recursively flattens a (potentially nested) unittest.TestSuite into a list of unique unittest.TestCase instances.
573
-
574
- This method traverses the provided test suite, which may contain nested suites or individual test cases,
575
- and collects all unique TestCase instances into a flat list. It ensures that each test case appears only once
576
- in the resulting list, based on a short identifier derived from the test's id. This is particularly useful
577
- for operations that require direct access to all test cases, such as filtering, counting, or custom execution.
506
+ Recursively flatten a unittest.TestSuite into a list of unique unittest.TestCase instances.
578
507
 
579
508
  Parameters
580
509
  ----------
581
510
  suite : unittest.TestSuite
582
- The test suite to flatten. This can be a single suite, a nested suite, or a suite containing test cases.
511
+ The test suite to flatten.
583
512
 
584
513
  Returns
585
514
  -------
586
- List[unittest.TestCase]
587
- A flat list containing all unique unittest.TestCase instances found within the input suite.
588
-
589
- Notes
590
- -----
591
- - The uniqueness of test cases is determined by a "short id", which is composed of the last two segments
592
- of the test's full id (typically "ClassName.methodName"). This helps avoid duplicate test cases in the result.
593
- - The method uses recursion to traverse all levels of nested suites.
594
- - Only objects with an 'id' attribute (i.e., test cases) are included in the result.
515
+ list of unittest.TestCase
516
+ Flat list of unique unittest.TestCase instances.
595
517
  """
596
518
  tests = []
597
519
  seen_ids = set()
598
520
 
599
521
  def _flatten(item):
600
- """
601
- Recursively process a TestSuite or test case, collecting unique test cases.
602
-
603
- - If the item is a TestSuite, recursively process its children.
604
- - If the item is a test case (has 'id'), generate a short id and add it if not already seen.
605
- """
606
522
  if isinstance(item, unittest.TestSuite):
607
- # Recursively flatten all sub-items in the suite
608
523
  for sub_item in item:
609
524
  _flatten(sub_item)
610
525
  elif hasattr(item, "id"):
611
- # Generate a short id for uniqueness (e.g., "ClassName.methodName")
612
526
  test_id = item.id()
613
527
  parts = test_id.split('.')
614
528
  if len(parts) >= 2:
615
529
  short_id = '.'.join(parts[-2:])
616
530
  else:
617
531
  short_id = test_id
618
- # Add the test case only if its short id has not been seen
619
532
  if short_id not in seen_ids:
620
533
  seen_ids.add(short_id)
621
534
  tests.append(item)
622
535
 
623
- # Start flattening from the root suite
624
536
  _flatten(suite)
625
-
626
- # Return a flat list of unique unittest.TestCase instances
627
537
  return tests
628
538
 
629
539
  def __runSuite(
630
540
  self
631
541
  ) -> Tuple[unittest.TestResult, io.StringIO, io.StringIO]:
632
542
  """
633
- Executes the test suite using the configured execution mode (sequential or parallel),
634
- while capturing both standard output and error streams during the test run.
635
-
636
- This method determines the execution mode (sequential or parallel) based on the current
637
- configuration and delegates the actual test execution to the appropriate internal method.
638
- It ensures that all output and error messages generated during the test run are captured
639
- in dedicated buffers for later inspection or reporting.
543
+ Execute the test suite using the configured execution mode, capturing output and error streams.
640
544
 
641
545
  Returns
642
546
  -------
643
- Tuple[unittest.TestResult, io.StringIO, io.StringIO]
644
- A tuple containing:
645
- - result: The unittest.TestResult object with detailed information about the test run,
646
- including passed, failed, errored, and skipped tests.
647
- - output_buffer: An io.StringIO object containing all captured standard output produced
648
- during the test execution.
649
- - error_buffer: An io.StringIO object containing all captured standard error output
650
- produced during the test execution.
651
-
652
- Notes
653
- -----
654
- - The execution mode is determined by the value of self.__execution_mode.
655
- - Output and error streams are always captured, regardless of execution mode.
656
- - The returned buffers can be used for further processing, logging, or displaying test output.
547
+ tuple
548
+ (result, output_buffer, error_buffer)
549
+ result : unittest.TestResult
550
+ Test result object with test outcomes.
551
+ output_buffer : io.StringIO
552
+ Captured standard output during test execution.
553
+ error_buffer : io.StringIO
554
+ Captured standard error during test execution.
657
555
  """
658
-
659
- # Create buffers to capture standard output and error during test execution
660
556
  output_buffer = io.StringIO()
661
557
  error_buffer = io.StringIO()
662
558
 
663
- # Determine execution mode and run tests accordingly
664
559
  if self.__execution_mode == ExecutionMode.PARALLEL.value:
665
- # Run tests in parallel mode
666
560
  result = self.__runTestsInParallel(
667
561
  output_buffer,
668
562
  error_buffer
669
563
  )
670
564
  else:
671
- # Run tests sequentially (default)
672
565
  result = self.__runTestsSequentially(
673
566
  output_buffer,
674
567
  error_buffer
675
568
  )
676
569
 
677
- # Return the test result along with the captured output and error buffers
678
570
  return result, output_buffer, error_buffer
679
571
 
680
572
  def __resolveFlattenedTestSuite(
681
573
  self
682
574
  ) -> unittest.TestSuite:
683
575
  """
684
- Resolves and injects dependencies for all test cases in the suite, returning a flattened TestSuite.
685
-
686
- This method processes each test case in the internal suite, inspects the test method signatures,
687
- and uses the application's dependency resolver to inject any required dependencies. It handles
688
- decorated methods, methods without dependencies, and raises errors for unresolved dependencies.
689
- The result is a new, flat unittest.TestSuite containing test cases with all dependencies resolved
690
- and injected, ready for execution.
691
-
692
- Parameters
693
- ----------
694
- None
576
+ Resolve and inject dependencies for all test cases in the suite, returning a flattened TestSuite.
695
577
 
696
578
  Returns
697
579
  -------
698
580
  unittest.TestSuite
699
- A new TestSuite containing all test cases from the original suite, with dependencies injected
700
- where required. Test cases with unresolved dependencies will cause an exception to be raised.
581
+ New TestSuite with dependencies injected where required.
701
582
 
702
583
  Raises
703
584
  ------
704
585
  OrionisTestValueError
705
- If any test method has dependencies that cannot be resolved.
706
-
707
- Notes
708
- -----
709
- - Decorated test methods are left unchanged and added as-is.
710
- - Test methods without dependencies are added directly.
711
- - Test methods with unresolved dependencies will trigger an error.
712
- - The returned TestSuite is flat and contains all processed test cases.
586
+ If any test method has unresolved dependencies.
713
587
  """
714
-
715
- # Create a new test suite to hold test cases with dependencies resolved
716
588
  flattened_suite = unittest.TestSuite()
717
589
 
718
- # Iterate through all test cases in the original (possibly nested) suite
719
590
  for test_case in self.__flattenTestSuite(self.__suite):
720
591
 
721
- # If it's a failed test, add it as-is to the flattened suite
722
592
  if test_case.__class__.__name__ == "_FailedTest":
723
593
  flattened_suite.addTest(test_case)
724
594
  continue
725
595
 
726
- # Get the test method name using reflection
727
596
  rf_instance = ReflectionInstance(test_case)
728
597
  method_name = rf_instance.getAttribute("_testMethodName")
729
598
 
730
- # If no method name is found, add the test case as-is
731
599
  if not method_name:
732
600
  flattened_suite.addTest(test_case)
733
601
  continue
734
602
 
735
- # Retrieve the actual test method object from the class
736
603
  test_method = getattr(test_case.__class__, method_name, None)
737
604
 
738
- # Check if the test method is decorated by looking for __wrapped__ attributes
739
605
  decorators = []
740
606
  if hasattr(test_method, '__wrapped__'):
741
607
  original = test_method
742
608
  while hasattr(original, '__wrapped__'):
743
- # Collect decorator names for informational purposes
744
609
  if hasattr(original, '__qualname__'):
745
610
  decorators.append(original.__qualname__)
746
611
  elif hasattr(original, '__name__'):
747
612
  decorators.append(original.__name__)
748
613
  original = original.__wrapped__
749
614
 
750
- # If decorators are present, add the test case as-is (do not inject dependencies)
751
615
  if decorators:
752
616
  flattened_suite.addTest(test_case)
753
617
  continue
754
618
 
755
- # Attempt to extract dependency information from the test method signature
756
619
  signature = rf_instance.getMethodDependencies(method_name)
757
620
 
758
- # If there are no dependencies to resolve, or unresolved dependencies exist, add as-is
759
621
  if ((not signature.resolved and not signature.unresolved) or (not signature.resolved and len(signature.unresolved) > 0)):
760
622
  flattened_suite.addTest(test_case)
761
623
  continue
762
624
 
763
- # If there are unresolved dependencies, raise an error
764
625
  if (len(signature.unresolved) > 0):
765
626
  raise OrionisTestValueError(
766
627
  f"Test method '{method_name}' in class '{test_case.__class__.__name__}' has unresolved dependencies: {signature.unresolved}. "
767
628
  "Please ensure all dependencies are correctly defined and available."
768
629
  )
769
630
 
770
- # All dependencies are resolved; prepare to inject them into the test method
771
631
  test_class = ReflectionInstance(test_case).getClass()
772
632
  original_method = getattr(test_class, method_name)
773
633
 
774
- # Resolve dependencies using the application's resolver
775
634
  params = Resolver(self.__app).resolveSignature(signature)
776
635
 
777
- # Create a wrapper function that injects resolved dependencies into the test method
778
636
  def create_test_wrapper(original_test, resolved_args: dict):
779
637
  def wrapper(self_instance):
780
638
  return original_test(self_instance, **resolved_args)
781
639
  return wrapper
782
640
 
783
- # Wrap the original test method with the dependency-injecting wrapper
784
641
  wrapped_method = create_test_wrapper(original_method, params)
785
-
786
- # Bind the wrapped method to the test case instance
787
642
  bound_method = wrapped_method.__get__(test_case, test_case.__class__)
788
-
789
- # Replace the original test method on the test case with the wrapped version
790
643
  setattr(test_case, method_name, bound_method)
791
-
792
- # Add the modified test case to the flattened suite
793
644
  flattened_suite.addTest(test_case)
794
645
 
795
- # Return the new flattened suite with all dependencies resolved and injected
796
646
  return flattened_suite
797
647
 
798
648
  def __runTestsSequentially(
@@ -801,23 +651,20 @@ class UnitTest(IUnitTest):
801
651
  error_buffer: io.StringIO
802
652
  ) -> unittest.TestResult:
803
653
  """
804
- Executes the test suite sequentially, capturing the output and error streams.
654
+ Execute the test suite sequentially, capturing output and error streams.
805
655
 
806
656
  Parameters
807
657
  ----------
808
658
  output_buffer : io.StringIO
809
- A buffer to capture the standard output during test execution.
659
+ Buffer to capture standard output.
810
660
  error_buffer : io.StringIO
811
- A buffer to capture the standard error during test execution.
661
+ Buffer to capture standard error.
812
662
 
813
663
  Returns
814
664
  -------
815
665
  unittest.TestResult
816
- The result of the test suite execution, containing information about
817
- passed, failed, and skipped tests.
666
+ Result of the test suite execution.
818
667
  """
819
-
820
- # Create a custom result class to capture detailed test results
821
668
  result = None
822
669
  for case in self.__resolveFlattenedTestSuite():
823
670
 
@@ -835,16 +682,13 @@ class UnitTest(IUnitTest):
835
682
  )
836
683
  single_result: IOrionisTestResult = runner.run(unittest.TestSuite([case]))
837
684
 
838
- # Print a concise summary for each test.
839
685
  self.__printer.unittestResult(single_result.test_results[0])
840
686
 
841
- # Merge results
842
687
  if result is None:
843
688
  result = single_result
844
689
  else:
845
690
  self.__mergeTestResults(result, single_result)
846
691
 
847
- # Return the result object containing test outcomes
848
692
  return result
849
693
 
850
694
  def __runTestsInParallel(
@@ -853,82 +697,47 @@ class UnitTest(IUnitTest):
853
697
  error_buffer: io.StringIO
854
698
  ) -> unittest.TestResult:
855
699
  """
856
- Executes all test cases in the test suite concurrently using a thread pool,
857
- aggregating their results into a single result object. Standard output and error
858
- streams are redirected to the provided buffers during execution.
859
-
860
- This method is designed to speed up test execution by running multiple test cases
861
- in parallel threads, making use of the configured maximum number of workers. Each
862
- test case is executed in isolation, and their results are merged into a combined
863
- result object. If the `fail_fast` option is enabled and a test fails, remaining
864
- tests are canceled as soon as possible.
700
+ Execute all test cases in the test suite concurrently using a thread pool, aggregating results.
865
701
 
866
702
  Parameters
867
703
  ----------
868
704
  output_buffer : io.StringIO
869
- Buffer to capture standard output produced during test execution.
705
+ Buffer to capture standard output.
870
706
  error_buffer : io.StringIO
871
- Buffer to capture standard error produced during test execution.
707
+ Buffer to capture standard error.
872
708
 
873
709
  Returns
874
710
  -------
875
711
  unittest.TestResult
876
- A combined result object (instance of the custom result class) containing
877
- the aggregated outcomes of all executed tests, including detailed information
878
- about passed, failed, errored, and skipped tests.
879
-
880
- Notes
881
- -----
882
- - Uses a custom result class to collect detailed test outcomes.
883
- - If `fail_fast` is enabled and a test fails, remaining tests are canceled.
884
- - Output and error streams are captured for the entire parallel execution.
712
+ Combined result object containing all test outcomes.
885
713
  """
886
-
887
- # Flatten the test suite to get individual test cases
888
714
  test_cases = list(self.__resolveFlattenedTestSuite())
889
-
890
- # Create a custom result instance to collect all results
891
715
  result_class = self.__customResultClass()
892
716
  combined_result = result_class(io.StringIO(), descriptions=True, verbosity=self.__verbosity)
893
717
 
894
- # Helper function to run a single test and return its result.
895
- # Each test runs in its own thread with minimal output.
896
718
  def run_single_test(test):
897
719
  runner = unittest.TextTestRunner(
898
- stream=io.StringIO(), # Use a dummy stream for individual test output
720
+ stream=io.StringIO(),
899
721
  verbosity=0,
900
722
  failfast=False,
901
723
  resultclass=result_class
902
724
  )
903
- # Run the test and return its result object
904
725
  return runner.run(unittest.TestSuite([test]))
905
726
 
906
- # Redirect stdout and stderr to the provided buffers during parallel execution
907
727
  with redirect_stdout(output_buffer), redirect_stderr(error_buffer):
908
-
909
- # Create a ThreadPoolExecutor to run tests in parallel
910
728
  with ThreadPoolExecutor(max_workers=self.__max_workers) as executor:
911
-
912
- # Submit all test cases to the executor
913
729
  futures = [executor.submit(run_single_test, test) for test in test_cases]
914
-
915
- # Process the results as they complete
916
730
  for future in as_completed(futures):
917
731
  test_result = future.result()
918
- # Merge each individual test result into the combined result
919
732
  self.__mergeTestResults(combined_result, test_result)
920
-
921
- # If fail_fast is enabled and a test failed, cancel remaining futures
922
733
  if self.__fail_fast and not combined_result.wasSuccessful():
923
734
  for f in futures:
924
735
  f.cancel()
925
736
  break
926
737
 
927
- # Print a concise summary for each test in the combined result
928
738
  for test_result in combined_result.test_results:
929
739
  self.__printer.unittestResult(test_result)
930
740
 
931
- # Return the combined result object containing all test outcomes
932
741
  return combined_result
933
742
 
934
743
  def __mergeTestResults(
@@ -939,42 +748,23 @@ class UnitTest(IUnitTest):
939
748
  """
940
749
  Merge the results of two unittest.TestResult objects into a single result.
941
750
 
942
- This method updates the `combined_result` object by aggregating the test run counts,
943
- failures, errors, skipped tests, expected failures, and unexpected successes from the
944
- `individual_result` object. It also merges any custom test results stored in the
945
- `test_results` attribute, if present, ensuring that all detailed test outcomes are
946
- included in the combined result.
947
-
948
751
  Parameters
949
752
  ----------
950
753
  combined_result : unittest.TestResult
951
- The TestResult object that will be updated to include the results from `individual_result`.
754
+ The TestResult object to update.
952
755
  individual_result : unittest.TestResult
953
- The TestResult object whose results will be merged into `combined_result`.
756
+ The TestResult object to merge in.
954
757
 
955
758
  Returns
956
759
  -------
957
760
  None
958
- This method does not return a value. It modifies `combined_result` in place.
959
-
960
- Notes
961
- -----
962
- - The method aggregates all relevant test outcome lists and counters.
963
- - If the `test_results` attribute exists (for custom result classes), it is also merged.
964
- - This is useful for combining results from parallel or sequential test executions.
965
761
  """
966
-
967
- # Aggregate the number of tests run
968
762
  combined_result.testsRun += individual_result.testsRun
969
-
970
- # Extend the lists of failures, errors, skipped, expected failures, and unexpected successes
971
763
  combined_result.failures.extend(individual_result.failures)
972
764
  combined_result.errors.extend(individual_result.errors)
973
765
  combined_result.skipped.extend(individual_result.skipped)
974
766
  combined_result.expectedFailures.extend(individual_result.expectedFailures)
975
767
  combined_result.unexpectedSuccesses.extend(individual_result.unexpectedSuccesses)
976
-
977
- # Merge custom test results if present (for enhanced result tracking)
978
768
  if hasattr(individual_result, 'test_results'):
979
769
  if not hasattr(combined_result, 'test_results'):
980
770
  combined_result.test_results = []
@@ -984,30 +774,15 @@ class UnitTest(IUnitTest):
984
774
  self
985
775
  ) -> type:
986
776
  """
987
- Creates a custom test result class for enhanced test tracking.
988
- This method dynamically generates an `OrionisTestResult` class that extends
989
- `unittest.TextTestResult`. The custom class provides advanced functionality for
990
- tracking test execution details, including timings, statuses, and error information.
777
+ Create a custom test result class for enhanced test tracking.
991
778
 
992
779
  Returns
993
780
  -------
994
781
  type
995
- A dynamically created class `OrionisTestResult` that overrides methods to handle
996
- test results, including success, failure, error, and skipped tests. The class
997
- collects detailed information about each test, such as execution time, error
998
- messages, traceback, and file path.
999
-
1000
- Notes
1001
- -----
1002
- The `OrionisTestResult` class includes the following method overrides:
1003
- The method uses the `this` reference to access the outer class's methods, such as
1004
- `_extractErrorInfo`, for extracting and formatting error information.
782
+ Dynamically created OrionisTestResult class extending unittest.TextTestResult.
1005
783
  """
1006
-
1007
- # Use `this` to refer to the outer class instance
1008
784
  this = self
1009
785
 
1010
- # Define the custom test result class
1011
786
  class OrionisTestResult(unittest.TextTestResult):
1012
787
  def __init__(self, *args, **kwargs):
1013
788
  super().__init__(*args, **kwargs)
@@ -1101,7 +876,6 @@ class UnitTest(IUnitTest):
1101
876
  )
1102
877
  )
1103
878
 
1104
- # Return the dynamically created OrionisTestResult class
1105
879
  return OrionisTestResult
1106
880
 
1107
881
  def _extractErrorInfo(
@@ -1109,61 +883,34 @@ class UnitTest(IUnitTest):
1109
883
  traceback_str: str
1110
884
  ) -> Tuple[Optional[str], Optional[str]]:
1111
885
  """
1112
- Extracts the file path and a cleaned traceback from a given traceback string.
1113
-
1114
- This method analyzes a Python traceback string to determine the file path of the Python file
1115
- where the error occurred (typically the last file in the traceback). It also removes lines
1116
- related to framework internals and irrelevant noise, such as those containing 'unittest/',
1117
- 'lib/python', or 'site-packages', to produce a more concise and relevant traceback for reporting.
886
+ Extract the file path and a cleaned traceback from a given traceback string.
1118
887
 
1119
888
  Parameters
1120
889
  ----------
1121
890
  traceback_str : str
1122
- The full traceback string to process.
891
+ Full traceback string to process.
1123
892
 
1124
893
  Returns
1125
894
  -------
1126
- Tuple[Optional[str], Optional[str]]
1127
- A tuple containing:
1128
- - file_path (Optional[str]): The path to the Python file where the error occurred, or None if not found.
1129
- - clean_tb (Optional[str]): The cleaned traceback string, with framework internals and unrelated lines removed.
1130
-
1131
- Notes
1132
- -----
1133
- The cleaned traceback starts from the first occurrence of the test file path and omits lines
1134
- that are part of the Python standard library or third-party packages, focusing on user code.
895
+ tuple
896
+ file_path : str or None
897
+ Path to the Python file where the error occurred.
898
+ clean_tb : str or None
899
+ Cleaned traceback string with framework internals removed.
1135
900
  """
1136
-
1137
- # Extract all Python file paths from the traceback string
1138
901
  file_matches = re.findall(r'File ["\'](.*?.py)["\']', traceback_str)
1139
-
1140
- # Use the last file in the traceback as the most relevant (where the error occurred)
1141
902
  file_path = file_matches[-1] if file_matches else None
1142
-
1143
- # Split the traceback into individual lines for processing
1144
903
  tb_lines = traceback_str.split('\n')
1145
904
  clean_lines = []
1146
905
  relevant_lines_started = False
1147
-
1148
- # Iterate through each line in the traceback
1149
906
  for line in tb_lines:
1150
-
1151
- # Skip lines that are part of framework internals or third-party libraries
1152
907
  if any(s in line for s in ['unittest/', 'lib/python', 'site-packages']):
1153
908
  continue
1154
-
1155
- # Start including lines once the relevant file path is found
1156
909
  if file_path and file_path in line and not relevant_lines_started:
1157
910
  relevant_lines_started = True
1158
-
1159
- # If we've started collecting relevant lines, add them to the cleaned traceback
1160
911
  if relevant_lines_started:
1161
912
  clean_lines.append(line)
1162
-
1163
- # Join the cleaned lines into a single string; if none, return the original traceback
1164
913
  clean_tb = str('\n').join(clean_lines) if clean_lines else traceback_str
1165
-
1166
- # Return the file path and cleaned traceback
1167
914
  return file_path, clean_tb
1168
915
 
1169
916
  def __generateSummary(
@@ -1172,51 +919,26 @@ class UnitTest(IUnitTest):
1172
919
  execution_time: float
1173
920
  ) -> Dict[str, Any]:
1174
921
  """
1175
- Generates a comprehensive summary of the test suite execution.
1176
-
1177
- This method processes the provided unittest.TestResult object and aggregates
1178
- statistics such as the total number of tests, counts of passed, failed, errored,
1179
- and skipped tests, as well as the overall execution time and success rate.
1180
- It also collects detailed information for each individual test, including
1181
- identifiers, class and method names, status, execution time, error messages,
1182
- tracebacks, file paths, and docstrings.
1183
-
1184
- If result persistence is enabled, the summary is saved using the configured
1185
- persistence driver (e.g., SQLite or JSON). If web reporting is enabled, a
1186
- web report is generated and linked.
922
+ Generate a summary of the test suite execution.
1187
923
 
1188
924
  Parameters
1189
925
  ----------
1190
926
  result : unittest.TestResult
1191
- The result object containing details of the test execution.
927
+ Result object containing details of the test execution.
1192
928
  execution_time : float
1193
- The total execution time of the test suite in milliseconds.
929
+ Total execution time in milliseconds.
1194
930
 
1195
931
  Returns
1196
932
  -------
1197
- Dict[str, Any]
1198
- A dictionary containing:
1199
- - total_tests (int): Total number of tests executed.
1200
- - passed (int): Number of tests that passed.
1201
- - failed (int): Number of tests that failed.
1202
- - errors (int): Number of tests that encountered errors.
1203
- - skipped (int): Number of tests that were skipped.
1204
- - total_time (float): Total execution time in milliseconds.
1205
- - success_rate (float): Percentage of tests that passed.
1206
- - test_details (List[Dict[str, Any]]): List of dictionaries with details for each test,
1207
- including id, class, method, status, execution_time, error_message, traceback,
1208
- file_path, and doc_string.
1209
- - timestamp (str): ISO-formatted timestamp of when the summary was generated.
933
+ dict
934
+ Dictionary containing test statistics and details.
1210
935
 
1211
936
  Side Effects
1212
937
  ------------
1213
- - If persistence is enabled, the summary is persisted to storage.
1214
- - If web reporting is enabled, a web report is generated.
938
+ If persistence is enabled, the summary is persisted to storage.
939
+ If web reporting is enabled, a web report is generated.
1215
940
  """
1216
-
1217
941
  test_details = []
1218
-
1219
- # Collect detailed information for each test result
1220
942
  for test_result in result.test_results:
1221
943
  rst: TestResult = test_result
1222
944
  test_details.append({
@@ -1230,13 +952,8 @@ class UnitTest(IUnitTest):
1230
952
  'file_path': rst.file_path,
1231
953
  'doc_string': rst.doc_string
1232
954
  })
1233
-
1234
- # Calculate the number of passed tests
1235
955
  passed = result.testsRun - len(result.failures) - len(result.errors) - len(result.skipped)
1236
- # Calculate the success rate as a percentage
1237
956
  success_rate = (passed / result.testsRun * 100) if result.testsRun > 0 else 100.0
1238
-
1239
- # Build the summary dictionary
1240
957
  self.__result = {
1241
958
  "total_tests": result.testsRun,
1242
959
  "passed": passed,
@@ -1248,16 +965,10 @@ class UnitTest(IUnitTest):
1248
965
  "test_details": test_details,
1249
966
  "timestamp": datetime.now().isoformat()
1250
967
  }
1251
-
1252
- # Persist the summary if persistence is enabled
1253
968
  if self.__persistent:
1254
969
  self.__handlePersistResults(self.__result)
1255
-
1256
- # Generate a web report if web reporting is enabled
1257
970
  if self.__web_report:
1258
971
  self.__handleWebReport(self.__result)
1259
-
1260
- # Return the summary dictionary
1261
972
  return self.__result
1262
973
 
1263
974
  def __handleWebReport(
@@ -1267,38 +978,20 @@ class UnitTest(IUnitTest):
1267
978
  """
1268
979
  Generate a web-based report for the provided test results summary.
1269
980
 
1270
- This method creates a web report for the test execution summary using the `TestingResultRender` class.
1271
- It determines the appropriate storage path for the report, configures persistence options based on the
1272
- current settings, and invokes the rendering process. After generating the report, it prints a link to
1273
- the web report using the configured printer.
1274
-
1275
981
  Parameters
1276
982
  ----------
1277
983
  summary : dict
1278
- The summary of test results for which the web report will be generated.
984
+ Summary of test results for web report generation.
1279
985
 
1280
986
  Returns
1281
987
  -------
1282
988
  None
1283
- This method does not return any value. The generated web report is rendered and a link to it is printed
1284
- to the console via the printer.
1285
-
1286
- Notes
1287
- -----
1288
- - The storage path for the report is determined by `self.__base_path`.
1289
- - If result persistence is enabled and the driver is set to 'sqlite', the report is marked as persistent.
1290
- - The web report is generated using the `TestingResultRender` class.
1291
- - The method prints the link to the generated web report using the printer.
1292
989
  """
1293
-
1294
- # Create the TestingResultRender instance with the storage path and summary.
1295
990
  render = TestingResultRender(
1296
991
  storage_path=self.__storage,
1297
992
  result=summary,
1298
993
  persist=self.__persistent and self.__persistent_driver == 'sqlite'
1299
994
  )
1300
-
1301
- # Render the web report and print the link using the printer.
1302
995
  self.__printer.linkWebReport(render.render())
1303
996
 
1304
997
  def __handlePersistResults(
@@ -1308,71 +1001,35 @@ class UnitTest(IUnitTest):
1308
1001
  """
1309
1002
  Persist the test results summary using the configured persistence driver.
1310
1003
 
1311
- This method saves the provided test results summary to persistent storage, based on the
1312
- current configuration. Supported drivers include SQLite (using the TestLogs class) and
1313
- JSON file output. The storage location is determined by the configured base path.
1314
-
1315
1004
  Parameters
1316
1005
  ----------
1317
1006
  summary : dict
1318
- The summary of test results to persist. This should include all relevant test execution
1319
- details, such as test counts, statuses, execution times, and individual test results.
1007
+ Test results summary to persist.
1320
1008
 
1321
1009
  Returns
1322
1010
  -------
1323
1011
  None
1324
- This method does not return any value. It performs persistence as a side effect.
1325
1012
 
1326
1013
  Raises
1327
1014
  ------
1328
1015
  OSError
1329
- If there is an error creating directories or writing files to disk.
1016
+ If there is an error creating directories or writing files.
1330
1017
  OrionisTestPersistenceError
1331
1018
  If database operations fail or any other error occurs during persistence.
1332
-
1333
- Notes
1334
- -----
1335
- - If `self.__persistent_driver` is set to 'sqlite', the summary is stored in an SQLite database
1336
- using the TestLogs class.
1337
- - If `self.__persistent_driver` is set to 'json', the summary is written to a timestamped JSON
1338
- file in the specified base path.
1339
- - The method ensures that the target directory exists before writing files.
1340
- - Any errors encountered during persistence are raised as exceptions for the caller to handle.
1341
1019
  """
1342
-
1343
1020
  try:
1344
-
1345
1021
  if self.__persistent_driver == PersistentDrivers.SQLITE.value:
1346
-
1347
- # Persist results to SQLite database using TestLogs
1348
1022
  history = TestLogs(self.__storage)
1349
-
1350
- # Insert the summary into the database
1351
1023
  history.create(summary)
1352
-
1353
1024
  elif self.__persistent_driver == PersistentDrivers.JSON.value:
1354
-
1355
- # Generate a timestamp for the log file name
1356
1025
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
1357
-
1358
- # Construct the log file path with the timestamp
1359
1026
  log_path = Path(self.__storage) / f"{timestamp}_test_results.json"
1360
-
1361
- # Ensure the directory exists
1362
1027
  log_path.parent.mkdir(parents=True, exist_ok=True)
1363
-
1364
- # Write the summary dictionary to the JSON file
1365
1028
  with open(log_path, 'w', encoding='utf-8') as log:
1366
1029
  json.dump(summary, log, indent=4)
1367
-
1368
1030
  except OSError as e:
1369
-
1370
- # Raise an OSError if there is an issue with file or directory operations
1371
1031
  raise OSError(f"Error creating directories or writing files: {str(e)}")
1372
-
1373
1032
  except Exception as e:
1374
-
1375
- # Raise a custom exception for any other issues during persistence
1376
1033
  raise OrionisTestPersistenceError(f"Error persisting test results: {str(e)}")
1377
1034
 
1378
1035
  def __filterTestsByName(
@@ -1381,29 +1038,26 @@ class UnitTest(IUnitTest):
1381
1038
  pattern: str
1382
1039
  ) -> unittest.TestSuite:
1383
1040
  """
1384
- Filters tests in a given test suite based on a specified name pattern.
1041
+ Filter tests in a test suite based on a specified name pattern.
1042
+
1385
1043
  Parameters
1386
1044
  ----------
1387
1045
  suite : unittest.TestSuite
1388
- The test suite containing the tests to filter.
1046
+ Test suite containing the tests to filter.
1389
1047
  pattern : str
1390
- A regular expression pattern to match test names.
1048
+ Regular expression pattern to match test names.
1049
+
1391
1050
  Returns
1392
1051
  -------
1393
1052
  unittest.TestSuite
1394
- A new test suite containing only the tests that match the pattern.
1053
+ New test suite containing only tests that match the pattern.
1054
+
1395
1055
  Raises
1396
1056
  ------
1397
1057
  OrionisTestValueError
1398
1058
  If the provided pattern is not a valid regular expression.
1399
- Notes
1400
- -----
1401
1059
  """
1402
-
1403
- # Initialize an empty TestSuite to hold the filtered tests
1404
1060
  filtered_suite = unittest.TestSuite()
1405
-
1406
- # Validate the pattern
1407
1061
  try:
1408
1062
  regex = re.compile(pattern)
1409
1063
  except re.error as e:
@@ -1412,13 +1066,9 @@ class UnitTest(IUnitTest):
1412
1066
  f"Regular expression compilation error: {str(e)}. "
1413
1067
  "Please check the pattern syntax and try again."
1414
1068
  )
1415
-
1416
- # Iterate through all tests in the suite and filter by the regex pattern
1417
1069
  for test in self.__flattenTestSuite(suite):
1418
1070
  if regex.search(test.id()):
1419
1071
  filtered_suite.addTest(test)
1420
-
1421
- # Return the filtered suite containing only tests that match the pattern
1422
1072
  return filtered_suite
1423
1073
 
1424
1074
  def __filterTestsByTags(
@@ -1429,45 +1079,30 @@ class UnitTest(IUnitTest):
1429
1079
  """
1430
1080
  Filter tests in a unittest TestSuite by specified tags.
1431
1081
 
1432
- Iterates through all tests in the provided TestSuite and checks for a `__tags__`
1433
- attribute either on the test method or the test case class. If any of the specified
1434
- tags match the tags associated with the test, the test is included in the filtered suite.
1435
-
1436
1082
  Parameters
1437
1083
  ----------
1438
1084
  suite : unittest.TestSuite
1439
- The original TestSuite containing all tests.
1085
+ Original TestSuite containing all tests.
1440
1086
  tags : list of str
1441
- List of tags to filter the tests by.
1087
+ Tags to filter the tests by.
1442
1088
 
1443
1089
  Returns
1444
1090
  -------
1445
1091
  unittest.TestSuite
1446
- A new TestSuite containing only the tests that match the specified tags.
1092
+ New TestSuite containing only tests with matching tags.
1447
1093
  """
1448
-
1449
- # Initialize an empty TestSuite to hold the filtered tests
1450
1094
  filtered_suite = unittest.TestSuite()
1451
1095
  tag_set = set(tags)
1452
-
1453
1096
  for test in self.__flattenTestSuite(suite):
1454
-
1455
- # Get test method if this is a TestCase instance
1456
1097
  test_method = getattr(test, test._testMethodName, None)
1457
-
1458
- # Check for tags attribute on the test method
1459
1098
  if hasattr(test_method, '__tags__'):
1460
1099
  method_tags = set(getattr(test_method, '__tags__'))
1461
1100
  if tag_set.intersection(method_tags):
1462
1101
  filtered_suite.addTest(test)
1463
-
1464
- # Also check on the test case class
1465
1102
  elif hasattr(test, '__tags__'):
1466
1103
  class_tags = set(getattr(test, '__tags__'))
1467
1104
  if tag_set.intersection(class_tags):
1468
1105
  filtered_suite.addTest(test)
1469
-
1470
- # Return the filtered suite containing only tests with matching tags
1471
1106
  return filtered_suite
1472
1107
 
1473
1108
  def getTestNames(
@@ -1478,8 +1113,8 @@ class UnitTest(IUnitTest):
1478
1113
 
1479
1114
  Returns
1480
1115
  -------
1481
- List[str]
1482
- List of test names (unique identifiers) from the test suite.
1116
+ list of str
1117
+ List of test names from the test suite.
1483
1118
  """
1484
1119
  return [test.id() for test in self.__flattenTestSuite(self.__suite)]
1485
1120
 
@@ -1487,12 +1122,12 @@ class UnitTest(IUnitTest):
1487
1122
  self
1488
1123
  ) -> int:
1489
1124
  """
1490
- Returns the total number of test cases in the test suite.
1125
+ Get the total number of test cases in the test suite.
1491
1126
 
1492
1127
  Returns
1493
1128
  -------
1494
1129
  int
1495
- The total number of individual test cases in the suite.
1130
+ Total number of individual test cases in the suite.
1496
1131
  """
1497
1132
  return len(list(self.__flattenTestSuite(self.__suite)))
1498
1133
 
@@ -1502,7 +1137,9 @@ class UnitTest(IUnitTest):
1502
1137
  """
1503
1138
  Clear all tests from the current test suite.
1504
1139
 
1505
- Resets the internal test suite to an empty `unittest.TestSuite`, removing any previously added tests.
1140
+ Returns
1141
+ -------
1142
+ None
1506
1143
  """
1507
1144
  self.__suite = unittest.TestSuite()
1508
1145
 
@@ -1510,12 +1147,12 @@ class UnitTest(IUnitTest):
1510
1147
  self
1511
1148
  ) -> dict:
1512
1149
  """
1513
- Returns the results of the executed test suite.
1150
+ Get the results of the executed test suite.
1514
1151
 
1515
1152
  Returns
1516
1153
  -------
1517
- UnitTest
1518
- The result of the executed test suite.
1154
+ dict
1155
+ Result of the executed test suite.
1519
1156
  """
1520
1157
  return self.__result
1521
1158
 
@@ -1523,12 +1160,12 @@ class UnitTest(IUnitTest):
1523
1160
  self
1524
1161
  ) -> int:
1525
1162
  """
1526
- Returns the output buffer used for capturing test results.
1527
- This method returns the internal output buffer that collects the results of the test execution.
1163
+ Get the output buffer used for capturing test results.
1164
+
1528
1165
  Returns
1529
1166
  -------
1530
1167
  int
1531
- The output buffer containing the results of the test execution.
1168
+ Output buffer containing the results of the test execution.
1532
1169
  """
1533
1170
  return self.__output_buffer
1534
1171
 
@@ -1536,8 +1173,11 @@ class UnitTest(IUnitTest):
1536
1173
  self
1537
1174
  ) -> None:
1538
1175
  """
1539
- Prints the contents of the output buffer to the console.
1540
- This method retrieves the output buffer and prints its contents using the rich console.
1176
+ Print the contents of the output buffer to the console.
1177
+
1178
+ Returns
1179
+ -------
1180
+ None
1541
1181
  """
1542
1182
  self.__printer.print(self.__output_buffer)
1543
1183
 
@@ -1545,12 +1185,12 @@ class UnitTest(IUnitTest):
1545
1185
  self
1546
1186
  ) -> int:
1547
1187
  """
1548
- Returns the error buffer used for capturing test errors.
1549
- This method returns the internal error buffer that collects any errors encountered during test execution.
1188
+ Get the error buffer used for capturing test errors.
1189
+
1550
1190
  Returns
1551
1191
  -------
1552
1192
  int
1553
- The error buffer containing the errors encountered during the test execution.
1193
+ Error buffer containing errors encountered during test execution.
1554
1194
  """
1555
1195
  return self.__error_buffer
1556
1196
 
@@ -1558,7 +1198,10 @@ class UnitTest(IUnitTest):
1558
1198
  self
1559
1199
  ) -> None:
1560
1200
  """
1561
- Prints the contents of the error buffer to the console.
1562
- This method retrieves the error buffer and prints its contents using the rich console.
1201
+ Print the contents of the error buffer to the console.
1202
+
1203
+ Returns
1204
+ -------
1205
+ None
1563
1206
  """
1564
- self.__printer.print(self.__error_buffer)
1207
+ self.__printer.print(self.__error_buffer)