Zurück zum Blog

Side Project ·

Einen RAG-Chatbot testen: Architektur, Strategie und Umsetzung

Das Testen von Konversationsschnittstellen mit Retrieval-Augmented Generation (RAG) bringt eigene Herausforderungen mit: LLM-Antworten sind nicht-deterministisch, dynamische UI-Widgets kommunizieren über Parent-Child-Iframe-Grenzen hinweg, und Tests gegen Live-API-Endpoints riskieren, Kontingente zu erschöpfen oder Betriebskosten aufzublähen.

Quellcode: github.com/pdaszko/sa-chatbot

Dafür haben wir ein dreistufiges Test-Framework für Szkolenia Skin Atelier implementiert. Es trennt schnelle Offline-Unit-Checks, Live-Qualitätsprüfungen der KI und browserbasierte End-to-End-(E2E-)Automatisierung.

  • Vitest für schnelle, isolierte Unit- und Integrationstests mit TypeScript-Support.
  • Playwright für Cross-Browser-E2E-Automatisierung und visuelle Regressionstests.
  • Google Gemini API für Live-Qualitätsbewertung der KI-Antworten und semantische Assertions.
  • Eigene Test-Runner, um Vitest von Playwright zu isolieren und Namespace-Kollisionen zu verhindern.

Die dreistufige Testarchitektur

1. Offline-Unit- & Integrationstests (Vitest)

Offline-Tests laufen in unter 500 Millisekunden und kosten 0,00 $. Sie prüfen die Kern-Anwendungslogik, eigene Rate-Limiter und gemockte Routing-Handler.

  • Rate-Limit-Tests (test/unit/rate-limit.test.ts): nutzt Fake-Timer, um zu beweisen, dass der Sliding-Window-IP-Limiter genau 10 Anfragen pro Minute erlaubt, die 11. mit HTTP 429 blockiert und den Zugriff nach Ablauf des Fensters wieder freigibt.
  • Vektor-Mathematik-Validierung (test/unit/rag-retrieval.test.ts): stellt sicher, dass identische Vektoren 1.0 ergeben, orthogonale 0.0 und entgegengesetzte -1.0.
  • Mock-API-Integration (test/unit/gemini-mock.test.ts): mockt das ai-Paket und Nodemailer und verifiziert, dass die Chat-API Kontext abruft, Prompts baut und Lead-E-Mails versendet — ohne echte Netzwerkaufrufe.

2. Live-Qualitätstests der KI (Vitest)

Diese Tests sprechen die echte Google Gemini API an. Da LLM-Ausgaben variieren, nutzen wir semantische Assertions statt exakter String-Vergleiche.

  • Compliance-Verifikation (test/live/gemini-live.test.ts): streamt Gemini-Output, parst SSE-JSON und prüft, dass die Antwort auf Polnisch verfasst ist und die geforderten Links zu Schulungsprogrammen enthält.
  • Semantische Ähnlichkeitsprüfung (test/live/gemini-live.test.ts): vergleicht Antwort-Embeddings mit einem Golden Standard und besteht nur, wenn die Cosine Similarity über 0.75 liegt.

3. Playwright-E2E-Browsertests (Playwright)

E2E-Tests starten die Next.js-App auf Port 3001 und prüfen visuelle Layouts, responsives Viewport-Verhalten und Parent-Child-Iframe-Kommunikation.

  • Theme-Farb-Verifikation (test/e2e/chatbot-ui.spec.ts): liest CSS-Eigenschaften aus dem DOM, um Markenfarben und Chat-Bubble-Styles zu verifizieren.
  • Iframe-Resizing & Messaging (test/e2e/chatbot-ui.spec.ts): stellt sicher, dass der Chat-Toggle das Iframe von 120x120px auf die korrekten Desktop-/Mobile-Viewport-Maße vergrößert.
  • Konversations-Flows (test/e2e/chatbot-ui.spec.ts): simuliert eine Anfrage, verifiziert die Nutzer-Bubbles und prüft den Lade-Indikator.

Runner-Konfiguration & Isolation

Um Konflikte zwischen Test-Runnern zu vermeiden, haben wir Vitest von Playwright isoliert. Playwright verwendet einen eigenen globalen test-Namespace — wird er in Vitest geladen, kann die Suite abstürzen.

  • Die Default-Konfiguration zielt nur auf test/unit und schließt test/e2e aus.
  • Die Live-Test-Trennung nutzt vitest.live.config.ts, damit kostenpflichtige KI-Checks nicht während lokaler Unit-Watches laufen.

Befehle und Skripte

BefehlZielZweck
npm run testtest/unit/Führt Offline-Unit- und Integrationstests einmalig aus.
npm run test:unit:watchtest/unit/Führt Offline-Unit-Tests im Watch-Modus aus.
npm run test:livetest/live/Führt Live-KI-Evaluationstests aus.
npm run test:e2etest/e2e/Führt Playwright-Browser-Automatisierungstests aus.
npm run test:allAlleFührt Unit-, Live- und E2E-Suiten nacheinander aus.