Testkonzept für unsere Lisp files überlegt
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
# 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 |
|
||||
Reference in New Issue
Block a user