66 lines
3.0 KiB
Python
66 lines
3.0 KiB
Python
"""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
|