diff --git a/turret_python_interface/mock_interface.py b/turret_python_interface/mock_interface.py new file mode 100644 index 0000000..14f7050 --- /dev/null +++ b/turret_python_interface/mock_interface.py @@ -0,0 +1,58 @@ +""" +Provides a mock Interface class for testing purposes, to decouple tests from requiring +the entire turret hardware stack. +""" + +from math import tau, pi, sin +from pathlib import Path +from types import TracebackType +from typing import Optional, Type + +from .interface import Interface +from .datamodel.telemetry_packet import TelemetryPacket + + +class MockInterface(Interface): + # noinspection PyMissingConstructor + def __init__( + self, + *, + serial_path: Path = Path("/") / "dev" / "ttyS0", + baud: int = 115200, + timeout=30, + ): + # NOTE: we intentionally don't call the constructor of the superclass as it would + # init a serial connection; which is an implementation detail + # and we cannot mock it effectively. + # NOTE: the internal data members of this type are not mocked, as they are implementation + # details. mocking them is unnecessary. + self.t = 0 + ... + + @property + def state(self) -> float: + # basically, we are reproducing a sine wave. + # Every time the state is observed, time progresses. + + # preserve the current time + t = self.t + # increment t for the next tick + self.t += pi / 4 + if self.t >= tau: + self.t = 0 + + return sin(t) + + def __enter__(self) -> Interface: + ... + + def __exit__( + self, + __exc_type: Optional[Type[BaseException]], + __exc_value: Optional[BaseException], + __traceback: Optional[TracebackType], + ) -> Optional[bool]: + ... + + def get_telemetry(self) -> TelemetryPacket: + return TelemetryPacket(turret_pos=self.state)