Skip to content

Commit 40ca938

Browse files
committed
split capture fixture
1 parent 3e8e024 commit 40ca938

File tree

3 files changed

+42
-34
lines changed

3 files changed

+42
-34
lines changed

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ minversion = "6.0"
170170
addopts = "--ff"
171171
pythonpath = ["src"]
172172
testpaths = ["tests"]
173+
required_plugins = ["mock-serial", "logot"]
173174
logot_capturer = "logot.loguru.LoguruCapturer"
174175
filterwarnings = [
175176
# DeprecationWarning from pypms are errors
@@ -224,7 +225,7 @@ sqlite_cache = true
224225
exclude = "site"
225226

226227
[[tool.mypy.overrides]]
227-
module = ["influxdb"]
228+
module = ["influxdb", "mock_serial"]
228229
ignore_missing_imports = true
229230

230231
[[tool.mypy.overrides]]

tests/conftest.py

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,11 @@ def __str__(self) -> str:
7676
return self.name
7777

7878
@property
79-
def sensor(self) -> Sensor:
80-
return Sensor[self.name]
81-
82-
@property
83-
def data(self) -> Iterator[bytes]:
79+
def raw_message(self) -> Iterator[bytes]:
8480
return (msg.data for msg in self.value)
8581

8682
@property
87-
def time(self) -> Iterator[int]:
83+
def message_timestamp(self) -> Iterator[int]:
8884
return (msg.time for msg in self.value)
8985

9086
@property
@@ -93,7 +89,7 @@ def tzinfo(self) -> tzinfo:
9389

9490
@property
9591
def obs(self) -> Iterator[ObsData]:
96-
sensor = self.sensor
92+
sensor = Sensor[self.name]
9793
return (sensor.decode(msg.data, time=msg.time) for msg in self.value)
9894

9995
@property
@@ -148,13 +144,35 @@ def debug_messages(self, command: str) -> Iterator[str]:
148144

149145

150146
@pytest.fixture(params=CapturedData, ids=str)
151-
def capture_data(request: pytest.FixtureRequest) -> CapturedData:
147+
def captured_data(request: pytest.FixtureRequest) -> CapturedData:
152148
"""captured data from real sensors"""
153149
return request.param
154150

155151

156-
@pytest.fixture()
157-
def capture(monkeypatch: pytest.MonkeyPatch, capture_data: CapturedData) -> CapturedData:
152+
@pytest.fixture
153+
def replay_time(monkeypatch: pytest.MonkeyPatch, captured_data: CapturedData) -> None:
154+
"""mock datetime at `pms.core.sensor`, `pms.sensors.base` and `pms.sensors.mqtt`"""
155+
captured_data = captured_data
156+
157+
class mock_datetime(datetime):
158+
message_timestamp = captured_data.message_timestamp
159+
160+
@classmethod
161+
def fromtimestamp(cls, t, tz=captured_data.tzinfo):
162+
assert tz == captured_data.tzinfo
163+
return datetime.fromtimestamp(t, tz)
164+
165+
@classmethod
166+
def now(cls, tz=captured_data.tzinfo):
167+
return cls.fromtimestamp(next(cls.message_timestamp), tz)
168+
169+
monkeypatch.setattr("pms.core.sensor.datetime", mock_datetime)
170+
monkeypatch.setattr("pms.sensors.base.datetime", mock_datetime)
171+
monkeypatch.setattr("pms.extra.mqtt.datetime", mock_datetime)
172+
173+
174+
@pytest.fixture
175+
def replay_serial(monkeypatch: pytest.MonkeyPatch, captured_data: CapturedData) -> None:
158176
"""mock pms.core.reader.Serial and some pms.core.reader.SensorReader internals"""
159177

160178
class MockSerial:
@@ -172,43 +190,32 @@ def close(self):
172190
def reset_input_buffer(self):
173191
pass
174192

175-
captured_data = capture_data.data
193+
raw_message = captured_data.raw_message
176194

177195
def mock_reader__cmd(self, command: str) -> bytes:
178196
"""bypass serial.write/read"""
179197
logger.debug(f"mock write/read: {command}")
180198
# nonlocal data
181199
if command == "passive_read":
182-
return next(captured_data)
200+
return next(raw_message)
183201
if command in {"wake", "passive_mode"}:
184202
return b"." * self.sensor.command(command).answer_length
185203

186204
return b""
187205

188-
def mock_reader__pre_heat(self) -> int:
189-
return 0
190-
191206
def mock_sensor_check(self, buffer: bytes, command: str) -> bool:
192207
"""don't check if message matches sensor"""
193208
return True
194209

195-
class mock_datetime(datetime):
196-
captured_time = capture_data.time
197-
198-
@classmethod
199-
def fromtimestamp(cls, t, tz=capture_data.tzinfo):
200-
assert tz == capture_data.tzinfo
201-
return datetime.fromtimestamp(t, tz)
202-
203-
@classmethod
204-
def now(cls, tz=capture_data.tzinfo):
205-
return cls.fromtimestamp(next(cls.captured_time), tz)
206-
207210
monkeypatch.setattr("pms.core.reader.Serial", MockSerial)
208211
monkeypatch.setattr("pms.core.reader.SensorReader._cmd", mock_reader__cmd)
209-
monkeypatch.setattr("pms.core.reader.SensorReader._pre_heat", mock_reader__pre_heat)
210212
monkeypatch.setattr("pms.core.reader.Sensor.check", mock_sensor_check)
211-
monkeypatch.setattr("pms.core.sensor.datetime", mock_datetime)
212-
monkeypatch.setattr("pms.sensors.base.datetime", mock_datetime)
213+
sensor = Sensor[captured_data.name]
214+
if hasattr(sensor.value, "PREHEAT"):
215+
monkeypatch.setattr(sensor.value, "PREHEAT", 0)
216+
213217

214-
return capture_data
218+
@pytest.fixture()
219+
def capture(captured_data: CapturedData, replay_time, replay_serial) -> CapturedData:
220+
"""replay onservations from captured data"""
221+
return captured_data

tests/extra/test_cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def pub(data: dict[str, int | str]) -> None:
2626

2727

2828
@pytest.fixture()
29-
def mock_mqtt_subscribe(capture_data, monkeypatch: pytest.MonkeyPatch):
29+
def mock_mqtt_subscribe(captured_data, monkeypatch: pytest.MonkeyPatch, replay_time):
3030
"""mock ms.extra.mqtt.subscribe"""
3131
from pms.extra.mqtt import Data
3232

@@ -39,7 +39,7 @@ def subscribe(
3939
*,
4040
on_sensordata: Callable[[Data], None],
4141
) -> None:
42-
for obs in capture_data.obs:
42+
for obs in captured_data.obs:
4343
for field in fields(obs):
4444
if not field.metadata:
4545
continue

0 commit comments

Comments
 (0)