Files
dxfmakros/doc/LispTests.md
T

274 lines
7.7 KiB
Markdown

# Testkonzept SSG_LIB - Hybrid AutoLISP + Python
## Uebersicht
Die SSG_LIB AutoLISP-Makros werden ueber einen zweistufigen Hybrid-Ansatz getestet:
1. **AutoLISP** (in BricsCAD): Liest JSON-Testfaelle, fuehrt die Funktionen aus,
schreibt Ergebnisse als JSON und DXF.
2. **Python** (pytest + ezdxf): Validiert die Ergebnisse automatisch gegen
erwartete Werte und optionale Referenz-DXFs.
```
Python (pytest) AutoLISP (BricsCAD) Python (pytest)
=============== ==================== ===============
Testfall-Definitionen --> Ausfuehrung der --> Validierung:
als JSON bereitstellen LISP-Funktionen - JSON-Ergebnisse
+ DXF + results.json - DXF-Geometrie
- Referenz-Vergleich
```
## Verzeichnisstruktur
```
tests/
├── testdata/ # JSON-Testfall-Definitionen (versioniert)
│ ├── kreisel_tests.json
│ ├── vario_tests.json
│ └── omniflo_tests.json
├── reference/ # Abgenommene Referenz-DXFs (versioniert)
│ └── kreisel_ref.dxf
├── output/ # Generierte Ergebnisse (in .gitignore)
│ ├── kreisel_tests.dxf
│ └── kreisel_results.json
├── ssg_testrunner.lsp # LISP Test-Runner
├── conftest.py # pytest Fixtures
├── test_kreisel.py # pytest Kreisel-Validierung
├── test_vario.py # pytest Vario-Validierung
├── test_omniflo.py # pytest Omniflo-Validierung
└── requirements.txt # Python-Abhaengigkeiten (ezdxf, pytest)
```
## Schritt 1: Testfaelle definieren (JSON)
Jedes Modul hat eine eigene JSON-Datei in `tests/testdata/`. Aufbau:
```json
{
"module": "Kreisel",
"version": "1.0",
"description": "ILS Kreisel Testfaelle",
"tests": [
{
"id": "KR_Horiz_ObenUnten",
"function": "draw-module",
"params": {
"basepoint": [500.0, 5000.0, 2500.0],
"abstand": 4200.0,
"rotation": 270.0,
"attribs": {
"KREISELART": "STANDARD",
"NAME": "TEST_H_ObenUnten"
}
},
"expect": {
"attributes": {
"KREISELART": "STANDARD",
"DREHUNG": "270",
"ABSTAND": "4200"
},
"block_prefix": "KR_",
"min_entities": 6
}
}
]
}
```
### Felder
| Feld | Beschreibung |
|---|---|
| `id` | Eindeutiger Testfall-Name |
| `function` | Aufzurufende LISP-Funktion |
| `params` | Uebergabewerte an die Funktion |
| `expect.attributes` | Erwartete Block-Attribute nach Ausfuehrung |
| `expect.block_prefix` | Erwartetes Praefix des erzeugten Block-Namens |
| `expect.min_entities` | Mindestanzahl Entities im erzeugten Block |
## Schritt 2: LISP Test-Runner (ssg_testrunner.lsp)
Der LISP Test-Runner liest die JSON-Testfaelle, fuehrt die Funktionen in
BricsCAD aus und schreibt die Ergebnisse.
### Aufruf in BricsCAD
```
Command: TESTRUN "kreisel"
```
Der Befehl:
1. Liest `tests/testdata/kreisel_tests.json`
2. Erstellt eine neue leere Zeichnung
3. Fuehrt fuer jeden Testfall die angegebene Funktion mit den Parametern aus
4. Sammelt Ergebnisse: Block-Handle, tatsaechliche Attribute, Insertionspunkt
5. Schreibt `tests/output/kreisel_results.json`
6. Speichert die Zeichnung als `tests/output/kreisel_tests.dxf`
### Ausgabe: results.json
```json
[
{
"test_id": "KR_Horiz_ObenUnten",
"status": "executed",
"block_handle": "A3F",
"block_name": "KR_STANDARD_01",
"insert_point": [500.0, 5000.0, 2500.0],
"rotation": 270.0,
"actual_attributes": {
"KREISELART": "STANDARD",
"DREHUNG": "270",
"ABSTAND": "4200",
"NAME": "TEST_H_ObenUnten"
}
}
]
```
## Schritt 3: Python-Validierung (pytest)
Die Python-Tests lesen `results.json` und die erzeugte DXF-Datei und pruefen:
### 3a. Attribut-Pruefung (results.json)
Vergleicht `actual_attributes` aus results.json gegen `expect.attributes`
aus den Testdefinitionen. Keine BricsCAD-Instanz noetig.
### 3b. Geometrie-Pruefung (ezdxf)
Oeffnet die erzeugte DXF-Datei mit der Python-Bibliothek `ezdxf` und prueft:
- **Block-Existenz**: Alle erwarteten Bloecke im Modelspace vorhanden
- **Entity-Anzahl**: Mindestanzahl Entities pro Block
- **Kreisradien**: AN8/SP8-Kreise haben korrekten Radius (400mm)
- **Linienlaengen**: Tangenten haben korrekte Laenge (= Abstand)
- **Layer-Zuordnung**: Entities auf korrektem Layer
- **Insertionspunkte**: Bloecke an erwarteter Position
### 3c. Referenz-Vergleich
Vergleicht die Ergebnis-DXF gegen eine abgenommene Referenz-DXF:
- Gleiche Anzahl Bloecke im Modelspace
- Gleiche Block-Typen
- Gleiche Attributwerte
## Schritt 4: Referenz-Management
### Neue Referenz erstellen (erster Lauf oder nach Aenderung)
```bash
# 1. Tests in BricsCAD ausfuehren
# Command: TESTRUN "kreisel"
# 2. Ergebnis-DXF visuell pruefen (in BricsCAD oeffnen)
# 3. Wenn OK: Als neue Referenz speichern
copy tests\output\kreisel_tests.dxf tests\reference\kreisel_ref.dxf
```
### Referenz aktualisieren
Wenn sich die LISP-Logik aendert und die neuen Ergebnisse korrekt sind:
```bash
# 1. Tests in BricsCAD ausfuehren
# 2. Ergebnis visuell pruefen
# 3. Python-Tests zeigen Referenz-Abweichung:
pytest tests/test_kreisel.py -v
# FAILED test_block_count_matches_reference - 6 != 5
# 4. Neue Referenz speichern
copy tests\output\kreisel_tests.dxf tests\reference\kreisel_ref.dxf
# 5. Tests erneut ausfuehren - jetzt PASS
pytest tests/test_kreisel.py -v
```
## Ausfuehrung
### Kompletter Testlauf
```bash
# Umgebung setzen
bin\setenv.bat
# 1. Testdaten-DXF erzeugen (Python, optional wenn Basis-DXF benoetigt)
python tests/create_testbase.py
# 2. BricsCAD starten und Tests ausfuehren
# In BricsCAD: TESTRUN "kreisel"
# In BricsCAD: TESTRUN "vario"
# In BricsCAD: TESTRUN "omniflo"
# 3. Python-Validierung
pytest tests/ -v
```
### Nur Python-Validierung (ohne BricsCAD)
```bash
# Setzt voraus, dass output/ bereits erzeugt wurde
pytest tests/ -v
```
### Einzelnes Modul testen
```bash
pytest tests/test_kreisel.py -v
```
## Umgebungsvariablen
| Variable | Pfad | Beschreibung |
|---|---|---|
| `DXFM_TESTS` | `<DXFMAKRO>/tests` | Test-Wurzelverzeichnis |
| `DXFM_TESTDATA` | `<DXFMAKRO>/tests/testdata` | JSON-Testdefinitionen |
| `DXFM_TESTOUT` | `<DXFMAKRO>/tests/output` | Generierte Ergebnisse |
| `DXFM_TESTREF` | `<DXFMAKRO>/tests/reference` | Abgenommene Referenzen |
## Abhaengigkeiten
### Python (tests/requirements.txt)
```
ezdxf>=1.0
pytest>=7.0
```
### AutoLISP
- SSG_LIB muss geladen sein (ssg_load.lsp)
- `ssg_testrunner.lsp` wird manuell oder via on_start geladen
## Modulspezifische Testfaelle
### Kreisel (kreisel_tests.json)
| Test-ID | Beschreibung | Params |
|---|---|---|
| KR_Horiz_ObenUnten | Horizontaler Kreisel, oben nach unten | rot=270, art=STANDARD |
| KR_Horiz_UntenOben | Horizontaler Kreisel, unten nach oben | rot=90, art=PIN |
| KR_Vert_LinksRechts | Vertikaler Kreisel, links nach rechts | rot=0, art=PIN |
| KR_Vert_RechtsLinks | Vertikaler Kreisel, rechts nach links | rot=180, art=STANDARD |
| KR_Insert_Schraeg | Kreisel mit 10 Grad Drehung | rot=10, abstand=6000 |
### Vario (vario_tests.json)
| Test-ID | Beschreibung | Params |
|---|---|---|
| VF_Gerade_1Segment | Einzelnes gerades Segment | laenge=2000 |
| VF_Gerade_3Segmente | Drei gerade Segmente | laenge=6000 |
| VF_Gefaelle_Standard | Gefaellestrecke Standard | hoehe=500 |
| VF_Bogen_Links | Linksbogen | winkel=90 |
| VF_Bogen_Rechts | Rechtsbogen | winkel=-90 |
### Omniflo (omniflo_tests.json)
| Test-ID | Beschreibung | Params |
|---|---|---|
| OM_Bogen_90 | 90-Grad Bogen | winkel=90 |
| OM_Weiche_Links | Linksweiche | seite=L |
| OM_Weiche_Rechts | Rechtsweiche | seite=R |