Files
klangkiste/docs/acceptance-tests.md
2026-01-14 13:11:07 +00:00

583 lines
12 KiB
Markdown
Raw Permalink 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.
# Acceptance-Tests
## Zweck
Konsistenter Testkatalog basierend auf dem aktuellen Code. Alle Tests trennen Simulation und Hardware. Nicht implementierte Punkte sind explizit markiert.
## Voraussetzungen
- Repo-Root
- Python 3
- Box API fuer Simulation: `python3 box/main.py run`
- GUI optional: `cd gui/frontend && npm run dev`
- Backend optional: `cd gui/backend && npm run dev`
Hinweis:
- Sobald die Box gepairt ist, erfordern `/command` Aufrufe den Header `X-API-Token`.
## Schritt-fuer-Schritt
Die Tests koennen einzeln oder der Reihe nach ausgefuehrt werden.
---
# Lokale Box-Tests (L1-L10)
## Test L1: Box-Start & box_id
1) Ziel
- box_id wird einmalig erzeugt und bleibt stabil.
2) Voraussetzungen
- Simulation: `box/data/box.json` kann fehlen.
- Hardware: frischer Start.
3) Durchfuehrung Simulation / Emulation
- Box starten:
```
python3 box/main.py run
```
- Status lesen:
```
curl http://127.0.0.1:8000/status
```
- Datei pruefen:
```
cat box/data/box.json
```
4) Durchfuehrung Reale Box (Hardware)
- Box einschalten.
- Statusseite/API pruefen (sofern erreichbar).
5) Erwartetes Ergebnis
- `box_id` im Format `klangkiste-<10 chars a-z0-9>`.
- `box/data/box.json` bleibt stabil ueber Neustarts.
6) Abweichungen / Fehlersuche
- `box_id` fehlt: Schreibrechte in `box/data/` pruefen.
---
## Test L2: WLAN-Ersteinrichtung (Setup WebGUI)
1) Ziel
- WLAN-Profil per Setup UI anlegen.
2) Voraussetzungen
- Keine WLAN-Profile gespeichert.
3) Durchfuehrung Simulation / Emulation
- WLAN reset:
```
curl -X POST http://127.0.0.1:8000/command \
-H "Content-Type: application/json" \
-d '{"command":"wifi_reset"}'
```
- Setup UI oeffnen:
```
http://127.0.0.1:9000/setup
```
- SSID waehlen, Passwort eingeben, speichern.
- Status pruefen:
```
curl http://127.0.0.1:8000/status
```
4) Durchfuehrung Reale Box (Hardware)
- Nicht testbar mit aktuellem Code: kein echter AP/WLAN-Stack.
5) Erwartetes Ergebnis
- `wifi_state = WIFI_ONLINE`
- `connected_ssid` gesetzt
6) Abweichungen / Fehlersuche
- Setup UI nicht erreichbar: Port 9000 frei, Box laeuft.
---
## Test L3: Persistenz & Neustart
1) Ziel
- Resume und WLAN-Profile bleiben ueber Neustart erhalten.
2) Voraussetzungen
- WLAN-Profil vorhanden.
- Playback einmal gestartet.
3) Durchfuehrung Simulation / Emulation
- WLAN-Profil setzen:
```
curl -X POST http://127.0.0.1:8000/command \
-H "Content-Type: application/json" \
-d '{"command":"wifi_add_profile","payload":{"ssid":"HomeWiFi","password":"secret","priority":10}}'
```
- Playback starten:
```
curl -X POST http://127.0.0.1:8000/command \
-H "Content-Type: application/json" \
-d '{"command":"nfc_on","payload":{"uid":"UID_1"}}'
```
- Playback stoppen:
```
curl -X POST http://127.0.0.1:8000/command \
-H "Content-Type: application/json" \
-d '{"command":"nfc_off","payload":{"uid":"UID_1"}}'
```
- Box-Prozess neu starten.
- Status pruefen:
```
curl http://127.0.0.1:8000/status
```
4) Durchfuehrung Reale Box (Hardware)
- Nicht testbar mit aktuellem Code: kein echter WLAN-Stack.
5) Erwartetes Ergebnis
- `box/data/state.json` enthaelt Resume.
- `box/data/secrets.enc` existiert.
6) Abweichungen / Fehlersuche
- Resume fehlt: `box/data/state.json` pruefen.
---
## Test L4: HTTP API Status & Commands
1) Ziel
- /status und /command liefern Antworten und aendern Status.
2) Voraussetzungen
- Box laeuft.
3) Durchfuehrung Simulation / Emulation
- Status:
```
curl http://127.0.0.1:8000/status
```
- Command (vor Pairing -> 403 erwartet):
```
curl -X POST http://127.0.0.1:8000/command \
-H "Content-Type: application/json" \
-d '{"command":"play_pause"}'
```
4) Durchfuehrung Reale Box (Hardware)
- Gleich wie Simulation, sofern API erreichbar.
5) Erwartetes Ergebnis
- Vor Pairing: HTTP 403 fuer gesperrte Commands.
- Nach Pairing (mit Token): HTTP 200 und Status aktualisiert.
6) Abweichungen / Fehlersuche
- 400: Payload pruefen.
---
## Test L5: GUI-Steuerung
1) Ziel
- GUI steuert Box und zeigt Live-Status.
2) Voraussetzungen
- GUI laeuft auf 127.0.0.1:5174.
3) Durchfuehrung Simulation / Emulation
- GUI oeffnen, Buttons klicken.
- Status aendert sich innerhalb von 1s.
4) Durchfuehrung Reale Box (Hardware)
- GUI auf Box-IP ausrichten (spaeter).
5) Erwartetes Ergebnis
- `/status` aendert sich nach Commands.
6) Abweichungen / Fehlersuche
- GUI "Failed to fetch": `VITE_BACKEND_URL` pruefen.
---
## Test L6: Playback & NFC
1) Ziel
- NFC startet Playback.
2) Voraussetzungen
- Tags in `box/data/box.json`.
- Medien im Backend unter `gui/backend/media`.
3) Durchfuehrung Simulation / Emulation
```
curl -X POST http://127.0.0.1:8000/command \
-H "Content-Type: application/json" \
-d '{"command":"nfc_on","payload":{"uid":"UID_1"}}'
```
4) Durchfuehrung Reale Box (Hardware)
- NFC-Tag auflegen (spaeter).
5) Erwartetes Ergebnis
- `playback_state.state = PLAYING`
6) Abweichungen / Fehlersuche
- Tag fehlt: `box/data/box.json` pruefen.
---
## Test L7: Resume-Logik
1) Ziel
- Resume pro UID funktioniert.
2) Voraussetzungen
- Playback einmal gestartet.
3) Durchfuehrung Simulation / Emulation
- `nfc_on UID_1`, warten, `nfc_off UID_1`, dann `nfc_on UID_1`.
4) Durchfuehrung Reale Box (Hardware)
- NFC auflegen/abnehmen (spaeter).
5) Erwartetes Ergebnis
- Resume nutzt gespeicherte Position.
6) Abweichungen / Fehlersuche
- Resume = 0: `box/data/state.json` pruefen.
---
## Test L8: Rekursion & Ordnerstruktur
1) Ziel
- Rekursive Reihenfolge (DFS) ist korrekt.
2) Voraussetzungen
- Verschachtelte Ordner im Backend unter `gui/backend/media`.
3) Durchfuehrung Simulation / Emulation
- Tag auf `media/book_6` setzen, `nfc_on`.
4) Durchfuehrung Reale Box (Hardware)
- Medienstruktur auf Box kopieren (spaeter).
5) Erwartetes Ergebnis
- DFS-Reihenfolge, lexikografisch.
6) Abweichungen / Fehlersuche
- Reihenfolge falsch: Ordnernamen pruefen.
---
## Test L9: Offline-Szenarien (Box intern)
1) Ziel
- WiFi/Spotify-Status reagieren auf Commands.
2) Voraussetzungen
- Box laeuft.
3) Durchfuehrung Simulation / Emulation
- `wifi_reset` und `spotify_clear` ausfuehren.
4) Durchfuehrung Reale Box (Hardware)
- Nicht testbar mit aktuellem Code.
5) Erwartetes Ergebnis
- `wifi_state = WIFI_UNCONFIGURED`
- `spotify_status = NOT_CONFIGURED`
6) Abweichungen / Fehlersuche
- Status aendert sich nicht: `/status` pruefen.
---
## Test L10: Fehlerfaelle (Box intern)
1) Ziel
- Fehler setzen `last_error`.
2) Voraussetzungen
- Box laeuft.
3) Durchfuehrung Simulation / Emulation
```
curl -X POST http://127.0.0.1:8000/command \
-H "Content-Type: application/json" \
-d '{"command":"trigger_error","payload":{"type":"uid_unmapped"}}'
```
4) Durchfuehrung Reale Box (Hardware)
- Nicht testbar mit aktuellem Code.
5) Erwartetes Ergebnis
- `playback_state.last_error` gesetzt.
6) Abweichungen / Fehlersuche
- Kein Fehler sichtbar: `/status` pruefen.
---
# Backend/Pairing-Tests (A-J)
## Test A: Box-Erststart & Identitaet
1) Ziel
- box_id wird einmalig erzeugt.
2) Voraussetzungen
- Box gestartet.
3) Durchfuehrung Simulation / Emulation
- Siehe Test L1.
4) Durchfuehrung Reale Box (Hardware)
- Siehe Test L1.
5) Erwartetes Ergebnis
- box_id stabil.
6) Abweichungen / Fehlersuche
- Siehe Test L1.
---
## Test B: Announce -> neue Box erscheint im Backend
1) Ziel
- Box meldet sich beim Backend und erscheint als UNPAIRED.
2) Voraussetzungen
- Backend laeuft:
```
cd gui/backend
npm run dev
```
- Frontend laeuft:
```
cd gui/frontend
npm run dev -- --host 0.0.0.0 --port 5174 --strictPort
```
3) Durchfuehrung Simulation / Emulation
- Box starten:
```
python3 box/main.py run
```
- 30-60s warten (Announce-Intervall).
- Frontend-GUI oeffnen:
```
http://127.0.0.1:5174
```
- Optional: Backend-Storage pruefen:
```
sqlite3 gui/backend/db/klangkiste.sqlite "SELECT box_id, state, last_seen FROM boxes;"
```
4) Durchfuehrung Reale Box (Hardware)
- Box einschalten.
- Frontend-GUI oeffnen, Box sollte erscheinen.
5) Erwartetes Ergebnis
- Box erscheint als UNPAIRED in der Frontend-GUI.
- `gui/backend/db/klangkiste.sqlite` enthaelt `box_id` und `fingerprint`.
6) Abweichungen / Fehlersuche
- Keine Box sichtbar: Backend-URL in `box/data/box.json` pruefen.
- Backend nicht erreichbar: Backend-Prozess/Port 5001 pruefen.
---
## Test C: Mehrere Boxen gleichzeitig
1) Ziel
- Mehrere Boxen werden separat erkannt.
2) Voraussetzungen
- Mehrere Boxen mit unterschiedlichen `box_id`.
3) Durchfuehrung Simulation / Emulation
- Nicht testbar mit aktuellem Code: Box nutzt festen `box/data/`-Pfad und kann nicht mehrfach parallel laufen.
4) Durchfuehrung Reale Box (Hardware)
- Zwei physische Boxen einschalten.
- Frontend-GUI zeigt beide UNPAIRED an.
5) Erwartetes Ergebnis
- Zwei Eintraege mit unterschiedlichen `box_id`.
6) Abweichungen / Fehlersuche
- Duplikate: `box_id` doppelt? Factory-Reset pruefen.
---
## Test D: Pairing-Freigabe ueber Frontend-GUI
1) Ziel
- Pairing liefert API-Token und Box wird PAIRED.
2) Voraussetzungen
- Box erscheint als UNPAIRED in der Frontend-GUI.
3) Durchfuehrung Simulation / Emulation
- Frontend-GUI oeffnen:
```
http://127.0.0.1:5174
```
- Button "Pairen" klicken.
- API-Token via Backend-API abrufen:
```
curl -X POST http://127.0.0.1:5001/api/boxes/pair -H "Content-Type: application/json" -d '{"box_id":"<box_id>"}'
```
4) Durchfuehrung Reale Box (Hardware)
- Gleiches Vorgehen ueber Frontend-GUI.
5) Erwartetes Ergebnis
- Box erscheint in der gepaarten Liste.
- `api_token` wird an die Box ausgeliefert.
6) Abweichungen / Fehlersuche
- Pairing bleibt aus: `gui/backend/db/klangkiste.sqlite` pruefen.
---
## Test E: Verhalten vor Pairing (keine Steuerung erlaubt)
1) Ziel
- Vor Pairing werden Steuerbefehle blockiert.
2) Voraussetzungen
- Box UNPAIRED.
3) Durchfuehrung Simulation / Emulation
```
curl -i -X POST http://127.0.0.1:8000/command -H "Content-Type: application/json" -d '{"command":"play_pause"}'
```
4) Durchfuehrung Reale Box (Hardware)
- Gleicher Request gegen Box-IP.
5) Erwartetes Ergebnis
- HTTP 403 "pairing required".
6) Abweichungen / Fehlersuche
- Wenn 200: Pairing-Status und API-Token pruefen.
---
## Test F: Verhalten nach Pairing
1) Ziel
- Nach Pairing sind Commands erlaubt (mit Token).
2) Voraussetzungen
- Box PAIRED und api_token vorhanden.
3) Durchfuehrung Simulation / Emulation
```
curl -i -X POST http://127.0.0.1:8000/command -H "Content-Type: application/json" -H "X-API-Token: <api_token>" -d '{"command":"play_pause"}'
```
4) Durchfuehrung Reale Box (Hardware)
- Gleiches Vorgehen gegen Box-IP.
5) Erwartetes Ergebnis
- HTTP 200, Status aktualisiert.
6) Abweichungen / Fehlersuche
- 403: Token pruefen, Pairing-Status pruefen.
---
## Test G: Neustart vor/nach Pairing
1) Ziel
- Pairing-Status und Token bleiben ueber Neustart erhalten.
2) Voraussetzungen
- Box PAIRED.
3) Durchfuehrung Simulation / Emulation
- Box-Prozess stoppen, neu starten.
- Mit Token Command senden.
4) Durchfuehrung Reale Box (Hardware)
- Power cycle.
5) Erwartetes Ergebnis
- Box bleibt PAIRED, Token weiterhin gueltig.
6) Abweichungen / Fehlersuche
- Token fehlt: `box/data/secrets.enc` pruefen.
---
## Test H: Factory Reset -> neue Identitaet
1) Ziel
- Factory Reset erzeugt neue Identitaet.
2) Voraussetzungen
- Box einmal gestartet.
3) Durchfuehrung Simulation / Emulation
- Box stoppen.
- Dateien loeschen:
```
rm -f box/data/box.json box/data/state.json box/data/secrets.enc
```
- Box neu starten.
4) Durchfuehrung Reale Box (Hardware)
- Nicht testbar mit aktuellem Code: kein Reset-Mechanismus.
5) Erwartetes Ergebnis
- Neue `box_id`.
6) Abweichungen / Fehlersuche
- `box_id` bleibt gleich: Dateien nicht geloescht.
---
## Test I: Offline / Backend nicht erreichbar
1) Ziel
- Box laeuft weiter ohne Backend.
2) Voraussetzungen
- Box laeuft, Backend gestoppt.
3) Durchfuehrung Simulation / Emulation
- Backend stoppen.
- Playback starten (mit Token falls gepairt).
4) Durchfuehrung Reale Box (Hardware)
- Backend vom Netz trennen.
5) Erwartetes Ergebnis
- Lokale Playback-Logik laeuft weiter.
- Nicht testbar mit aktuellem Code: Backend markiert OFFLINE nicht.
6) Abweichungen / Fehlersuche
- Box stoppt: lokale Logs pruefen.
---
## Test J: Simulation vs. Hardware Unterschiede
1) Ziel
- Unterschiede klar dokumentieren.
2) Voraussetzungen
- Box laeuft in Simulation.
3) Durchfuehrung Simulation / Emulation
- WiFi/IP/Spotify/Audio sind Mock.
- Setup UI und API funktionieren lokal.
4) Durchfuehrung Reale Box (Hardware)
- Echte Backends notwendig (nicht implementiert).
5) Erwartetes Ergebnis
- Simulation laeuft ohne Hardware.
6) Abweichungen / Fehlersuche
- Hardware-Backends fehlen.