Files
dxfmakros/doc/LispTests.md
T

300 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/DWG.
2. **Python** (pytest + ezdxf): Validiert die Ergebnisse automatisch gegen
erwartete Werte und optionale Referenzdaten.
```text
Python (pytest) AutoLISP (BricsCAD) Python (pytest)
=============== ==================== ===============
Testfall-Definitionen --> Ausfuehrung der --> Validierung:
als JSON bereitstellen LISP-Funktionen - JSON-Ergebnisse
+ DXF/DWG + results.json - DXF-Geometrie
- Referenz-Vergleich
```
## Verzeichnisstruktur
```text
tests/
├── alltests.json # Zentrale Testregistry (welche Module + Speicherformat)
├── test_run_all.lsp # C:SSG_RUN_ALL_TESTS - fuehrt alle Tests aus
├── test_kreisel.lsp # C:TEST_KREISEL - Kreisel-Testrunner
├── test_foerderer.lsp # C:TEST_FOERDERER - Variofoerderer-Testrunner
├── test_kseinaus.lsp # C:TEST_KSEINAUS - KreiselEinAus-Testrunner
├── test_omniflo.lsp # C:TEST_OMNIFLO - Omniflo-Testrunner
├── conftest.py # pytest Fixtures
├── test_kreisel.py # pytest Kreisel-Validierung
├── test_omniflo.py # pytest Omniflo-Validierung
├── create_testbase.py # Hilfsskript (optional, i.d.R. nicht benoetigt)
├── requirements.txt # Python-Abhaengigkeiten (ezdxf, pytest)
├── testdata/ # JSON-Testfall-Definitionen (versioniert)
│ ├── kreisel_tests.json
│ ├── foerderer_tests.json
│ └── omniflo_tests.json
├── reference/ # Abgenommene Referenzdaten (versioniert)
│ └── omniflo_export_reference.csv
└── output/ # Generierte Ergebnisse (nicht in Git)
├── kreisel_results.json
├── kreisel_tests.dxf
├── foerderer_results.json
├── foerderer_tests.dwg
├── kseinaus_results.json
├── omniflo_results.json
├── omniflo_tests.dxf
└── omniflo_export.csv
```
## Testregistry (alltests.json)
Die Datei `tests/alltests.json` ist die zentrale Registry aller Testmodule.
`SSG_RUN_ALL_TESTS` liest sie beim Start — die Testliste ist nicht hartcodiert.
```json
[
{ "name": "kreisel", "save": "dxf", "module": "KreiselInsert" },
{ "name": "foerderer", "save": "dwg", "module": "VarioFoerderer" },
{ "name": "kseinaus", "save": null, "module": "VarioFoerderer" },
{ "name": "omniflo", "save": "dxf", "module": "OmniModulInsert" }
]
```
| Feld | Typ | Bedeutung |
| --- | --- | --- |
| `name` | String | Basisname des Testmoduls (Pflicht) |
| `save` | `"dxf"` / `"dwg"` / `null` | Speicherformat der Zeichnung |
| `module` | String | LISP-Modul (wird von ssg-ensure geladen) |
Aus dem `name` werden alle Dateinamen abgeleitet:
| Element | Schema | Beispiel (`kreisel`) |
| --- | --- | --- |
| LISP-Datei | `tests/test_<name>.lsp` | `tests/test_kreisel.lsp` |
| BricsCAD-Befehl | `TEST_<NAME>` | `TEST_KREISEL` |
| Export-Funktion | `<name>:export-results` | `kreisel:export-results` |
| JSON-Ergebnis | `output/<name>_results.json` | `output/kreisel_results.json` |
| DXF/DWG-Datei | `output/<name>_tests.dxf/.dwg` | `output/kreisel_tests.dxf` |
## Schritt 1: Testfaelle definieren (JSON)
Jedes Modul hat eine eigene JSON-Datei in `tests/testdata/`. Format: **flaches JSON-Array**
(kompatibel mit `omni:load-json`). Kein Nesting, keine Wrapper-Objekte.
### Kreisel-Format (kreisel_tests.json)
```json
[
{
"id": "KR_Kreuz_Q1_0Grad",
"function": "insert",
"x": 500, "y": 500, "z": 2500,
"abstand": 2000,
"rotation": 0.0,
"typ": "STANDARD",
"expect_block_prefix": "KREISEL_",
"expect_hoehe": "2500",
"expect_kreiselart": "STANDARD"
}
]
```
Felder:
- `id` — Eindeutiger Testfall-Name
- `function``"insert"` oder `"connect"`
- Eingabeparameter: `x`, `y`, `z`, `abstand`, `rotation`, `typ`
- `expect_*` — Erwartete Ergebniswerte (fuer Python-Validierung)
### Foerderer-Format (foerderer_tests.json)
```json
[
{ "y_abstand": 400 },
{
"test_id": "VF_Auf_0",
"richtung": "Auf",
"deltaL": 7000,
"deltaH": 0
}
]
```
- Erster Eintrag (ohne `test_id`): Konfiguration (`y_abstand` zwischen Foerderern)
- Felder: `test_id`, `richtung` (`"Auf"` / `"Ab"`), `deltaL`, `deltaH`
- Ergebnisstatus: `GEBAUT`, `NICHT_GEBAUT`, `GEOMETRISCH_UNMOEGLICH`
### Omniflo-Format (omniflo_tests.json)
```json
[
{
"id": "821104025",
"type": "bogen",
"sivasnr": "821104025",
"x": 219.4, "y": 223.06,
"hoehe": 2000,
"drehung": 0.0,
"description": "APB 110 R 550/22,5 84/522",
"row": "Boegen 22.5"
}
]
```
## Schritt 2: LISP-Testrunner ausfuehren (BricsCAD)
### Alle Tests auf einmal
```lisp
(load (strcat (getenv "DXFMAKRO") "/tests/test_run_all.lsp"))
SSG_RUN_ALL_TESTS
```
`SSG_RUN_ALL_TESTS` liest `alltests.json` und fuehrt fuer jedes Modul aus:
1. Zeichnung leeren (ERASE ALL + PURGE x5)
2. `test_<name>.lsp` laden und `TEST_<NAME>` ausfuehren
3. JSON-Export: `<name>:export-results` aufrufen (immer)
4. Zeichnung speichern gemaess `save`-Feld (`"dxf"`, `"dwg"` oder kein Speichern)
5. Bei Fehler: weiter mit naechstem Test (Fehlerisolation)
### Einzeltest (z.B. nur Kreisel)
```lisp
(load (strcat (getenv "DXFMAKRO") "/tests/test_kreisel.lsp"))
TEST_KREISEL
(kreisel:export-results (strcat (getenv "DXFMAKRO") "/tests/output"))
```
### Ausgabe: results.json
```json
[
{
"test_id": "KR_Kreuz_Q1_0Grad",
"status": "GEBAUT",
"block_name": "KREISEL_STANDARD",
"insert_point": [500.0, 500.0, 2500.0],
"rotation": 0.0,
"actual_kreiselart": "STANDARD",
"actual_hoehe": "2500"
}
]
```
## Schritt 3: Python-Validierung (pytest)
```cmd
bin\run_tests.bat --runall
```
Oder einzelnes Testmodul:
```cmd
bin\run_tests.bat --runall test_kreisel.py
```
### test_kreisel.py
| Klasse | Prueft |
| --- | --- |
| `TestKreiselAttributes` | Attribute (KREISELART, HOEHE), Block-Prefixe, Status |
| `TestKreiselGeometry` | DXF-Bloecke, Positionen, Kreis-Radien (400mm) |
| `TestKreiselReference` | Block-Anzahl und -Typen gegen Referenz-DXF |
### test_omniflo.py
| Klasse | Prueft |
| --- | --- |
| `TestOmnifloExportUnit` | Mock-Export: Merkmale, Datentypen, Vollstaendigkeit (ohne BricsCAD) |
| `TestOmnifloExportCSV` | CSV aus BricsCAD: Header, Spalten, JSON-Merkmale |
Tests, deren Eingabedaten fehlen (kein BricsCAD-Lauf), werden automatisch
uebersprungen (`pytest.skip`).
## Schritt 4: Referenz-Management
```cmd
# Aktuelle Ergebnisse als neue Referenz speichern
bin\run_tests.bat --set-as-reference
```
Kopiert alle Dateien aus `output/` nach `reference/`. Nur bei bestandenen Tests verwenden.
## Modulspezifische Testfaelle
### Kreisel (kreisel_tests.json)
| Test-ID | Beschreibung | Params |
| --- | --- | --- |
| KR_Kreuz_Q1_0Grad | Standard Kreisel, 0 Grad | rot=0, z=2500, abstand=2000 |
| KR_Kreuz_Q2_90Grad | Standard Kreisel, 90 Grad | rot=90, z=2500, abstand=3000 |
| KR_Kreuz_Q3_180Grad | Standard Kreisel, 180 Grad | rot=180, z=2500, abstand=4000 |
| KR_Kreuz_Q4_270Grad | Standard Kreisel, 270 Grad | rot=270, z=2500, abstand=5000 |
| KR_Schraeg_Q1_30Grad | Standard Kreisel, schraeg | rot=30, z=3000, abstand=3000 |
| KR_Pin_Q1_0Grad | Pin-Kreisel, 0 Grad | rot=0, typ=PIN, z=1500 |
| KR_Pin_Q1_90Grad | Pin-Kreisel, 90 Grad | rot=90, typ=PIN, z=1500 |
| KR_Pin_Q1_30Grad_Schraeg | Pin-Kreisel, schraeg | rot=30, typ=PIN, z=1500 |
### Foerderer (foerderer_tests.json)
| Test-ID | Richtung | deltaL | deltaH |
| --- | --- | --- | --- |
| VF_Auf_0 | Auf | 7000 | 0 |
| VF_Auf_1000 | Auf | 7000 | 1000 |
| VF_Auf_2000 | Auf | 7000 | 2000 |
| VF_Auf_3000 | Auf | 7000 | 3000 |
| VF_Auf_4000 | Auf | 7000 | 4000 |
| VF_Auf_5000 | Auf | 7000 | 5000 |
| VF_Ab_0 | Ab | 7000 | 0 (GEOMETRISCH_UNMOEGLICH) |
| VF_Ab_1000 | Ab | 7000 | 1000 |
| VF_Ab_2000 | Ab | 7000 | 2000 |
| VF_Ab_3000 | Ab | 7000 | 3000 |
| VF_Ab_4000 | Ab | 7000 | 4000 |
| VF_Ab_5000 | Ab | 7000 | 5000 |
### Omniflo (omniflo_tests.json)
Testfaelle basieren auf echten Sivas-Nummern (Boegen und Zusatzmodule).
Beispiele: `821104025`, `821104025+0_B10090`, `821104025+0_B10091`, ...
## Umgebungsvariablen
Werden via `bin\setenv.bat` gesetzt. Fuer Tests relevant:
| Variable | Beschreibung |
| --- | --- |
| `DXFMAKRO` | Projektwurzel |
| `DXFM_TESTS` | tests/-Verzeichnis |
| `DXFM_TESTDATA` | testdata/-Verzeichnis |
| `DXFM_TESTOUT` | output/-Verzeichnis |
| `DXFM_TESTREF` | reference/-Verzeichnis |
| `DXFM_OMNIFLO` | Pfad zu Omniflo-DXF-Dateien |
## Abhaengigkeiten
### Python (tests/requirements.txt)
```text
ezdxf>=1.0
pytest>=7.0
```
### AutoLISP
- SSG_LIB muss geladen sein (Menue per `_MENULOAD` eingerichtet, siehe CLAUDE.md)
- `test_run_all.lsp` laedt die einzelnen Testrunner automatisch
## Neuen Test erstellen
1. **Testdaten**: `testdata/<modul>_tests.json` erstellen (flaches JSON-Array)
2. **LISP-Testrunner**: `test_<modul>.lsp` erstellen mit `c:TEST_<MODUL>` und `<modul>:export-results`
3. **Testregistry**: Eintrag in `alltests.json` hinzufuegen
4. **Python-Validierung** (optional): `test_<modul>.py` und Fixtures in `conftest.py`
Detailliertes Vorgehen und Codevorlagen: siehe `tests/README.md`.