Files
dxfmakros/tests/test_omniflo_strecke.py
T

184 lines
6.8 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
test_omniflo_strecke.py - Validiert den Omniflo-Streckenzug.
Testfall (tests/testdata/omniflo_strecke_tests.json), aktuelles Datenmodell:
3 Elemente: 2x bogen (echte Omniflo-Boegen), 1x weiche.
Prueft (ohne BricsCAD):
1. Struktur: 3 Elemente in der richtigen Gruppen-/Typ-Verteilung, seq lueckenlos
2. Katalog: die Bogen-SivasNummern (gruppe "bogen") existieren in
data/json/omniflo_boegen.json mit passendem Radius/Kurvenwinkel; die
Weichen-SivasNummer in data/json/omniflo_weichen.json
Hinweis: Boegen/Weichen tragen im aktuellen Testdaten-Modell KEINE Endpunkte
(x_ende/y_ende = null) und keine Mittelpunkte - die frueheren Halbkreis-/
Verkettungs-Tests (drehung_ende, x_mitte, kurve_180, 12 Elemente) bezogen sich
auf ein anderes, nicht mehr vorhandenes Modell und wurden entfernt. Die
Aluprofil-Geraden (AP60/AP110/APG110) wurden samt Menue und Befehlen entfernt.
Optional (nach BricsCAD-Lauf c:TEST_OMNIFLO_STRECKE):
3. Integrationstest gegen tests/output/omniflo_strecke_results.json
"""
import json
import os
import pytest
_TOL = 0.05 # mm / Grad Toleranz (JSON ist auf 2 Nachkommastellen gerundet)
# ---------------------------------------------------------------------------
# Hilfsfunktionen
# ---------------------------------------------------------------------------
def _data_dir():
base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
return os.path.join(base, "data")
def _testdata_dir():
return os.getenv("DXFM_TESTDATA",
os.path.join(os.path.dirname(os.path.abspath(__file__)), "testdata"))
def _output_dir():
return os.getenv("DXFM_TESTOUT",
os.path.join(os.path.dirname(os.path.abspath(__file__)), "output"))
def _load_json(path):
try:
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
except UnicodeDecodeError:
with open(path, "r", encoding="cp1252") as f:
return json.load(f)
def _load_strecke():
return _load_json(os.path.join(_testdata_dir(), "omniflo_strecke_tests.json"))
def _katalog_lookup(dateiname):
"""SivasNr -> Katalog-Eintrag aus data/json/<dateiname>. Der Schluessel
heisst je nach Katalog 'Sivasnr' oder 'SivasNummer'."""
eintraege = _load_json(os.path.join(_data_dir(), "json", dateiname))
lookup = {}
for e in eintraege:
key = e.get("Sivasnr") or e.get("SivasNummer") or e.get("sivasnr")
if key is not None:
lookup[str(key)] = e
return lookup
# ---------------------------------------------------------------------------
# Fixtures
# ---------------------------------------------------------------------------
@pytest.fixture
def strecke():
return _load_strecke()
@pytest.fixture
def boegen_lookup():
return _katalog_lookup("omniflo_boegen.json")
@pytest.fixture
def weichen_lookup():
return _katalog_lookup("omniflo_weichen.json")
# ---------------------------------------------------------------------------
# 1. Struktur des Streckenzugs
# ---------------------------------------------------------------------------
class TestStreckeStruktur:
def test_gesamtzahl(self, strecke):
"""2 Boegen + 1 Weiche = 3 Elemente."""
assert len(strecke) == 3, f"Erwartet 3 Elemente, erhalten {len(strecke)}"
def test_seq_lueckenlos(self, strecke):
"""seq muss lueckenlos bei 1 beginnend aufsteigen."""
for i, el in enumerate(strecke):
assert el["seq"] == i + 1, f"Element {i}: seq={el['seq']}, erwartet {i + 1}"
def test_gruppen_verteilung(self, strecke):
"""Erwartete Gruppen-Verteilung: 2x bogen, 1x weiche."""
from collections import Counter
ist = Counter(el["gruppe"] for el in strecke)
erwartet = {"bogen": 2, "weiche": 1}
assert dict(ist) == erwartet, (
f"Gruppen-Verteilung abweichend: Ist {dict(ist)}, Soll {erwartet}")
def test_typen(self, strecke):
"""bogen/weiche -> type 'bogen'."""
for el in strecke:
assert el["type"] == "bogen", (
f"seq {el['seq']}: type={el['type']}, erwartet bogen")
# ---------------------------------------------------------------------------
# 2. Katalog-Abgleich der Boegen / Weichen
# ---------------------------------------------------------------------------
class TestStreckeKatalog:
def test_bogen_sivasnr_im_katalog(self, strecke, boegen_lookup):
"""Echte Boegen (gruppe 'bogen') muessen im Boegen-Katalog stehen."""
boegen = [el for el in strecke if el["gruppe"] == "bogen"]
assert boegen, "Keine Boegen in der Strecke"
for el in boegen:
assert str(el["sivasnr"]) in boegen_lookup, (
f"SivasNr {el['sivasnr']} nicht in omniflo_boegen.json")
def test_bogen_radius_und_winkel(self, strecke, boegen_lookup):
for el in strecke:
if el["gruppe"] != "bogen":
continue
eintrag = boegen_lookup[str(el["sivasnr"])]
assert float(eintrag["Radius"]) == pytest.approx(el["radius"], abs=_TOL), (
f"{el['sivasnr']}: Radius Katalog={eintrag['Radius']}, Test={el['radius']}")
assert float(eintrag["KurvenWinkel"]) == pytest.approx(el["winkel"], abs=_TOL), (
f"{el['sivasnr']}: Winkel Katalog={eintrag['KurvenWinkel']}, Test={el['winkel']}")
def test_weiche_sivasnr_im_katalog(self, strecke, weichen_lookup):
"""Die Weiche (gruppe 'weiche') muss im Weichen-Katalog stehen."""
weichen = [el for el in strecke if el["gruppe"] == "weiche"]
for el in weichen:
assert str(el["sivasnr"]) in weichen_lookup, (
f"Weichen-SivasNr {el['sivasnr']} nicht in omniflo_weichen.json")
# ---------------------------------------------------------------------------
# 3. Integrationstest gegen BricsCAD-Ergebnis (optional)
# ---------------------------------------------------------------------------
class TestStreckeResults:
"""Validiert omniflo_strecke_results.json aus c:TEST_OMNIFLO_STRECKE."""
@pytest.fixture
def results(self):
path = os.path.join(_output_dir(), "omniflo_strecke_results.json")
if not os.path.exists(path):
pytest.skip("omniflo_strecke_results.json nicht vorhanden - "
"TEST_OMNIFLO_STRECKE in BricsCAD ausfuehren")
data = _load_json(path)
if not data:
pytest.skip("omniflo_strecke_results.json ist leer")
return data
def test_alle_elemente_ausgefuehrt(self, strecke, results):
assert len(results) == len(strecke), (
f"Erwartet {len(strecke)} Ergebnisse, erhalten {len(results)}")
def test_alle_ok(self, results):
for r in results:
assert r["status"] == "OK", (
f'{r.get("test_id")} (seq {r.get("seq")}): Status={r["status"]}')