274 lines
7.7 KiB
Markdown
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 |
|