Implement REQ-001~004 (dcy-001): scaffold the trex-core package (pyproject, trex_core/, tests/), port the slot pure domain into trex_core.domain.slot with import rewrites, add the EXPECTED_SLOT_FIELDS contract guard (test_contract), and port the state/service unit tests. Verification: 56 passed, ruff clean, import sweep shows zero external deps, public __all__ exposes no infra symbols, contract negative case reproduced. Align project-structure/runtime-flows baselines to the real tree. Sync SDLC tracking: REQ-001~004 → Implemented, BAT-001 → release-candidate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
37 lines
1.4 KiB
Python
37 lines
1.4 KiB
Python
"""Column-contract guard for `Slot` (dcy-001 OQ-2 / REQ-003 FR-5).
|
|
|
|
Asserts the `Slot` dataclass field set matches the declared `EXPECTED_SLOT_FIELDS`
|
|
so any field add/remove fails loudly. Names/presence only — type mapping lives in
|
|
dcy-001 부록 A / docs/data-model.md, not here.
|
|
|
|
DB-side (information_schema) drift checking is out of scope for this iteration and
|
|
is deferred to the persistence REQ (dcy-001 OQ-2).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
|
|
from trex_core.domain.slot import EXPECTED_SLOT_FIELDS, Slot
|
|
|
|
|
|
def test_slot_fields_match_expected_contract():
|
|
"""AC-2: dataclass field set == declared contract."""
|
|
actual = {f.name for f in dataclasses.fields(Slot)}
|
|
assert actual == set(EXPECTED_SLOT_FIELDS)
|
|
|
|
|
|
def test_contract_detects_added_field():
|
|
"""AC-3 negative case: an extra field on a Slot-like dataclass must be caught.
|
|
|
|
Recreates the guard against a mutated copy so the test proves the assertion
|
|
fails when fields drift, without mutating the real Slot.
|
|
"""
|
|
mutated_fields = {f.name for f in dataclasses.fields(Slot)} | {"unexpected_new_field"}
|
|
assert mutated_fields != set(EXPECTED_SLOT_FIELDS)
|
|
|
|
|
|
def test_contract_detects_removed_field():
|
|
"""AC-3 negative case: a removed field must be caught."""
|
|
reduced_fields = {f.name for f in dataclasses.fields(Slot)} - {"forced_close_at"}
|
|
assert reduced_fields != set(EXPECTED_SLOT_FIELDS)
|