Add artifact.001/tests/test_core.py
This commit is contained in:
parent
bd710468bf
commit
ab1b92ebee
1 changed files with 98 additions and 0 deletions
98
artifact.001/tests/test_core.py
Normal file
98
artifact.001/tests/test_core.py
Normal 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
|
||||||
Loading…
Reference in a new issue