omniflo csv Export lisp routine entfernt.

This commit is contained in:
2026-07-02 14:04:32 +02:00
parent 3869f8b624
commit f73f0c123a
3 changed files with 65 additions and 115 deletions
@@ -106,3 +106,4 @@ Elementnummer;TeileArt;TeileId;Bezeichnung;Anzahl;Merkmale
105;"Omniflo Weiche";"0000";"OFWeiche :6";1;{"Weichentyp": "Dreifachweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372404+0_BG071090"} 105;"Omniflo Weiche";"0000";"OFWeiche :6";1;{"Weichentyp": "Dreifachweiche", "Richtung": "3", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": true, "SivasNummer": "834372404+0_BG071090"}
106;"Omniflo Weiche";"0000";"OFWeiche :1";1;{"Weichentyp": "Deltaweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372401"} 106;"Omniflo Weiche";"0000";"OFWeiche :1";1;{"Weichentyp": "Deltaweiche", "Richtung": "7", "Weichenwinkel": 90.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372401"}
107;"Omniflo Weiche";"0000";"OFWeiche :1";1;{"Weichentyp": "Sternweiche", "Richtung": "3", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372420"} 107;"Omniflo Weiche";"0000";"OFWeiche :1";1;{"Weichentyp": "Sternweiche", "Richtung": "3", "Weichenwinkel": 0.0, "Höhe": "2000", "Drehung": 0.0, "Antrieb Kurve": false, "SivasNummer": "834372420"}
108;"Omniflo Sum";"autogenerated_of_json";"Omniflo sum";1;{"Anzahl Bögen": 27, "Anzahl Weichengrundkörper": 0, "Anzahl Einwegweichen": 30, "Anzahl Deltaweichen": 7, "Anzahl Doppelweichen und Dreiwegeweichen": 42, "Anzahl Sternweichen": 1, "Gesamtlänge AP110": 0.0, "Gesamtlänge AP60": 0.0}
Can't render this file because it contains an unexpected character in line 2 and column 42.
+6 -20
View File
@@ -1,10 +1,11 @@
;; ============================================================ ;; ============================================================
;; test_omniflo.lsp - Automatischer Integrationstest fuer Omniflo ;; test_omniflo.lsp - Automatischer Integrationstest fuer Omniflo
;; ;;
;; Laedt Testfaelle aus tests/testdata/omniflo_tests.json, ;; Laedt Testfaelle aus tests/testdata/omniflo_tests.json und
;; fuegt je einen Bogen und Weiche jeden Typs in verschiedenen ;; fuegt je einen Bogen und Weiche jeden Typs in verschiedenen
;; Hoehen ein (Versatz in x-Richtung je 200mm) und exportiert ;; Hoehen ein (Versatz in x-Richtung je 200mm). Ergebnisse werden
;; die CSV-Datei nach tests/output/omniflo_export.csv. ;; ueber omniflo:export-results nach tests/output/omniflo_results.json
;; geschrieben (Aufruf durch SSG_RUN_ALL_TESTS oder manuell).
;; ;;
;; Voraussetzungen: ;; Voraussetzungen:
;; - SSG_LIB geladen (OmniModulInsert.lsp, export.lsp) ;; - SSG_LIB geladen (OmniModulInsert.lsp, export.lsp)
@@ -104,14 +105,13 @@
;; ============================================================ ;; ============================================================
;; C:TEST_OMNIFLO ;; C:TEST_OMNIFLO
;; ;;
;; Liest omniflo_tests.json, fuegt alle Testbloecke ein, ;; Liest omniflo_tests.json und fuegt alle Testbloecke ein.
;; exportiert CSV nach tests/output/.
;; ============================================================ ;; ============================================================
(defun c:TEST_OMNIFLO (/ tests-json-pfad testfaelle (defun c:TEST_OMNIFLO (/ tests-json-pfad testfaelle
x-val y-val x-val y-val
idx eintrag sivasnr hoehe-str drehung-str idx eintrag sivasnr hoehe-str drehung-str
description insert-pt anzahl-ok anzahl-fehler description insert-pt anzahl-ok anzahl-fehler
results-list tests-out-dir old-results) results-list)
(ssg-start "TEST_OMNIFLO" (ssg-start "TEST_OMNIFLO"
'(("OSMODE") ("ATTREQ") ("ATTDIA"))) '(("OSMODE") ("ATTREQ") ("ATTDIA")))
@@ -217,24 +217,10 @@
;; Ergebnisse in globaler Variable speichern ;; Ergebnisse in globaler Variable speichern
(setq *omniflo-test-results* (reverse results-list)) (setq *omniflo-test-results* (reverse results-list))
;; CSV-Export nach tests/output/
(setq tests-out-dir
(strcat (getenv "DXFMAKRO") "/tests/output"))
(vl-mkdir tests-out-dir)
(setq old-results (getenv "DXFM_RESULTS"))
(setenv "DXFM_RESULTS" tests-out-dir)
(princ "\n[TEST_OMNIFLO] Starte OMNI_EXPORT -> tests/output/omniflo_export.csv")
(c:OMNI_EXPORT)
(setenv "DXFM_RESULTS" (if old-results old-results ""))
(ssg-end) (ssg-end)
(princ "\n================================================================") (princ "\n================================================================")
(princ "\n TEST_OMNIFLO abgeschlossen.") (princ "\n TEST_OMNIFLO abgeschlossen.")
(princ (strcat "\n CSV: " tests-out-dir "/omniflo_export.csv"))
(princ "\n================================================================") (princ "\n================================================================")
(princ) (princ)
) )
+58 -95
View File
@@ -6,11 +6,11 @@ test_omniflo.py - Validiert Omniflo Bogen/Weiche Export.
Prueft: Prueft:
1. CSV-Inhalt gegen Testdefinitionen (Unit-Test, ohne BricsCAD) 1. CSV-Inhalt gegen Testdefinitionen (Unit-Test, ohne BricsCAD)
2. Merkmale-Werte gegen JSON-Katalog 2. Merkmale-Werte gegen JSON-Katalog
3. Korrekte Anzahl und Reihenfolge der Elemente 3. Korrekte Anzahl und Reihenfolge der Elemente inkl. Omniflo-Sum-Zeile
4. Integrationstest: liest CSV aus BricsCAD-Lauf (falls vorhanden) 4. Integrationstest: liest omniflo_results.json aus BricsCAD-Lauf (falls vorhanden)
5. Referenz-Vergleich: CSV-Export aus export_csv.py gegen abgenommene Referenz-CSV
""" """
import csv
import json import json
import os import os
import sys import sys
@@ -99,6 +99,9 @@ class TestOmnifloExportUnit:
drehung=float(tc["drehung"]), drehung=float(tc["drehung"]),
)) ))
self.items = process_blocks(self.blocks, self.lookup) self.items = process_blocks(self.blocks, self.lookup)
# Item-Zeilen ohne die abschliessende "Omniflo Sum"-Zeile
self.element_items = [it for it in self.items if it["teileart"] != "Omniflo Sum"]
self.sum_item = next((it for it in self.items if it["teileart"] == "Omniflo Sum"), None)
# CSV in output speichern # CSV in output speichern
out_dir = _output_dir() out_dir = _output_dir()
@@ -112,27 +115,40 @@ class TestOmnifloExportUnit:
def test_item_count_matches_testcases(self): def test_item_count_matches_testcases(self):
"""Anzahl exportierter Elemente muss Anzahl Testfaelle entsprechen.""" """Anzahl exportierter Elemente muss Anzahl Testfaelle entsprechen."""
assert len(self.items) == len(self.tests), ( assert len(self.element_items) == len(self.tests), (
f"Erwartet {len(self.tests)} Elemente, erhalten {len(self.items)}" f"Erwartet {len(self.tests)} Elemente, erhalten {len(self.element_items)}"
) )
def test_numbering_starts_at_one(self): def test_numbering_starts_at_one(self):
"""Element-Nummerierung muss bei 1 beginnen.""" """Element-Nummerierung muss bei 1 beginnen."""
assert self.items[0]["nr"] == 1, ( assert self.element_items[0]["nr"] == 1, (
f"Erstes Element: nr={self.items[0]['nr']}, erwartet 1" f"Erstes Element: nr={self.element_items[0]['nr']}, erwartet 1"
) )
def test_numbering_is_consecutive(self): def test_numbering_is_consecutive(self):
"""Element-Nummern muessen lueckenlos aufsteigen.""" """Element-Nummern muessen lueckenlos aufsteigen (inkl. abschliessender Sum-Zeile)."""
for i, item in enumerate(self.items): for i, item in enumerate(self.items):
assert item["nr"] == i + 1, ( assert item["nr"] == i + 1, (
f"Element {i}: nr={item['nr']}, erwartet {i + 1}" f"Element {i}: nr={item['nr']}, erwartet {i + 1}"
) )
def test_sum_zeile_angehaengt(self):
"""Nach allen Omniflo-Elementen muss eine 'Omniflo Sum'-Zeile folgen."""
assert self.sum_item is not None, "Keine 'Omniflo Sum'-Zeile erzeugt"
assert self.sum_item["nr"] == len(self.items)
assert self.sum_item["teileid"] == "autogenerated_of_json"
m = self.sum_item["merkmale"]
bogen_tests = [tc for tc in self.tests if tc["type"] == "bogen"]
weiche_tests = [tc for tc in self.tests if tc["type"] == "weiche"]
assert m["Anzahl Bögen"] == len(bogen_tests)
assert (m["Anzahl Weichengrundkörper"] + m["Anzahl Einwegweichen"]
+ m["Anzahl Deltaweichen"] + m["Anzahl Doppelweichen und Dreiwegeweichen"]
+ m["Anzahl Sternweichen"]) == len(weiche_tests)
def test_bogen_teileart(self): def test_bogen_teileart(self):
"""Boegen muessen TeileArt 'Omniflo Kurve' haben.""" """Boegen muessen TeileArt 'Omniflo Kurve' haben."""
bogen_tests = [tc for tc in self.tests if tc["type"] == "bogen"] bogen_tests = [tc for tc in self.tests if tc["type"] == "bogen"]
bogen_items = [it for it in self.items if it["teileart"] == "Omniflo Kurve"] bogen_items = [it for it in self.element_items if it["teileart"] == "Omniflo Kurve"]
assert len(bogen_items) == len(bogen_tests), ( assert len(bogen_items) == len(bogen_tests), (
f"Erwartet {len(bogen_tests)} Boegen, erhalten {len(bogen_items)}" f"Erwartet {len(bogen_tests)} Boegen, erhalten {len(bogen_items)}"
) )
@@ -140,7 +156,7 @@ class TestOmnifloExportUnit:
def test_weiche_teileart(self): def test_weiche_teileart(self):
"""Weichen muessen TeileArt 'Omniflo Weiche' haben.""" """Weichen muessen TeileArt 'Omniflo Weiche' haben."""
weiche_tests = [tc for tc in self.tests if tc["type"] == "weiche"] weiche_tests = [tc for tc in self.tests if tc["type"] == "weiche"]
weiche_items = [it for it in self.items if it["teileart"] == "Omniflo Weiche"] weiche_items = [it for it in self.element_items if it["teileart"] == "Omniflo Weiche"]
assert len(weiche_items) == len(weiche_tests), ( assert len(weiche_items) == len(weiche_tests), (
f"Erwartet {len(weiche_tests)} Weichen, erhalten {len(weiche_items)}" f"Erwartet {len(weiche_tests)} Weichen, erhalten {len(weiche_items)}"
) )
@@ -148,7 +164,7 @@ class TestOmnifloExportUnit:
def test_bogen_merkmale_felder(self): def test_bogen_merkmale_felder(self):
"""Boegen-Merkmale muessen alle Pflichtfelder enthalten.""" """Boegen-Merkmale muessen alle Pflichtfelder enthalten."""
required = {"Kurvenwinkel", "Radius", "Höhe", "Drehung", "SivasNummer"} required = {"Kurvenwinkel", "Radius", "Höhe", "Drehung", "SivasNummer"}
for item in self.items: for item in self.element_items:
if item["teileart"] != "Omniflo Kurve": if item["teileart"] != "Omniflo Kurve":
continue continue
merkmale = item["merkmale"] merkmale = item["merkmale"]
@@ -161,7 +177,7 @@ class TestOmnifloExportUnit:
"""Weichen-Merkmale muessen alle Pflichtfelder enthalten.""" """Weichen-Merkmale muessen alle Pflichtfelder enthalten."""
required = {"Weichentyp", "Richtung", "Weichenwinkel", required = {"Weichentyp", "Richtung", "Weichenwinkel",
"Höhe", "Drehung", "Antrieb Kurve", "SivasNummer"} "Höhe", "Drehung", "Antrieb Kurve", "SivasNummer"}
for item in self.items: for item in self.element_items:
if item["teileart"] != "Omniflo Weiche": if item["teileart"] != "Omniflo Weiche":
continue continue
merkmale = item["merkmale"] merkmale = item["merkmale"]
@@ -174,7 +190,7 @@ class TestOmnifloExportUnit:
"""Bogen-Merkmale muessen mit JSON-Katalog uebereinstimmen.""" """Bogen-Merkmale muessen mit JSON-Katalog uebereinstimmen."""
for tc, item in zip( for tc, item in zip(
[t for t in self.tests if t["type"] == "bogen"], [t for t in self.tests if t["type"] == "bogen"],
[it for it in self.items if it["teileart"] == "Omniflo Kurve"] [it for it in self.element_items if it["teileart"] == "Omniflo Kurve"]
): ):
sivasnr = tc["sivasnr"] sivasnr = tc["sivasnr"]
assert sivasnr in self.lookup, f"SivasNr {sivasnr} nicht im Katalog" assert sivasnr in self.lookup, f"SivasNr {sivasnr} nicht im Katalog"
@@ -200,7 +216,7 @@ class TestOmnifloExportUnit:
"""Weichen-Merkmale muessen mit JSON-Katalog uebereinstimmen.""" """Weichen-Merkmale muessen mit JSON-Katalog uebereinstimmen."""
for tc, item in zip( for tc, item in zip(
[t for t in self.tests if t["type"] == "weiche"], [t for t in self.tests if t["type"] == "weiche"],
[it for it in self.items if it["teileart"] == "Omniflo Weiche"] [it for it in self.element_items if it["teileart"] == "Omniflo Weiche"]
): ):
sivasnr = tc["sivasnr"] sivasnr = tc["sivasnr"]
assert sivasnr in self.lookup, f"SivasNr {sivasnr} nicht im Katalog" assert sivasnr in self.lookup, f"SivasNr {sivasnr} nicht im Katalog"
@@ -229,7 +245,7 @@ class TestOmnifloExportUnit:
def test_bogen_hoehe_als_string(self): def test_bogen_hoehe_als_string(self):
"""Bogen-Hoehe muss als String vorliegen (z.B. '2000', nicht 2000).""" """Bogen-Hoehe muss als String vorliegen (z.B. '2000', nicht 2000)."""
for item in self.items: for item in self.element_items:
if item["teileart"] != "Omniflo Kurve": if item["teileart"] != "Omniflo Kurve":
continue continue
assert isinstance(item["merkmale"]["Höhe"], str), ( assert isinstance(item["merkmale"]["Höhe"], str), (
@@ -239,7 +255,7 @@ class TestOmnifloExportUnit:
def test_weiche_hoehe_als_string(self): def test_weiche_hoehe_als_string(self):
"""Weichen-Hoehe muss als String vorliegen.""" """Weichen-Hoehe muss als String vorliegen."""
for item in self.items: for item in self.element_items:
if item["teileart"] != "Omniflo Weiche": if item["teileart"] != "Omniflo Weiche":
continue continue
assert isinstance(item["merkmale"]["Höhe"], str), ( assert isinstance(item["merkmale"]["Höhe"], str), (
@@ -248,7 +264,7 @@ class TestOmnifloExportUnit:
def test_kurvenwinkel_als_float(self): def test_kurvenwinkel_als_float(self):
"""Kurvenwinkel muss als Float vorliegen (90.0, nicht 90).""" """Kurvenwinkel muss als Float vorliegen (90.0, nicht 90)."""
for item in self.items: for item in self.element_items:
if item["teileart"] == "Omniflo Kurve": if item["teileart"] == "Omniflo Kurve":
assert isinstance(item["merkmale"]["Kurvenwinkel"], float), ( assert isinstance(item["merkmale"]["Kurvenwinkel"], float), (
f"{item['bezeichnung']}: Kurvenwinkel muss float sein" f"{item['bezeichnung']}: Kurvenwinkel muss float sein"
@@ -273,90 +289,37 @@ class TestOmnifloExportUnit:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Integrations-Tests: CSV aus BricsCAD-Lauf validieren # Integrations-Tests: Omniflo-Ergebnisse aus BricsCAD-Lauf validieren
# (tests/output/omniflo_results.json, geschrieben von omniflo:export-results)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
class TestOmnifloExportCSV: class TestOmnifloResults:
"""Validiert CSV-Datei aus dem BricsCAD-Lauf (c:TEST_OMNIFLO_EXPORT).""" """Validiert omniflo_results.json aus dem BricsCAD-Lauf (c:TEST_OMNIFLO)."""
@pytest.fixture(autouse=True) def test_all_tests_executed(self, omniflo_testdata, omniflo_results):
def setup(self): """Alle definierten Testfaelle muessen ausgefuehrt worden sein."""
csv_path = os.path.join(_output_dir(), "omniflo_export.csv") expected_sivas = {t["sivasnr"] for t in omniflo_testdata}
if not os.path.exists(csv_path): result_sivas = {r["sivasnr"] for r in omniflo_results}
pytest.skip( missing = expected_sivas - result_sivas
"omniflo_export.csv nicht vorhanden - " assert not missing, f"Nicht ausgefuehrte Tests: {missing}"
"TEST_OMNIFLO_EXPORT in BricsCAD ausfuehren"
)
self.csv_path = csv_path
self.rows = []
with open(csv_path, "r", encoding="utf-8") as f:
reader = csv.reader(f, delimiter=";")
self.header = next(reader)
for row in reader:
self.rows.append(row)
def test_header_felder(self): def test_all_executed_successfully(self, omniflo_results):
"""CSV-Header muss korrekte Spaltenbezeichnungen haben.""" """Alle Ergebnisse muessen Status 'OK' haben."""
assert self.header[0] == "Elementnummer" for result in omniflo_results:
assert self.header[1] == "TeileArt" assert result["status"] == "OK", (
assert self.header[2] == "TeileId" f'{result["test_id"]} ({result["sivasnr"]}): Status={result["status"]}'
assert self.header[3] == "Bezeichnung"
assert self.header[4] == "Anzahl"
assert self.header[5] == "Merkmale"
def test_mindest_anzahl_zeilen(self):
"""CSV muss mindestens so viele Zeilen haben wie Testfaelle."""
tests = _load_omniflo_tests()
assert len(self.rows) >= len(tests), (
f"CSV hat {len(self.rows)} Zeilen, "
f"erwartet mind. {len(tests)}"
)
def test_anzahl_spalte_ist_eins(self):
"""Anzahl-Spalte muss fuer alle Zeilen '1' sein."""
for i, row in enumerate(self.rows):
if len(row) < 5:
continue
assert row[4] == "1", (
f"Zeile {i + 2}: Anzahl={row[4]}, erwartet 1"
) )
def test_merkmale_sind_valides_json(self): def test_hoehe_matches(self, omniflo_testdata, omniflo_results):
"""Merkmale-Spalte muss valides JSON enthalten.""" """Eingefuegte Hoehe muss dem Testfall entsprechen."""
for i, row in enumerate(self.rows): results_by_sivas = {r["sivasnr"]: r for r in omniflo_results}
if len(row) < 6: for test in omniflo_testdata:
result = results_by_sivas.get(test["sivasnr"])
if not result:
continue continue
try: assert result["hoehe"] == str(int(test["hoehe"])), (
json.loads(row[5]) f'{test["sivasnr"]}: Hoehe erwartet={test["hoehe"]}, '
except json.JSONDecodeError as e: f'ist={result["hoehe"]}'
pytest.fail(
f"Zeile {i + 2}: Merkmale ist kein valides JSON: {e}\n"
f" Inhalt: {row[5][:100]}"
)
def test_bogen_merkmale_felder_in_csv(self):
"""Bogen-Zeilen muessen Pflichtfelder in Merkmale haben."""
required = {"Kurvenwinkel", "Radius", "Höhe", "Drehung", "SivasNummer"}
for i, row in enumerate(self.rows):
if len(row) < 6 or row[1].strip('"') != "Omniflo Kurve":
continue
merkmale = json.loads(row[5])
missing = required - set(merkmale.keys())
assert not missing, (
f"Zeile {i + 2}: Fehlende Bogen-Felder: {missing}"
)
def test_weiche_merkmale_felder_in_csv(self):
"""Weichen-Zeilen muessen Pflichtfelder in Merkmale haben."""
required = {"Weichentyp", "Richtung", "Weichenwinkel",
"Höhe", "Drehung", "Antrieb Kurve", "SivasNummer"}
for i, row in enumerate(self.rows):
if len(row) < 6 or row[1].strip('"') != "Omniflo Weiche":
continue
merkmale = json.loads(row[5])
missing = required - set(merkmale.keys())
assert not missing, (
f"Zeile {i + 2}: Fehlende Weichen-Felder: {missing}"
) )
@@ -377,7 +340,7 @@ def _normalize_row(line):
class TestOmnifloReferenceCSV: class TestOmnifloReferenceCSV:
"""Vergleicht den erzeugten Unit-Test-CSV-Export mit einer Referenzdatei.""" """Vergleicht den von export_csv.py erzeugten CSV-Export mit einer Referenzdatei."""
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def setup(self): def setup(self):