diff --git a/temperature_logger/tests/test_core.py b/temperature_logger/tests/test_core.py new file mode 100644 index 0000000..56564e7 --- /dev/null +++ b/temperature_logger/tests/test_core.py @@ -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) +