aiguitest AI Vision-Modell · GUI Bildschirm · TEST Regression
Erprobt mit Ollama und qwen3-vl:8b

GUI-Tests in ganzen Sätzen.

AiGuiTest testet grafische Oberflächen auf einem Linux-Desktop über VNC. Statt Pixelkoordinaten und Referenzbilder zu pflegen, schreibst du, was du erwartest:

  • „Ist ein Terminalfenster mit Shell-Prompt geöffnet?“
  • „Klicke den Schließen-Button des Geany-Fensters.“
// aiguitest-run steps.json · Bestanden

// auf einen blick

Prompts statt Pixel.

Ein Vision-Sprachmodell sieht den Screenshot und beantwortet die Frage. Verschiebt sich ein Fenster oder ändert sich die Auflösung, bleibt der Test gültig.

01

Asserts als Fragen

Das Modell beschreibt erst, was es sieht, und urteilt dann streng.

02

Klickziele als Beschreibungen

Ein Template-Vergleich siebt die Kandidaten, das Modell wählt nur noch zwischen wenigen.

03

Erst explorativ, dann deterministisch

Prompts interaktiv in der Werkbank entwickeln, als JSON exportieren, im Testlauf ausführen, ohne Modell wiederholen.

04

Nachvollziehbar

Jeder Lauf legt Screenshots, Bildausschnitte und ein JSON-Protokoll ab; bei jedem Fehler wird der Bildschirm gesichert.

05

Schlank

Reines Python mit OpenCV, NumPy, requests und vncdotool. Kein Test-Framework nötig.

06

Lokales Modell

Jeder OpenAI-kompatible Endpunkt, erprobt mit Ollama und qwen3-vl:8b.

// der name ist der aufbau

Drei Teile. Nur einer davon braucht eine GPU.

Das Modell kann auf einem anderen Rechner laufen. AiGuiTest selbst läuft auf jeder Maschine mit Python.

AI

Vision-Modell

Jedes Vision-Modell hinter einer OpenAI-kompatiblen /chat/completions-Schnittstelle. Screenshots gehen auf 1280 px verkleinert hin, Koordinaten werden automatisch zurückgerechnet; temperature=0, seed=1.

GUI

Bildschirm statt Schnittstelle

Das Zielsystem ist ein beliebiger X-Desktop mit VNC-Server (RFB). AiGuiTest holt Screenshots aus dem Framebuffer und schickt Tasten, Text und Klicks zurück – kein DOM, kein Accessibility-Baum.

TEST

Lauf mit Protokoll

Jeder Lauf schreibt Screenshots und run.json nach runs/<zeitstempel>/. Schlägt ein Schritt fehl, liegt error.png im Laufordner, und der Lauf endet mit Exit-Code 1.

// so funktioniert es

Ein Schritt, drei Wege.

Für jede Prüfung geht ein verkleinerter Screenshot mit einem Prompt an das Vision-Modell; die Antwort ist JSON.

Tasten und Text brauchen kein Modell. Ein assert fragt wiederholt, bis das Urteil passt – oder bis nach 20 s der Timeout greift.

// arbeitsablauf

Erst explorativ, dann deterministisch.

Prompts entstehen im Gespräch mit dem Modell. Wiederholt wird ohne.

  1. ErkundenModell: ja

    In der Werkbank

    aiguitest-workbench – Prompts ausprobieren, mit -n 5 jeden fünfmal laufen lassen und so die Stabilität messen, dann export steps.json. Das Passwort schreibt der Export nicht mit.

  2. AusführenModell: ja

    Als Testlauf

    aiguitest-run --steps steps.json – Testlauf mit Protokoll in runs/<zeitstempel>/. Exit-Code 0 bestanden, 1 fehlgeschlagen (mit error.png), 2 keine VNC-Verbindung.

  3. WiederholenModell: nein

    Ohne Modell

    aiguitest-run --replay runs/<zeitstempel> – dieselben Tasten, Texte und click-Schritte per Template-Matching. Asserts und click_marks werden dabei übersprungen.

vnc-host::5901 — Framebuffer
coder@test1: ~×coder@test1:~$untitled - Geany×Datei Bearbeiten Suchen AnsichtThis is Geany 2.0
$ ./start.sh aiguitest-run steps.json
kein Ergebnis

// praxis

Links entsteht der Test, rechts liegt er im Repository.

Die Werkbank ist eine Kommandoschleife. Die Pfeiltasten-History bleibt in ~/.aiguitest_history erhalten.

./start.sh aiguitest-workbench
> key ctrl-alt-t
> ask Ist ein Terminalfenster geöffnet?
  [1] ok=True | Ein Terminalfenster mit Shell-Prompt ist sichtbar.
> keep terminal_offen
> marks der Schließen-Button (X) des Terminal-Fensters --needle images/close.png
  2 Kandidaten  [Needle images/close.png: 2 von 60, bester Score 1.000]
  -> Nummer 1, Mitte (531,138)
> click
> keep terminal_schliessen
> export steps.json

Ohne Modell: --fake. Gegen ein PNG statt gegen VNC: --image screen.png.

steps.json
{
  "name": "Geany starten und wieder schließen",
  "vnc": { "server": "vnc-host::5901" },
  "steps": [
    { "type": "key", "name": "terminal öffnen", "key": "ctrl-alt-t" },
    { "type": "type", "text": "geany &" },
    { "type": "key", "key": "enter" },
    { "type": "screenshot", "name": "nach_dem_start" },
    { "type": "assert", "prompt": "Ist das Fenster des Texteditors Geany geöffnet?" },
    { "type": "click_marks",
      "prompt": "der Schließen-Button (X) in der Titelleiste des Geany-Fensters",
      "needle": "images/close.png" },
    { "type": "assert", "prompt": "Ist das Geany-Fenster noch sichtbar?",
      "expected": false }
  ]
}

expected: false prüft das Gegenteil – „Fenster ist jetzt weg“.

key und type tragen sich selbst in die Liste ein. export schreibt immer die ganze Liste; einzelne Schritte für eine bestehende Datei holt man mit json. Ältere Dateien mit deutschen Schlüsseln (schritte, typ, erwartet) werden weiterhin gelesen.

// vitalwerte

Was im Betrieb zählt.

Gemessen, nicht versprochen.

0

Modellaufrufe im Replay

205

Token für einen Klick, wenn ein Needle vorher siebt

4/4

Kontrollläufe richtig, auch mit vertauschtem Ziel

20 s

fragt ein Assert nach, bevor er fehlschlägt

// warum needles

Zwischen zwei Kandidaten entscheiden kann es.

Ein Vision-Modell ist schlecht darin, Pixelkoordinaten zu schätzen, und schlecht darin, aus 60 nummerierten Kästen den richtigen zu finden. Gemessen an einem Desktop mit Terminal und Geany, Ziel: das × des Geany-Fensters.

WegKandidatenErgebnisToken
Box direkt vom Modelldaneben, teils außerhalb des Bildes1965
nummerierte Kandidaten60keine Antwort2942
nummerierte Kandidaten mit Needle2richtig205

Ein Needle ist ein kleiner Bildausschnitt des gesuchten Elements, etwa ein Schließen-Knopf. Der Template-Vergleich beantwortet zuverlässig „ist das ein Schließen-Knopf?“, das Modell zuverlässig „in welchem Fenster?“. Vier von vier Kontrollläufen trafen richtig, auch mit vertauschtem Ziel.

// grenzen und hinweise

Was AiGuiTest nicht kann.

Steht hier, weil es sonst im ersten Projekt auffällt.

  • Modellaufrufe sind langsam.Je nach Hardware mehrere Sekunden pro Assert. Für schnelle Wiederholungen gibt es --replay.
  • Direkte Koordinaten vom Modell sind unzuverlässig.find und click liegen oft Dutzende Pixel daneben. Für Klicks click_marks mit Needle nehmen.
  • Needles hängen von Theme und Auflösung ab.Pro Widget-Art braucht es einen, bei anderem Fensterstil einen neuen.
  • Höchstens 60 Kandidaten.Von oben nach unten gezählt. Elemente weit unten im Bild erreicht click_marks womöglich nicht; prüfen lässt sich dort trotzdem mit assert.
  • Gleich aussehende Elemente.Das × zweier Fenster unterscheidet der Template-Vergleich nicht – das entscheidet das Modell über die Beschreibung, oder ein Needle mit mehr Kontext.
  • Replay prüft nicht.Wiederholt werden Tasten, Text und click-Schritte. Asserts und click_marks werden übersprungen.
  • Denkende Modelle brauchen Token-Luft.qwen3-vl verbraucht rund 2000 Token für sein Reasoning; AiGuiTest erlaubt deshalb 4000.

// einordnung

Die Nachbarn können jeweils etwas, das AiGuiTest nicht kann.

Wenn du ein DOM hast, nimm Playwright. Der Fall hier ist der andere.

 AiGuiTestos-autoinstSikuliXMidscene
Zugriff aufs Systemnur RFBnur RFBlokal oder RFBBrowser, Android
Prüfungenin WortenNeedlesBild, OCRin Worten
Modell im CI-Lauffür Asserts; Replay ohneentfälltentfälltja
InferenzOpenAI-kompatibel, lokal erprobtentfälltentfälltlokal oder Cloud
Gedacht fürX-Desktops über VNCBetriebssystemeDesktopWeb

Die Needles kommen bei AiGuiTest nicht an die Stelle des Urteils, sondern davor: sie sieben die Klickkandidaten. Geurteilt wird in Sätzen – deshalb überlebt ein Test, wenn sich ein Fenster verschiebt.

// faq

Häufige Fragen.

Brauche ich eine GPU?

Für das Modell ja, praktisch gesehen. AiGuiTest selbst läuft auf jeder Maschine mit Python; das Modell kann auf einem anderen Rechner laufen.

Funktioniert es mit anderen Modellen?

Mit jedem Vision-Modell hinter einer OpenAI-kompatiblen /chat/completions-Schnittstelle. Erprobt ist qwen3-vl:8b über Ollama.

Kann ich Tests ohne Modell in CI laufen lassen?

Teilweise: --replay spielt Tasten und Klicks per Template-Matching nach, prüft aber keine Asserts. --selftest läuft ganz ohne VNC und Modell.

Warum Tastennamen statt Text bei key?

key sendet genau einen Tastendruck oder eine Kombination wie ctrl-alt-t. Für Text gibt es type.

// erstgespräch

Bevor die nächste Abnahme von Hand durchgeklickt wird.

Dreißig Minuten, ein Blick auf dein System, eine ehrliche Einschätzung – auch wenn sie lautet, dass os-autoinst für dich reicht.