Add artifact.001/tests/test_core.py

This commit is contained in:
Mika 2026-04-04 17:36:39 +00:00
parent bd710468bf
commit ab1b92ebee

View file

@ -0,0 +1,98 @@
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