Files
Projektwissen/tests/test_referenzmodelle.py
T

66 lines
3.0 KiB
Python
Raw Normal View History

"""Strukturtests für die Referenzmodelle (.agents/skills/sn-bpmn/beispiele/referenz_*.md) – reines Python/pytest.
Die Referenzmodelle sind echte, größere Prozesse. Der Byte-Vergleich in test_pruefe_prozesse.py meldet jede
Änderung an der Ausgabe von md_to_bpmn.py; diese Tests prüfen zusätzlich, ob das Ergebnis danach noch den
Modellierregeln und den Grenzen von PICTURE genügt – auch wenn die .bpmn bewusst neu erzeugt wurde.
"""
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[1]
SKILL = ROOT / ".agents" / "skills" / "sn-bpmn"
sys.path.insert(0, str(SKILL))
import md_to_bpmn as m # noqa: E402
from test_md_to_bpmn import _kante_kreuzt_gateway # noqa: E402 (dieselbe Geometrieprüfung wie dort)
REFERENZEN = sorted((SKILL / "beispiele").glob("referenz_*.md"))
GATEWAYS = ("exclusiveGateway", "inclusiveGateway", "parallelGateway", "eventBasedGateway")
# Bekannte, noch nicht behobene Konverterfehler je Referenzmodell. strict=True: Sobald der Fehler behoben ist,
# schlägt der Test als XPASS fehl – dann den Eintrag hier entfernen. Nie verwenden, um neue Fehler zu verstecken.
BEKANNTE_KANTEN_DURCH_GATEWAY = {
"referenz_gewannenfestlegung": "Issue #8: Kante S12→S13 (Ja) läuft senkrecht durch die Raute von S13",
}
def mit_bekannten_fehlern(bekannt):
return [pytest.param(md, id=md.stem, marks=pytest.mark.xfail(reason=bekannt[md.stem], strict=True))
if md.stem in bekannt else pytest.param(md, id=md.stem) for md in REFERENZEN]
def baue(md):
meta, steps, order, externals = m.parse_markdown(md.read_text(encoding="utf-8"))
return m.build_bpmn(meta, steps, order, externals)
def test_es_gibt_mindestens_ein_referenzmodell():
"""Prüft, dass die Strukturtests tatsächlich an einem Referenzmodell laufen."""
assert REFERENZEN
@pytest.mark.parametrize("md", REFERENZEN, ids=lambda p: p.stem)
def test_jedes_element_hat_eine_zustaendigkeit(md):
"""Prüft, dass im Referenzmodell kein Element in der Lane 'Nicht zugeordnet' landet."""
lanes = [lane.get("name") for lane in baue(md).iter(f"{{{m.NS['bpmn']}}}lane")]
assert lanes, "Referenzmodell ohne Lanes"
assert m.UNASSIGNED_LANE not in lanes
@pytest.mark.parametrize("md", REFERENZEN, ids=lambda p: p.stem)
def test_kein_gateway_hat_mehr_als_vier_kanten(md):
"""Prüft Modellierregel 4: kein Gateway im Referenzmodell braucht mehr als die vier Anschlusspunkte von PICTURE."""
defs = baue(md)
for tag in GATEWAYS:
for gateway in defs.iter(f"{{{m.NS['bpmn']}}}{tag}"):
kanten = gateway.findall(f"{{{m.NS['bpmn']}}}incoming") + gateway.findall(f"{{{m.NS['bpmn']}}}outgoing")
assert len(kanten) <= 4, f"{gateway.get('id')} hat {len(kanten)} Kanten"
@pytest.mark.parametrize("md", mit_bekannten_fehlern(BEKANNTE_KANTEN_DURCH_GATEWAY))
def test_keine_kante_fuehrt_durchs_innere_eines_gateways(md):
"""Prüft, dass im Referenzmodell keine Kante quer durch eine Raute läuft (Fallstrick Gateway-Kantenführung)."""
assert _kante_kreuzt_gateway(baue(md), m.NS) is None