98 lines
No EOL
3.4 KiB
Python
98 lines
No EOL
3.4 KiB
Python
import json
|
||
import os
|
||
import tempfile
|
||
from datetime import datetime
|
||
from pathlib import Path
|
||
import pytest
|
||
|
||
# Wir importieren aus dem Projektpaket artifact_001.core
|
||
import importlib.util
|
||
|
||
def load_log_measurement():
|
||
# Dynamisches Laden der log_measurement Funktion aus src/artifact_001/core.py
|
||
# Dies ist CI-safe, da ansonsten ImportError entstehen könnte, falls sys.path anders konfiguriert ist.
|
||
pkg_path = Path(__file__).parent.parent / 'src' / 'artifact_001' / 'core.py'
|
||
spec = importlib.util.spec_from_file_location('artifact_001.core', pkg_path)
|
||
mod = importlib.util.module_from_spec(spec)
|
||
spec.loader.exec_module(mod)
|
||
return mod.log_measurement
|
||
|
||
@pytest.fixture
|
||
def sample_measurement():
|
||
return {
|
||
'timestamp': datetime(2024, 6, 10, 7, 5, 0),
|
||
'measured_p': 0.134,
|
||
'freeze_ok': False,
|
||
'setup_fingerprint': 'setupA',
|
||
'policy_hash': 'ph123'
|
||
}
|
||
|
||
@pytest.fixture(autouse=True)
|
||
def temp_output_dir(monkeypatch, tmp_path):
|
||
output_path = tmp_path / 'measurement_log.json'
|
||
os.makedirs(tmp_path, exist_ok=True)
|
||
# Patch the output path in core.py to use this temp file.
|
||
monkeypatch.setenv('AUX3_OUTPUT_PATH', str(output_path))
|
||
yield output_path
|
||
|
||
@pytest.mark.parametrize('invalid_case', [
|
||
{'measured_p': 'no_float'}, # falscher Typ
|
||
{'freeze_ok': 'not_bool'}, # falscher Typ
|
||
{'timestamp': 'invalid-date'}, # ungültiges Datum
|
||
])
|
||
def test_log_measurement_invalid_input(invalid_case, sample_measurement, temp_output_dir):
|
||
log_measurement = load_log_measurement()
|
||
bad_input = sample_measurement.copy()
|
||
bad_input.update(invalid_case)
|
||
with pytest.raises(Exception):
|
||
log_measurement(**bad_input)
|
||
|
||
|
||
def test_log_measurement_creates_valid_json(sample_measurement, temp_output_dir):
|
||
log_measurement = load_log_measurement()
|
||
fpath = temp_output_dir
|
||
# Sicherstellen, dass Datei leer ist
|
||
if fpath.exists():
|
||
fpath.unlink()
|
||
|
||
# Aufruf der Funktion
|
||
log_measurement(**sample_measurement)
|
||
|
||
assert fpath.exists(), 'JSON-Logdatei sollte erstellt werden.'
|
||
|
||
content = json.loads(fpath.read_text(encoding='utf-8'))
|
||
|
||
assert isinstance(content, list), 'JSON-Datei sollte eine Liste enthalten.'
|
||
assert len(content) == 1, 'Ein Messpunkt sollte geloggt sein.'
|
||
entry = content[0]
|
||
|
||
# Strukturprüfung basierend auf MeasurementLog data_model
|
||
expected_fields = ['timestamp', 'measured_p', 'freeze_ok', 'setup_fingerprint', 'policy_hash']
|
||
for field in expected_fields:
|
||
assert field in entry, f'Feld {field} sollte vorhanden sein.'
|
||
|
||
# Typ-Assertions (Nominal Case)
|
||
datetime.fromisoformat(entry['timestamp'])
|
||
assert isinstance(entry['measured_p'], float)
|
||
assert isinstance(entry['freeze_ok'], bool)
|
||
assert isinstance(entry['setup_fingerprint'], str)
|
||
assert isinstance(entry['policy_hash'], str)
|
||
|
||
|
||
def test_log_measurement_appends_to_existing(temp_output_dir, sample_measurement):
|
||
log_measurement = load_log_measurement()
|
||
fpath = temp_output_dir
|
||
|
||
# Erstes Logging
|
||
log_measurement(**sample_measurement)
|
||
|
||
# Zweites Logging – sollte anhängen
|
||
modified = sample_measurement.copy()
|
||
modified['measured_p'] = 0.555
|
||
log_measurement(**modified)
|
||
|
||
content = json.loads(fpath.read_text(encoding='utf-8'))
|
||
assert len(content) == 2, 'Zwei Messpunkte sollten geloggt sein.'
|
||
|
||
# Letzter Eintrag überprüfen
|
||
assert pytest.approx(content[-1]['measured_p'], 1e-6) == 0.555 |