#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ test_vf_geometrie.py - Regressionsnetz fuer die GEBAUTE Geometrie der HundM-Ketten. Warum zusaetzlich zu tests/test_hundm05.py: der Ergebnis-Record sagt "executed, kein Prompt, Journal aufgegangen" - er sagt NICHT, ob dieselbe Geometrie herauskam wie vorher. Genau das ist bei der Funktionstrennung in Stufe 2 (doc/TODO-plan-vf-interactive.md) das Risiko: die Reihenfolge der dL-Subtraktionen und der vfl-acc-*-Aufrufe IST Geometrie, und eine falsche Reihenfolge faellt in der Zeichnung nicht auf - nur im Sivas-Export. Verglichen wird gegen tests/reference/hundm05_attribute.json: - alle Attribute des VF_n-Blocks, insbesondere die reihenfolgeabhaengigen Komma-Listen L_VF_m / L_GF_m / GF_WINKEL / ANTRIEBFAHRTRICHTUNG - die Bausteinzusammensetzung des Blocks (faengt eine falsche Blockvariante, die kein Attribut verraet) - der Einfuegepunkt Die laufende ID und der Blockname sind bewusst NICHT Teil des Vergleichs: die VF-Nummer beginnt in jeder neuen Zeichnung wieder bei 1. Braucht eine gebaute Zeichnung (TEST_HUNDM05 mit "save": "dxf") und wird sonst uebersprungen. Referenz auffrischen - nur nach geprueftem Lauf: python lib/dxf_vf_abbild.py --spec tests/testdata/hundm05.json \ --referenz tests/reference/hundm05_attribute.json \ --schreibe-referenz """ import json import os import sys import pytest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib")) import dxf_vf_abbild as dva # noqa: E402 HIER = os.path.dirname(__file__) SPEC = os.path.join(HIER, "testdata", "hundm05.json") REFERENZ = os.path.join(HIER, "reference", "hundm05_attribute.json") # SSG_RUN_ALL_TESTS legt die Zeichnung in tests/output ab; ein Lauf mit # gesetztem DXFM_RESULTS speichert sie nach results/. DXF_ORTE = [os.path.join(HIER, "output", "hundm05_tests.dxf"), os.path.join(HIER, "..", "results", "test_hundm05.dxf")] @pytest.fixture(scope="module") def gebautes_abbild(): for pfad in DXF_ORTE: if os.path.isfile(pfad): return dva.abbild(pfad, SPEC, ("VF_",)) pytest.skip("keine gebaute HundM05-Zeichnung gefunden (%s) - " "TEST_HUNDM05 in BricsCAD ausfuehren" % " bzw. ".join(os.path.basename(p) for p in DXF_ORTE)) @pytest.fixture(scope="module") def referenz(): if not os.path.isfile(REFERENZ): pytest.skip("%s fehlt - mit lib/dxf_vf_abbild.py " "--schreibe-referenz anlegen" % REFERENZ) with open(REFERENZ, encoding="utf-8") as fh: return json.load(fh) def test_referenz_deckt_alle_specs(referenz): """Jede Kette der Spec muss in der Referenz stehen - sonst laeuft der Vergleich unbemerkt ins Leere.""" if not os.path.isfile(SPEC): pytest.skip("Spec fehlt") with open(SPEC, encoding="utf-8") as fh: specs = [o["spec_id"] for o in json.load(fh) if "spec_id" in o] fehlt = sorted(set(specs) - set(referenz)) assert not fehlt, ( "Ketten ohne Referenz: %s. Nach einem geprueften Lauf die Referenz " "mit lib/dxf_vf_abbild.py --schreibe-referenz auffrischen." % fehlt) def test_alle_ketten_gebaut(gebautes_abbild, referenz): fehlt = sorted(set(referenz) - set(gebautes_abbild)) assert not fehlt, "in der Zeichnung nicht gebaut: %s" % fehlt @pytest.mark.parametrize("feld", ["bausteine", "bausteine_gesamt"]) def test_bausteine_wie_referenz(gebautes_abbild, referenz, feld): """Die Bausteinliste faengt, was kein Attribut verraet: eine falsche Blockvariante (z.B. auf_3 statt ab_3, links statt rechts).""" for kette, soll in sorted(referenz.items()): if kette not in gebautes_abbild: continue ist = gebautes_abbild[kette] assert ist[feld] == soll[feld], \ f"{kette}: {feld} ist {ist[feld]}, Referenz {soll[feld]}" def test_attribute_wie_referenz(gebautes_abbild, referenz): for kette, soll in sorted(referenz.items()): if kette not in gebautes_abbild: continue ist = gebautes_abbild[kette]["attribs"] for tag in sorted(set(ist) | set(soll["attribs"])): assert ist.get(tag) == soll["attribs"].get(tag), \ f'{kette}: Attribut {tag} ist {ist.get(tag)!r}, ' \ f'Referenz {soll["attribs"].get(tag)!r}' def test_reihenfolge_listen_wie_referenz(gebautes_abbild, referenz): """Eigener Test fuer die Komma-Listen: sie sind das einzige, was eine vertauschte vfl-acc-*-Reihenfolge sichtbar macht - in der Zeichnung unsichtbar, im Sivas-Export falsch.""" listen = ("L_VF_m", "L_GF_m", "GF_WINKEL", "ANTRIEBFAHRTRICHTUNG") for kette, soll in sorted(referenz.items()): if kette not in gebautes_abbild: continue ist = gebautes_abbild[kette]["attribs"] for tag in listen: if tag not in soll["attribs"]: continue assert ist.get(tag) == soll["attribs"][tag], \ f'{kette}: {tag} ist {ist.get(tag)!r}, ' \ f'Referenz {soll["attribs"][tag]!r} - Reihenfolge der ' \ f'vfl-acc-*-Aufrufe geaendert?' def test_einfuegepunkt_wie_referenz(gebautes_abbild, referenz): for kette, soll in sorted(referenz.items()): if kette not in gebautes_abbild: continue for achse, (a, b) in enumerate( zip(gebautes_abbild[kette]["insert"], soll["insert"])): assert abs(a - b) < 1.0, \ f"{kette}: Einfuegepunkt Achse {achse} ist {a}, Referenz {b}" def test_vergleichsfunktion_meldet_abweichung(gebautes_abbild, referenz): """Gegenprobe: der Vergleich muss eine verfaelschte Referenz erkennen - sonst bewiesen die Tests oben nur, dass beide Seiten gleich gelesen werden.""" kette = sorted(referenz)[0] gift = json.loads(json.dumps(referenz)) gift[kette]["attribs"]["DELTA_L_mm"] = "999999" assert dva.vergleiche(gebautes_abbild, gift), \ "verfaelschte Referenz wurde NICHT erkannt" assert not dva.vergleiche(gebautes_abbild, referenz), \ "echte Referenz wird als abweichend gemeldet"