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
« prev ^ index » next coverage.py v7.13.5, created at 2026-06-04 16:22 +0200
1"""Test encapsulation.
3Lifecycle: Definition → Registration → Spawn
4Driver is inferred.
5"""
7from typing import TYPE_CHECKING, Any, final
9from ocarina.custom_types.test_runner import TestRunner
11if TYPE_CHECKING:
12 from collections.abc import Sequence
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
23@final
24class Test[Driver]:
25 """Single test case: metadata + scenario factory.
27 spawn() injects runtime dependencies (driver, logger) into the scenario.
28 """
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.
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.
52 """
53 if test_id is None:
54 test_id = name
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
63 def spawn(self, driver: Driver, logger: ILogger) -> TestRunner[Driver]:
64 """Instantiate chains with (driver, logger). Returns TestRunner."""
65 chain_runners: list[ChainRunner[Any]] = []
67 for pre_chain in self._pre_test_scenarios_fragments:
68 chain_runners.extend(pre_chain(driver, logger))
70 scenario = self._test_scenario(driver, logger)
71 chain_runners.extend(scenario.test_chain)
73 for post_chain in self._post_test_scenarios_fragments:
74 chain_runners.extend(post_chain(driver, logger))
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 )