Tests und Teststatus
Stand: 2026-10-20. Dieses Dokument trennt klar zwischen automatisiert getestet, live gegen die laufende Docker-Instanz geprĂŒft, mit echter Hardware geprĂŒft und nicht getestet.
Testsuiten
Abschnitt betitelt âTestsuitenâ| Suite | Ort | Braucht | Ergebnis |
|---|---|---|---|
| Unit | backend/tests/unit |
nichts | 142 bestanden |
| Audio mit echten Modellen | backend/tests/audio |
Modelle (JUSTAI_TEST_MODELS_DIR) |
9 bestanden; test_speaker.py schlÀgt in etwa 1 von 4 LÀufen fehl (Piper-Synthese ist zufÀllig, fremde Stimme dann 0,49 statt < 0,45) |
| Datenbank | backend/tests/db |
PostgreSQL + pgvector (JUSTAI_TEST_DATABASE_URL) |
3 bestanden |
| End-to-End | backend/tests/e2e |
laufende Instanz (JUSTAI_E2E_URL, JUSTAI_E2E_PASSWORD), Gemini |
13 bestanden (siehe Hinweis) |
| Beispiel-Plugin | plugins/example-weather/tests |
nichts | 6 bestanden |
| Frontend | frontend |
Node | tsc und ESLint fehlerfrei |
| Statische Analyse | ganzes Repo | â | ruff fehlerfrei, mypy --strict fehlerfrei (Backend, SDK, Sandbox) |
uv run pytest backend/tests/unituv run python scripts/fetch_models.py .modelsJUSTAI_TEST_MODELS_DIR=$PWD/.models uv run pytest backend/tests/audioJUSTAI_TEST_DATABASE_URL=postgresql+asyncpg://justai:pw@127.0.0.1:55432/justai_test uv run pytest backend/tests/dbJUSTAI_E2E_URL=http://localhost:8080 JUSTAI_E2E_PASSWORD=⊠uv run pytest backend/tests/e2euv run pytest plugins/example-weather/tests # getrennt aufrufen (eigene pytest-Konfiguration)cd frontend && npm run typecheck && npm run lintEine Test-Datenbank startet man z. B. mit
docker run -d --name j5-testdb -e POSTGRES_USER=justai -e POSTGRES_PASSWORD=pw -e POSTGRES_DB=justai_test -p 127.0.0.1:55432:5432 pgvector/pgvector:0.8.1-pg17.
Was die Suiten abdecken
Abschnitt betitelt âWas die Suiten abdeckenâ- Unit: Event-Bus (Isolation, Duplikate, Hop-Limit), Output Router (alle
Regeln), Tool-Executor (Rechte, BestÀtigung, Timeout, Fehler), Display-Komponenten,
Echo-Bausteine (Referenzpuffer, GCC-PHAT, Tracker), Wakeword-Arbitrierung (inkl.
spÀter Duplikate), Kalibrierung (Onset), KI-Router (Fallback, hÀngender Provider,
Cooldown, Rollen-Autokonfiguration), GesprÀchs-Zustandsautomat, Vision-Logik,
Automationsmodell (inkl. ErgÀnzung fehlender Typen), PTZ-Regelung, statische
PrĂŒfung generierten Codes, Prompts der Plugin-Erzeugung,
FakePluginContext(Jobs, Events, HTTP-Routen), fehlende Plugin-Einstellungen, Sprachsteuerung (PrivatsphĂ€re-Modus, Zuhörpause mit Wiedereinschalten), Login-Drosselung, Discovery-ZusammenfĂŒhrung. - Audio: SelbstgesprĂ€ch mit echten Modellen in einem simulierten Raum (AUDIO.md).
- DB: dauerhaftes Vergessen im GedÀchtnis (MEMORY.md).
- E2E: zwei simulierte RĂ€ume mit akustischem Echo, echte lokale STT/TTS/Wakeword, Gemini als LLM: GesprĂ€ch, Raum-Routing, kein Echo, Timeout, doppelte Wakewords, parallele GesprĂ€che, Display-Kopplung mit BestĂ€tigung, proaktive Automation, GesprĂ€ch fortsetzen (gleiche Stimme 0,82 â fortgesetzt, RĂŒckfrage âwie viele Einwohner hat sie?â richtig auf Rom bezogen; andere Stimme 0,26 â neues GesprĂ€ch), Sprech-Automation startet einen Dialog, Stimmprofil: aus echter GesprĂ€chssprache angelegt (3 Proben), beim nĂ€chsten âHey Jarvisâ mit gleicher Stimme erkannt (Ăhnlichkeit 0,75), andere Stimme nicht. Der Ablauf âim GesprĂ€ch anlegen lassenâ hat beim ersten Lauf funktioniert; Wiederholungen scheiterten am erschöpften Gemini-Kontingent (429), nicht an der Funktion. GerĂ€te-App: ein skriptgesteuertes Browser-GerĂ€t koppelt sich mit Mikrofon, Lautsprecher und Kamera, bekommt automatisch einen Endpoint mit 4 Rollen, liefert Snapshots; âHey Jarvisâ und eine Frage ĂŒber das WebSocket-Mikrofon starten ein GesprĂ€ch, die Antwort kommt als Audio beim GerĂ€t an.
Hinweis zu E2E: Die Suite nutzt das konfigurierte Cloud-LLM (Gemini). Am
2026-10-15 lieferte Gemini zeitweise gleichzeitig 429 (Kontingent erschöpft) fĂŒr
gemini-3.8-flash und 503 (Ăberlastung) fĂŒr den Fallback. In diesem Fall
antwortet der Assistent korrekt mit einer Fehlermeldung, und drei Tests schlugen
fehl. Die direkte Wiederholung bestand 5/5, obwohl im selben Zeitraum 8 weitere
429/503-Fehler ĂŒber die Fallback-Kette abgefangen wurden. FĂŒr stabile LĂ€ufe ein
lokales LLM als zusÀtzlichen Fallback eintragen.
Abnahmekriterien
Abschnitt betitelt âAbnahmekriterienâLegende: â nachgewiesen · đĄ teilweise (was fehlt, steht dabei) · âł offen.
| # | Kriterium | Status | Nachweis |
|---|---|---|---|
| 1 | GerĂ€teerkennung | â | Netzwerksuche findet die Tapo C200 in 6 s, schlĂ€gt den Tapo-Treiber mit Modell âC200â vor und erkennt sie als bereits angelegt. Eingerichtet zeigt sie die gemessenen FĂ€higkeiten (Video, Audio rein/raus, Snapshot). PTZ fehlt in der Liste, weil dafĂŒr das Cloud-Passwort fehlt. Das ist korrekt ermittelt, nicht geraten. Die C410 (Akku) war meist im Schlaf. |
| 2 | Raumzuordnung | â | Echte Hardware: C200 (Kamera, Mikrofon, Lautsprecher) als Endpoint âPoolhaus Kameraâ im Raum Poolhaus. E2E: kombinierte GerĂ€te pro Raum. |
| 3 | SprachgesprĂ€ch | â | Echte Hardware: âHey Jarvisâ an der C200 â Session â Antwort (Gemini Live) ĂŒber den Lautsprecher der C200. E2E: Pipeline-Modus mit Antwort im selben Raum. |
| 4 | Keine Echo-Schleife | â | Echte Hardware (C200): keine Selbstauslösung. Audio-Tests: Antwort enthĂ€lt absichtlich das Wakeword â kein Wake, kein durchgelassenes Echo. E2E: keine Echo-Turns im Transkript. |
| 5 | Timeout | â | Echte Hardware und E2E: Ende durch InaktivitĂ€t (end_reason = inactivity), danach ist wieder ein Wakeword nötig. |
| 6 | Keine falsche Raumausgabe | â | E2E: KĂŒchenlautsprecher bekommt kein einziges Frame, wenn im Wohnzimmer gefragt wird. Unit: Output-Router-Regeln. |
| 7 | Doppelte Wakewords | â | E2E: dasselbe Wakeword in zwei RĂ€umen (leiser in der KĂŒche) â genau eine Session, im lauteren Raum. Unit: Arbitrierung inkl. verspĂ€teter Duplikate. Mit zwei echten Mikrofonen nicht getestet (C410 nicht dauerhaft erreichbar). |
| 8 | Parallele GesprĂ€che | â | E2E: zwei RĂ€ume in getrennten Arbitrierungsgruppen fragen gleichzeitig, jeder bekommt seine Antwort. |
| 9 | Personenregistrierung | đĄ | Vorstellen per Sprache (identity.introduce), Einwilligung mit Nachweis und Registrierung mit QualitĂ€tsprĂŒfung sind implementiert; identity.register_face verlangt eine ausdrĂŒckliche BestĂ€tigung (Mechanismus unit-getestet). Offen: der Ablauf mit einer echten Person vor der Kamera. |
| 10 | Wiedererkennung | đĄ | YuNet/SFace sind im Container geladen (Plugin vision-opencv lĂ€uft, GesichtsprĂŒfung in der Vision-Pipeline aktiv); Abstimmung ĂŒber starke und schwache Treffer ist implementiert. Offen: Test mit echter Person. |
| 11 | PTZ-Tracking | đĄ | Regelung unit-getestet (Totzone, Schrittweite, Rate, Zielbindung, Heimkehr, manuelle Ăbersteuerung). Echte C200: manuelles Schwenken funktioniert (rechts und zurĂŒck, per Bildvergleich bestĂ€tigt). Offen: Verfolgen einer Person. |
| 12 | Erinnerung | â | Live: âMerk dir âŠâ in Session A, richtige Antwort in neuer Session B. Vergessen mit RĂŒckfrage; dauerhaft (DB-Test und live). |
| 13 | Automation | đĄ | Live: der Satz aus dem Kriterium (mit Personenname) legt eine korrekte Automation an. E2E: das Erkennungs-Event startet im richtigen Raum eine proaktive BegrĂŒĂung, once greift. Offen: Auslösung durch eine echte Gesichtserkennung (hĂ€ngt an 9/10). |
| 14 | Display-Ausgabe | â | E2E: Display im Wohnzimmer gekoppelt und gewĂ€hlt. Echter Browser: Dashboard mit Kurs, Chart und Tabelle gerendert. |
| 15 | Display-BestĂ€tigung | â | E2E: das Tool wartet nachweislich auf das ack. Echter Browser: ack nach dem Zeichnen; Hintergrundseite meldet sofort ânicht sichtbarâ, statt Erfolg vorzutĂ€uschen. |
| 16 | Provider-Wechsel | â | Live: Rolle conversation nur per Konfiguration auf einen neuen OpenAI-kompatiblen Endpoint umgestellt (Gemini ĂŒber dessen OpenAI-Schnittstelle); die Antwort kam laut Nutzungsprotokoll von oai:gemini-oai. Keine CodeĂ€nderung. Fallback bei Ăberlastung (503/429) im Betrieb beobachtet. |
| 17 | Plugin-Installation | â | Live: Zip hochgeladen â als untrusted in der Sandbox â Start ohne Rechte abgelehnt â Recht gewĂ€hrt â aktiv, Tool erscheint, der Assistent nutzt es â deaktiviert â Tool verschwindet. |
| 18 | Tool-Entwicklung | â | Live: âKalenderwoche und Wochentag zu einem Datumâ â Spezifikation, Code, Tests â statische PrĂŒfung â Tests in der Sandbox (2 bestanden) â Sicherheitsreview â Freigabe â der Assistent beantwortet âKW von 24.12.2026?â korrekt mit dem neuen Tool â Deaktivierung. Live (2026-10-20): âein Plugin, das alle 5 Minuten prĂŒft, ob es in Bozen zu regnen anfĂ€ngt, und Bescheid sagtâ â Plugin mit Tool, Hintergrundjob und Event-Typ; einmal ĂŒberarbeitet; freigegeben â lĂ€uft in der Sandbox, der Event-Typ plugin.gen-rain-monitor.rain_started steht im Katalog und wird fĂŒr Automationen angeboten. Offen: ein echter Regenbeginn, der eine Automation auslöst. |
| 19 | Neustart | â | docker compose down + up: RĂ€ume, GerĂ€te, Endpoints, Plugins (aktiv), Personen, Erinnerungen, Automationen, KI- und Systemeinstellungen identisch. ZusĂ€tzlich Backup in ein getrenntes Projekt wiederhergestellt. |
| 20 | Fehlerbehandlung | â | Live: die C410 ist meist offline, die C200 arbeitet unbeeinflusst. Neustarts einzelner Dienste: Medienserver â Kameras nach 2 s wieder da; Datenbank â API nach 3 s; Sandbox â Sandbox-Plugins nach 44 s automatisch neu gestartet. Ein fehlschlagendes Plugin (fehlende Rechte) wird failed markiert, alles andere lĂ€uft weiter. Gemini-Ăberlastung: Fallback statt Ausfall. Unit: Bus-Fehlerisolation, hĂ€ngende Provider. |
Weitere Live-PrĂŒfungen (2026-10-20)
Abschnitt betitelt âWeitere Live-PrĂŒfungen (2026-10-20)â- PrivatsphĂ€re-Modus per Sprache (Textchat an die C200): âschalte die Kamera ausâ â PrivatsphĂ€re-Modus an, direkt an der Kamera mit pytapo geprĂŒft; âwieder anâ â aus.
- Zuhörpause: âhör hier eine Minute nicht zuâ â Wakeword am Endpoint aus, eine einmalige Automation hat es nach 60 s wieder eingeschaltet und lief genau einmal.
- E2E mit englischem System-Prompt: 13/13 bestanden (Fragen auf Deutsch und Italienisch).
Was nur der Benutzer machen kann (offene Punkte)
Abschnitt betitelt âWas nur der Benutzer machen kann (offene Punkte)â- 9/10/13 mit echter Person: vor die C200 stellen, âIch bin âŠâ sagen, der Gesichtsregistrierung zustimmen. SpĂ€ter erneut vor die Kamera gehen; die BegrĂŒĂungs-Automation sollte dann auslösen.
- 11: Im GerÀt Tapo C200 das Tapo-Cloud-Passwort oder ein Kamerakonto
(Tapo-App â Kamera â Erweitert â Kamerakonto) eintragen, dann
ptz.follow. - Barge-in mit echter Hardware: Die C200 schaltet ihr Mikrofon wĂ€hrend der Wiedergabe stumm, damit ist Unterbrechen physikalisch unmöglich. FĂŒr einen Test braucht es ein GerĂ€t mit echtem Full-Duplex (z. B. USB-Freisprecheinrichtung).
- Display auf einem Fernseher: bisher nur im Desktop-Browser geprĂŒft.
- Installationsskript (
scripts/install.sh, 2026-10-16, als eigenes Compose-Projekt neben der laufenden Instanz): percurl ⊠| bashin leerem Ordner (klont von GitHub, Ports 8080/8443 belegt â 8081/8444, LAN-IP erkannt, zufĂ€lliges Passwort angezeigt und Anmeldung damit erfolgreich); interaktiv in einem Pseudo-Terminal (eigenes Passwort, Anmeldung erfolgreich,.envmit Rechten 600); erneuter Aufruf (behĂ€lt.env, baut neu). HTTPS ĂŒber die LAN-IP mit dem CA-Zertifikat geprĂŒft. Nicht getestet: Docker-Neuinstallation auf einem Rechner ohne Docker. - GerĂ€te-App auf echten Handys/Tablets: Setup-Seite, Kopplung und Einstellungskarte im Desktop-Browser geprĂŒft, der Medienweg per E2E-Test. Headless-Chrome mit simulierter Kamera/Mikrofon und strenger Autoplay-Regel: nach dem Koppeln und nach einem Neuladen ohne BerĂŒhrung kommen Kamerabilder und Mikrofon an; das Livebild (MJPEG) lĂ€uft in der Admin-UI. Echo- UnterdrĂŒckung des Browsers, Hintergrundverhalten mobiler Browser und die Zertifikatsinstallation auf Android/iOS sind noch nicht auf echten GerĂ€ten getestet.
Durch Live-Tests gefundene und behobene Fehler
Abschnitt betitelt âDurch Live-Tests gefundene und behobene FehlerâLive-PrĂŒfungen gegen die laufende Instanz haben Fehler gefunden, die keine Unit-Tests abgedeckt hatten:
| Fehler | Behebung |
|---|---|
| Vergessenes kam durch die GedĂ€chtnis-Extraktion der alten Session zurĂŒck | Grabsteine, DB-Test |
Dashboard stĂŒrzte nach dem Login ab (_cooldowns als Rolle in /api/ai/status) |
eigenes Feld, defensive UI |
âBegrĂŒĂe X das nĂ€chste Malâ: Modell lieĂ type weg und nutzte den Namen statt der ID; Antwort blieb leer |
Typen ergÀnzen, Namen auflösen, Validierungsdetails an das Modell, Ersatzantwort |
| Sandbox-Testlauf je nach Zufalls-Verzeichnisname nicht importierbar | fester Pfad, pythonpath |
| Generierter Klassenname umbenannt, Tests fanden ihn nicht | Alias statt Umbenennen |
| Zweites Tool-Projekt mit gleichem Namen brach ab (Unique-Constraint) | eindeutige Plugin-IDs |
âWo ist das nĂ€chste McDonaldâs?â: der Assistent behauptete, kein Internet zu haben, und lehnte auch auf zweimalige Bitte ab, ein Plugin zu bauen; der System-Prompt erwĂ€hnte tools.develop nicht, eine Websuche gab es nicht |
Google-Suche von Gemini neben den eigenen Tools (Realtime und Pipeline), Standort des Hauses in den Einstellungen und im Prompt, Prompt-Regel, tools.develop anzubieten und zu starten; Unit-Tests, E2E per Sprache (Realtime), live per Textchat |
| Plugin-Erzeugung brach ab (âReplacement index 0 out of rangeâ) nach der Ăbersetzung des Prompts | geschweifte Klammern im Prompt maskiert, Unit-Test |
| Tests generierter Plugins schlugen fehl (ââdictâ object is not callableâ): das Modell ĂŒbergab JSON direkt als HTTP-Route | FakePluginContext akzeptiert dict/list/str/Funktionen als Routen, Unit-Test |
| Deaktivieren der C200 hing ĂŒber 2 Minuten (GerĂ€t als deaktiviert markiert, Verbindungen blieben) | Supervisor.stop wartete unbegrenzt auf Tasks, die auf Abbruch nicht reagieren, und verschluckte dabei den eigenen Abbruch. Jetzt: höchstens 5 s, dann Warnung mit der Stelle, an der der Task hĂ€ngt; jeder Schritt beim Stoppen eines GerĂ€ts (Audio, Vision, Treiber, go2rtc) höchstens 10 s, langsame Schritte werden mit Namen geloggt. Live: Deaktivieren 0,2â0,3 s |
| Kameralautsprecher (C200) stumm, obwohl alle Bytes an der Kamera ankamen; auch nach go2rtc- und Kamera-Neustart. Eine frische zweite Verbindung und die Tapo-App waren hörbar | eigene, pro GesprĂ€ch neu geöffnete Lautsprecher-Verbindung (<stream>_talk), SchlieĂen nach 90 s Stille; ZustellprĂŒfung erkennt jetzt auch Kameraverbindungen, die go2rtc als Consumer fĂŒhrt (AUDIO.md). Testton danach technisch zugestellt (Login 4,1 s) |
| Erinnerung âin einer Viertelstundeâ wiederholte sich alle 5 s (18Ă in 1,5 min, dann erst durch das Limit von 20 LĂ€ufen pro Stunde gestoppt) | Der Zeitplaner prĂŒfte bei at-Triggern run_count an seiner zwischengespeicherten Kopie, die nur die Datenbank hochzĂ€hlte. Jetzt: einmalig ĂŒber den Auslösezeitpunkt, at-Automationen werden nach dem Lauf deaktiviert, Cache nach jedem Lauf neu geladen. Unit-Test und live geprĂŒft (1 Lauf, danach deaktiviert) |
| âHey Jarvis, wie spĂ€t ist es?â ohne Pause blieb unbeantwortet: Audio zwischen Wakeword und bereiter Session (1,4â1,7 s) wurde verworfen | behoben: Puffer pro Endpoint, Wiedergabe ab dem Wakeword mit VAD-Entscheidung Pause/keine Pause, Pipeline ignoriert Kurz-ĂuĂerungen; E2E in beiden Modi (AUDIO.md) |
Installation: mit geĂ€ndertem JUSTAI_HTTPS_PORT (z. B. 8444, weil 8443 belegt) lauschte der Core im Container auf 8444, Docker leitete aber auf 8443 weiter â HTTPS nicht erreichbar |
behoben: Container-Port fest 8443, JUSTAI_HTTPS_PORT nur noch Host-Port und Anzeige |
| GerĂ€te-App: Livebild in der Admin-UI ânicht verfĂŒgbarâ (fragte MP4 von go2rtc an, App-Kameras haben keinen Stream); nach dem automatischen Neuladen bei Updates keine Kamera/kein Mikrofon mehr, bis jemand tippt | behoben: MJPEG-Livebild, Selbststart, Ton per BerĂŒhrung nachholbar; im Browser geprĂŒft |
| Display: doppelte Achsenbeschriftung, âGesprĂ€châ-Anzeige durch Text-Chats, unklare Fehler bei unsichtbarer Seite, kein Neuladen nach Updates | behoben, im Browser geprĂŒft |
| Zeitzone der Einstellungen wurde von Automationen ignoriert; Schalter ohne Funktion in den Einstellungen | verdrahtet bzw. entfernt |
| Kein Schutz gegen Passwort-Raten, keine Security-Header | Drosselung, CSP u. a. |
| Discovery schlug fĂŒr Tapo den ONVIF-Treiber vor (ohne Lautsprecher) | herstellerspezifischer Treiber hat Vorrang |
| Nach einem Neustart von go2rtc blieben alle Kameras unerreichbar (Streams nur im Speicher) | Watchdog stellt Streams wieder her; live: 2 s |
| Erste Ausgabe nach einer Pause unhörbar (Kanal nach 2 min geschlossen, Neuaufbau zu langsam) | Kanal bleibt offen, Sprache wartet auf Bereitschaft |
| Ton blieb nach Kamera-Reconnect dauerhaft stumm (go2rtc holte ab, lieferte aber nicht an die Kamera) | ZustellungsprĂŒfung an go2rtc, automatischer Neuaufbau |
Bekannte InstabilitÀt
Abschnitt betitelt âBekannte InstabilitĂ€tâDie beiden Full-Duplex-Tests in backend/tests/audio sind nicht deterministisch,
weil Piper die Testsprache bei jedem Lauf leicht anders erzeugt. Im Mittel schlÀgt
etwa einer von drei bis sechs LÀufen fehl: mal wird eine echte Unterbrechung zu spÀt
erkannt, mal (seltener seit der Toleranz um die geschÀtzte Echoverzögerung) Echo als
Unterbrechung gewertet. Half Duplex, der Modus der C200, ist davon nicht betroffen.
Offen: reproduzierbare Testsprache und eine Abstimmung ĂŒber viele Varianten.
Nicht automatisiert getestet
Abschnitt betitelt âNicht automatisiert getestetâ- Konsolidierung des GedĂ€chtnisses (ZusammenfĂŒhren, WidersprĂŒche)
- Realtime-Modus (Gemini Live) nur manuell mit der C200, nicht in der E2E-Suite
- Plugin-AbhÀngigkeiten und Updates hochgeladener Plugins
- Retention-Job
- Lastverhalten mit vielen Kameras