Add temperature_logger/tests/test_core.py
This commit is contained in:
parent
04acc1bd3d
commit
a9b2132746
1 changed files with 107 additions and 0 deletions
107
temperature_logger/tests/test_core.py
Normal file
107
temperature_logger/tests/test_core.py
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
import json
|
||||||
|
import tempfile
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
from unittest import mock
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import temperature_logger.core as core
|
||||||
|
|
||||||
|
|
||||||
|
def fake_serial_readline_factory(seq):
|
||||||
|
"""Erzeugt eine Fake-Readline-Funktion, die Werte aus seq zurückgibt."""
|
||||||
|
it = iter(seq)
|
||||||
|
|
||||||
|
def fake_readline():
|
||||||
|
try:
|
||||||
|
val = next(it)
|
||||||
|
except StopIteration:
|
||||||
|
time.sleep(0.1)
|
||||||
|
val = b''
|
||||||
|
return f"{val}\n".encode()
|
||||||
|
|
||||||
|
return fake_readline
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_serial(monkeypatch):
|
||||||
|
class FakeSerial:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.port = args[0]
|
||||||
|
self.is_open = True
|
||||||
|
self.readline = fake_serial_readline_factory([22.3, 23.0, 21.7])
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.is_open = False
|
||||||
|
|
||||||
|
monkeypatch.setattr(core, 'serial', mock.Mock(Serial=FakeSerial))
|
||||||
|
return FakeSerial
|
||||||
|
|
||||||
|
|
||||||
|
def test_log_temperature_data_creates_json(tmp_path, mock_serial, monkeypatch):
|
||||||
|
output_file = tmp_path / 'temperature_log.json'
|
||||||
|
monkeypatch.setattr(core, 'OUTPUT_PATH', output_file)
|
||||||
|
|
||||||
|
# Reduce logging duration by limiting loop count via mock
|
||||||
|
monkeypatch.setattr(core.time, 'sleep', lambda x: None)
|
||||||
|
|
||||||
|
# Run function under test
|
||||||
|
result = core.log_temperature_data(sensor='/dev/ttyFAKE', interval=0.01)
|
||||||
|
|
||||||
|
assert result is None
|
||||||
|
assert output_file.exists(), 'Output JSON file sollte existieren.'
|
||||||
|
|
||||||
|
with output_file.open('r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
assert isinstance(data, list)
|
||||||
|
assert len(data) >= 1, 'Es sollten mindestens ein Messwert geloggt werden.'
|
||||||
|
|
||||||
|
sample = data[0]
|
||||||
|
assert all(k in sample for k in ('timestamp', 'temperature', 'location'))
|
||||||
|
assert isinstance(sample['temperature'], (float, int))
|
||||||
|
assert isinstance(sample['timestamp'], str)
|
||||||
|
assert isinstance(sample['location'], str)
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_sensor_port(monkeypatch):
|
||||||
|
class FakeSerialError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def raise_serial_error(*args, **kwargs):
|
||||||
|
raise FakeSerialError('Invalid port')
|
||||||
|
|
||||||
|
monkeypatch.setattr(core, 'serial', mock.Mock(Serial=raise_serial_error))
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
core.log_temperature_data(sensor='INVALID', interval=0.1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_interval_validation(monkeypatch, tmp_path):
|
||||||
|
monkeypatch.setattr(core, 'OUTPUT_PATH', tmp_path / 'temp.json')
|
||||||
|
monkeypatch.setattr(core, 'serial', mock.Mock())
|
||||||
|
|
||||||
|
with pytest.raises((AssertionError, ValueError, TypeError)):
|
||||||
|
core.log_temperature_data(sensor='/dev/ttyFake', interval=-1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_json_structure_fields(monkeypatch, tmp_path, mock_serial):
|
||||||
|
output_file = tmp_path / 'temperature_log.json'
|
||||||
|
monkeypatch.setattr(core, 'OUTPUT_PATH', output_file)
|
||||||
|
monkeypatch.setattr(core.time, 'sleep', lambda x: None)
|
||||||
|
|
||||||
|
core.log_temperature_data(sensor='/dev/ttyFAKE', interval=0.01)
|
||||||
|
|
||||||
|
with output_file.open('r', encoding='utf-8') as f:
|
||||||
|
logs = json.load(f)
|
||||||
|
|
||||||
|
for entry in logs:
|
||||||
|
assert 'timestamp' in entry
|
||||||
|
assert 'temperature' in entry
|
||||||
|
assert 'location' in entry
|
||||||
|
# Dataintegrity check
|
||||||
|
assert isinstance(entry['temperature'], float)
|
||||||
|
assert isinstance(entry['timestamp'], str)
|
||||||
|
assert isinstance(entry['location'], str)
|
||||||
|
|
||||||
Loading…
Reference in a new issue