Coverage for src / ocarina / dsl / testing / oc_test.py: 21.43%

22 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-06-04 16:22 +0200

1"""Test encapsulation. 

2 

3Lifecycle: Definition → Registration → Spawn 

4Driver is inferred. 

5""" 

6 

7from typing import TYPE_CHECKING, Any, final 

8 

9from ocarina.custom_types.test_runner import TestRunner 

10 

11if TYPE_CHECKING: 

12 from collections.abc import Sequence 

13 

14 from ocarina.custom_types.oc_test import ( 

15 TestName, 

16 TestScenario, 

17 TestScenarioFragment, 

18 ) 

19 from ocarina.dsl.testing_with_railway.chain_actions import ChainRunner 

20 from ocarina.ports.ilogger import ILogger 

21 

22 

23@final 

24class Test[Driver]: 

25 """Single test case: metadata + scenario factory. 

26 

27 spawn() injects runtime dependencies (driver, logger) into the scenario. 

28 """ 

29 

30 def __init__( # noqa: PLR0913 

31 self, 

32 *, 

33 name: TestName, 

34 test_id: str | None = None, 

35 test_scenario: TestScenario[Driver], 

36 pre_test_scenarios_fragments: Sequence[TestScenarioFragment[Driver]] 

37 | None = None, 

38 post_test_scenarios_fragments: Sequence[TestScenarioFragment[Driver]] 

39 | None = None, 

40 skipped: bool = False, 

41 ) -> None: 

42 """Test builder. 

43 

44 Args: 

45 name: Human-readable label used in logs and reports. 

46 test_id: Stable unique identifier. Defaults to name. 

47 test_scenario: Scenario factory (Driver, ILogger) → chains. 

48 pre_test_scenarios_fragments: Setup scenarios fragments run before scenario. 

49 post_test_scenarios_fragments: Setup scenarios fragments run after scenario. 

50 skipped: If True, test is registered but not executed. 

51 

52 """ 

53 if test_id is None: 

54 test_id = name 

55 

56 self.name = name 

57 self.test_id = test_id 

58 self._test_scenario = test_scenario 

59 self._pre_test_scenarios_fragments = pre_test_scenarios_fragments or [] 

60 self._post_test_scenarios_fragments = post_test_scenarios_fragments or [] 

61 self._skipped = skipped 

62 

63 def spawn(self, driver: Driver, logger: ILogger) -> TestRunner[Driver]: 

64 """Instantiate chains with (driver, logger). Returns TestRunner.""" 

65 chain_runners: list[ChainRunner[Any]] = [] 

66 

67 for pre_chain in self._pre_test_scenarios_fragments: 

68 chain_runners.extend(pre_chain(driver, logger)) 

69 

70 scenario = self._test_scenario(driver, logger) 

71 chain_runners.extend(scenario.test_chain) 

72 

73 for post_chain in self._post_test_scenarios_fragments: 

74 chain_runners.extend(post_chain(driver, logger)) 

75 

76 return TestRunner( 

77 chain_runners=chain_runners, 

78 skipped=self._skipped, 

79 setup=scenario.setup, 

80 teardown=scenario.teardown, 

81 watchers=scenario.watchers, 

82 )