Add physics model unit tests
Test dataclass creation, immutability, equality, and hashability for ThermalState and ElectricalState. Also test PhysicsEngine stub methods.
This commit is contained in:
214
tests/unit/test_physics_models.py
Normal file
214
tests/unit/test_physics_models.py
Normal file
@@ -0,0 +1,214 @@
|
||||
"""Unit tests for physics state dataclasses and engine stub."""
|
||||
|
||||
import pytest
|
||||
|
||||
from py_dvt_ate.simulation.physics.engine import PhysicsEngine
|
||||
from py_dvt_ate.simulation.physics.state import ElectricalState, ThermalState
|
||||
|
||||
|
||||
class TestThermalState:
|
||||
"""Tests for the ThermalState dataclass."""
|
||||
|
||||
def test_creation(self) -> None:
|
||||
"""Test ThermalState can be created with valid values."""
|
||||
state = ThermalState(
|
||||
chamber_temperature=25.0,
|
||||
case_temperature=30.0,
|
||||
junction_temperature=35.0,
|
||||
timestamp=0.0,
|
||||
)
|
||||
|
||||
assert state.chamber_temperature == 25.0
|
||||
assert state.case_temperature == 30.0
|
||||
assert state.junction_temperature == 35.0
|
||||
assert state.timestamp == 0.0
|
||||
|
||||
def test_immutability(self) -> None:
|
||||
"""Test ThermalState is immutable (frozen dataclass)."""
|
||||
state = ThermalState(
|
||||
chamber_temperature=25.0,
|
||||
case_temperature=30.0,
|
||||
junction_temperature=35.0,
|
||||
timestamp=0.0,
|
||||
)
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
state.chamber_temperature = 50.0 # type: ignore[misc]
|
||||
|
||||
def test_equality(self) -> None:
|
||||
"""Test ThermalState equality comparison."""
|
||||
state1 = ThermalState(
|
||||
chamber_temperature=25.0,
|
||||
case_temperature=30.0,
|
||||
junction_temperature=35.0,
|
||||
timestamp=0.0,
|
||||
)
|
||||
state2 = ThermalState(
|
||||
chamber_temperature=25.0,
|
||||
case_temperature=30.0,
|
||||
junction_temperature=35.0,
|
||||
timestamp=0.0,
|
||||
)
|
||||
|
||||
assert state1 == state2
|
||||
|
||||
def test_hashable(self) -> None:
|
||||
"""Test ThermalState is hashable (for use in sets/dicts)."""
|
||||
state = ThermalState(
|
||||
chamber_temperature=25.0,
|
||||
case_temperature=30.0,
|
||||
junction_temperature=35.0,
|
||||
timestamp=0.0,
|
||||
)
|
||||
|
||||
# Should not raise
|
||||
hash(state)
|
||||
{state} # Can be added to a set
|
||||
|
||||
|
||||
class TestElectricalState:
|
||||
"""Tests for the ElectricalState dataclass."""
|
||||
|
||||
def test_creation(self) -> None:
|
||||
"""Test ElectricalState can be created with valid values."""
|
||||
state = ElectricalState(
|
||||
input_voltage=5.0,
|
||||
output_voltage=3.3,
|
||||
load_current=0.1,
|
||||
quiescent_current=50e-6,
|
||||
power_dissipation=0.17,
|
||||
)
|
||||
|
||||
assert state.input_voltage == 5.0
|
||||
assert state.output_voltage == 3.3
|
||||
assert state.load_current == 0.1
|
||||
assert state.quiescent_current == 50e-6
|
||||
assert state.power_dissipation == 0.17
|
||||
|
||||
def test_immutability(self) -> None:
|
||||
"""Test ElectricalState is immutable (frozen dataclass)."""
|
||||
state = ElectricalState(
|
||||
input_voltage=5.0,
|
||||
output_voltage=3.3,
|
||||
load_current=0.1,
|
||||
quiescent_current=50e-6,
|
||||
power_dissipation=0.17,
|
||||
)
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
state.output_voltage = 1.8 # type: ignore[misc]
|
||||
|
||||
def test_equality(self) -> None:
|
||||
"""Test ElectricalState equality comparison."""
|
||||
state1 = ElectricalState(
|
||||
input_voltage=5.0,
|
||||
output_voltage=3.3,
|
||||
load_current=0.1,
|
||||
quiescent_current=50e-6,
|
||||
power_dissipation=0.17,
|
||||
)
|
||||
state2 = ElectricalState(
|
||||
input_voltage=5.0,
|
||||
output_voltage=3.3,
|
||||
load_current=0.1,
|
||||
quiescent_current=50e-6,
|
||||
power_dissipation=0.17,
|
||||
)
|
||||
|
||||
assert state1 == state2
|
||||
|
||||
|
||||
class TestPhysicsEngineStub:
|
||||
"""Tests for the PhysicsEngine stub."""
|
||||
|
||||
def test_creation_default(self) -> None:
|
||||
"""Test PhysicsEngine can be created with defaults."""
|
||||
engine = PhysicsEngine()
|
||||
|
||||
assert engine.dt == pytest.approx(0.01) # 100Hz -> 10ms
|
||||
|
||||
def test_creation_custom_rate(self) -> None:
|
||||
"""Test PhysicsEngine with custom update rate."""
|
||||
engine = PhysicsEngine(update_rate_hz=50.0)
|
||||
|
||||
assert engine.dt == pytest.approx(0.02) # 50Hz -> 20ms
|
||||
|
||||
def test_step_advances_time(self) -> None:
|
||||
"""Test step() advances simulation time."""
|
||||
engine = PhysicsEngine(update_rate_hz=100.0)
|
||||
|
||||
assert engine.simulation_time == pytest.approx(0.0)
|
||||
engine.step()
|
||||
assert engine.simulation_time == pytest.approx(0.01)
|
||||
engine.step()
|
||||
assert engine.simulation_time == pytest.approx(0.02)
|
||||
|
||||
def test_get_thermal_state(self) -> None:
|
||||
"""Test get_thermal_state returns ThermalState."""
|
||||
engine = PhysicsEngine()
|
||||
|
||||
state = engine.get_thermal_state()
|
||||
|
||||
assert isinstance(state, ThermalState)
|
||||
assert state.chamber_temperature == 25.0 # Default
|
||||
assert state.timestamp == 0.0
|
||||
|
||||
def test_get_electrical_state(self) -> None:
|
||||
"""Test get_electrical_state returns ElectricalState."""
|
||||
engine = PhysicsEngine()
|
||||
|
||||
state = engine.get_electrical_state()
|
||||
|
||||
assert isinstance(state, ElectricalState)
|
||||
|
||||
def test_set_chamber_setpoint(self) -> None:
|
||||
"""Test set_chamber_setpoint updates setpoint."""
|
||||
engine = PhysicsEngine()
|
||||
|
||||
engine.set_chamber_setpoint(85.0)
|
||||
|
||||
# Stub doesn't update chamber temp, just stores setpoint
|
||||
state = engine.get_thermal_state()
|
||||
assert state.chamber_temperature == 25.0 # Still at initial
|
||||
|
||||
def test_set_input_voltage(self) -> None:
|
||||
"""Test set_input_voltage updates voltage."""
|
||||
engine = PhysicsEngine()
|
||||
|
||||
engine.set_input_voltage(5.0)
|
||||
|
||||
state = engine.get_electrical_state()
|
||||
assert state.input_voltage == 5.0
|
||||
|
||||
def test_set_load_current(self) -> None:
|
||||
"""Test set_load_current updates current."""
|
||||
engine = PhysicsEngine()
|
||||
engine.set_output_enabled(True)
|
||||
|
||||
engine.set_load_current(0.1)
|
||||
|
||||
state = engine.get_electrical_state()
|
||||
assert state.load_current == 0.1
|
||||
|
||||
def test_output_disabled_by_default(self) -> None:
|
||||
"""Test output is disabled by default."""
|
||||
engine = PhysicsEngine()
|
||||
|
||||
assert not engine.is_output_enabled
|
||||
|
||||
def test_enable_output(self) -> None:
|
||||
"""Test set_output_enabled enables output."""
|
||||
engine = PhysicsEngine()
|
||||
|
||||
engine.set_output_enabled(True)
|
||||
|
||||
assert engine.is_output_enabled
|
||||
|
||||
def test_load_current_zero_when_disabled(self) -> None:
|
||||
"""Test load current is zero when output disabled."""
|
||||
engine = PhysicsEngine()
|
||||
engine.set_load_current(0.1)
|
||||
|
||||
state = engine.get_electrical_state()
|
||||
|
||||
assert state.load_current == 0.0 # Disabled, so zero
|
||||
Reference in New Issue
Block a user