9.5 KiB
9.5 KiB
runner-agents.md — test-samurai Runner-API
Ziel: Diese Datei beschreibt die öffentliche Runner-API, die ein neuer Runner implementieren muss, damit alle Commands vollständig unterstützt werden.
Modulform (Pflicht)
- Der Runner ist ein Lua-Modul, das eine Table mit Funktionen zurückgibt.
- Beispiel:
local runner = {}return runner
- Der Modulpfad in
runner_modulesmuss exakt zum Dateipfad unterlua/passen.- Beispiel:
lua/test-samurai-go-runner/init.lua->require("test-samurai-go-runner"). lua/init.luawärerequire("init")und ist kollisionsanfällig; vermeiden.
- Beispiel:
Pflichtfunktionen (volle Command- und Keymap-Unterstützung)
is_test_file(bufnr) -> boolean- Wird für die Runner-Auswahl genutzt.
find_nearest(bufnr, row, col) -> spec|nil, err?- Für
TSamNearest. spec.filemuss gesetzt sein.- Bei Fehler/kein Treffer:
nil, "reason"zurückgeben.
- Für
build_command(spec) -> command_spec- Für
TSamNearest.
- Für
build_file_command(bufnr) -> command_spec- Für
TSamFile.
- Für
build_all_command(bufnr) -> command_spec- Für
TSamAll.
- Für
build_failed_command(last_command, failures, scope_kind) -> command_spec- Für
TSamFailedOnly.
- Für
parse_results(output) -> results- Fallback-Parser für vollständigen Output.
output_parser() -> { on_line, on_complete }- Muss Streaming unterstützen (Listing wird live befüllt).
parse_test_output(output) -> table- Detail-Ausgabe pro Test (Detail-Float und
<cr>im Listing).
- Detail-Ausgabe pro Test (Detail-Float und
collect_failed_locations(failures, command, scope_kind) -> items- Quickfix-Unterstützung (Keymap
<leader>qn).
- Quickfix-Unterstützung (Keymap
Output-Parsing (Listing + Summary)
Beide Varianten müssen vorhanden sein:
parse_results(output) -> resultsresultsmuss enthalten:passes(Array von Namen)failures(Array von Namen)skips(Array von Namen)
- Optional:
display = { passes = {}, failures = {}, skips = {} }failures_all(für Streaming-Parser, um alle bisherigen Failures zu liefern)
- Wenn
displayfehlt, werdenpasses/failures/skipsdirekt im Listing angezeigt.
- oder
output_parser() -> { on_line, on_complete }on_line(line, state)kannresultsliefern (siehe oben).on_complete(output, state)kannresultsliefern (siehe oben).on_linemuss Ergebnisse liefern, damit das Listing-Float immer gestreamt wird.
Hinweis: parse_results darf intern output_parser().on_complete nutzen, aber beide Funktionen müssen existieren.
Listing-Gruppierung fuer Parent/Subtests
- Wenn Testnamen das Format
Parent/Subtestoder verschachteltParent/Sub/Subtesthaben und der Parent ebenfalls in den Ergebnissen vorhanden ist, gruppiert das Listing:- Parent kommt vor seinen direkten Kindern.
- Mehrstufige Subtests werden hierarchisch gruppiert (Parent -> Kind -> Enkel).
- Die Reihenfolge der Kinder folgt der Eingangsreihenfolge des Runners.
- Ohne Parent-Eintrag bleibt die normale Reihenfolge erhalten.
Detail-Output (TSamShowOutput / im Listing)
parse_test_output(output) -> table- Rückgabeform:
{ [test_name] = { "line1", "line2", ... } }
test_namemuss mitresults.*korrespondieren (gleiches Namensschema).
- Rückgabeform:
Quickfix-Unterstützung (Failures)
collect_failed_locations(failures, command, scope_kind) -> itemsitems: Array von Quickfix-Items{ filename = "...", lnum = <number>, col = <number>, text = "..." }
Erwartete Datenformen
command_spec:{ cmd = { "binary", "arg1", ... }, cwd = "..." }cmddarf nicht leer sein.cwdist optional; wenn nicht gesetzt, nutzt der Core das aktuelle CWD.
spec(vonfind_nearest):- Muss mindestens
fileenthalten, z. B.:{ file = "...", cwd = "...", test_name = "...", full_name = "...", kind = "..." }
- Muss mindestens
results(für Listing-Float + Keymaps):{ passes = { "Name1", ... }, failures = { "Name2", ... }, skips = { "Name3", ... } }- Optional:
display = { passes = { "DisplayName1", ... }, failures = { "DisplayName2", ... }, skips = { "DisplayName3", ... } } failuressteuert[ FAIL ]-Zeilen im Listing und wird von<leader>nf/<leader>pfgenutzt.
items(für Quickfix):{ { filename = "...", lnum = 1, col = 1, text = "..." }, ... }- Wird von
<leader>qnverwendet.
Keymaps (Datenlieferung)
<leader>nf/<leader>pf- benötigt
[ FAIL ]-Einträge im Listing. - Runner muss
results.failures(und optionaldisplay.failures) liefern.
- benötigt
<leader>qn- springt in die Quickfix-Liste.
- Runner muss
collect_failed_locationsimplementieren und gültigeitemsliefern.
<cr>im Listing- öffnet Detail-Float.
- Runner muss
parse_test_outputliefern und Testnamen konsistent zuresults.*halten.
Optional empfohlene Metadaten
name(String)- Wird in Fehlermeldungen und Logs angezeigt.
framework(String)- Wird zur Framework-Auswahl (z. B. JS) genutzt.
Prompt-Beispiel
"Erstelle mir anhand der runner-agents.md einen neuen Runner für Rust."
Minimaler Runner-Skeleton (Template)
local runner = {
name = "my-runner",
framework = "my-framework",
}
function runner.is_test_file(bufnr)
return false
end
function runner.find_nearest(bufnr, row, col)
return nil, "no test call found"
end
function runner.build_command(spec)
return { cmd = { "echo", "not-implemented" }, cwd = spec.cwd }
end
function runner.build_file_command(bufnr)
return { cmd = { "echo", "not-implemented" } }
end
function runner.build_all_command(bufnr)
return { cmd = { "echo", "not-implemented" } }
end
function runner.build_failed_command(last_command, failures, scope_kind)
return { cmd = { "echo", "not-implemented" }, cwd = last_command and last_command.cwd or nil }
end
function runner.parse_results(output)
return { passes = {}, failures = {}, skips = {}, display = { passes = {}, failures = {}, skips = {} } }
end
function runner.output_parser()
return {
on_line = function(_line, _state)
return nil
end,
on_complete = function(_output, _state)
return runner.parse_results(_output)
end,
}
end
function runner.parse_test_output(output)
return {}
end
function runner.collect_failed_locations(failures, command, scope_kind)
return {}
end
return runner
Checkliste für neue Runner
- is_test_file implementiert
- find_nearest implementiert (setzt
spec.file) - build_command implementiert
- build_file_command implementiert
- build_all_command implementiert
- build_failed_command implementiert
- parse_results implementiert
- output_parser implementiert (Streaming)
- parse_test_output implementiert
- collect_failed_locations implementiert
- command_spec
{ cmd, cwd }korrekt zurückgegeben
Projekt- und Prozessanforderungen
- Rolle: TDD-first Entwickler.
- Jede neue Funktion, jedes neue Kommando und jede Verhaltensänderung muss durch Tests abgesichert sein.
- Nach jeder Code-Änderung Tests via
bash run_test.shausführen und bei Fehlern korrigieren, bis alles grün ist.
- Nicht raten:
- Bei unklaren oder mehrdeutigen Anforderungen Arbeit stoppen und Klarstellung verlangen.
- TODO/NOTE im Code ist zulässig, stilles Raten nicht.
- Keine stillen Änderungen:
- Bestehende Features dürfen nicht unbemerkt geändert oder ersetzt werden.
- Notwendige Anpassungen zur Koexistenz mehrerer Features müssen klar erkennbar sein.
- Antworten immer auf Deutsch.
- Eine englischsprachige
README.mdist zu erstellen und wird bei Änderungen automatisch aktualisiert. - TDD-Vorgaben (aus
AGENTS.md) uebernehmen:- Neue Funktionen/Commands/Verhaltensaenderungen muessen getestet werden.
- Tests nach jeder Code-Aenderung ausfuehren.
- Im Runner erstellter Quellcode ist ebenfalls zu testen.
- Eine eigene
run_test.shwird im Runner-Repo angelegt.
- Eine Gitea-Action ist zu erstellen, die bei jedem Push die Tests ausfuehrt.
- Neovim wird per AppImage installiert (kein
apt). - Runner laeuft auf
gitea-act-runnermit Raspberry Pi 5 (ARM). - Beispiel (anpassbarer Workflow):
- Neovim wird per AppImage installiert (kein
name: tests
on:
push:
branches:
- "**"
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Neovim (AppImage)
run: |
curl -L -o nvim.appimage https://github.com/neovim/neovim/releases/download/v0.11.4/nvim.appimage
chmod +x nvim.appimage
sudo mv nvim.appimage /usr/local/bin/nvim
- name: Run tests
run: bash run_test.sh
Zusaetzliche Runner-Guidelines (framework-agnostisch)
- Testnamen-Konvention: Runner sollen eine konsistente, dokumentierte Full-Name-Bildung verwenden (z. B.
Parent/Subtest), inklusive Mehrfach-Nesting. Diese Konvention muss inresults.*,parse_test_outputundcollect_failed_locationsuebereinstimmen. - TSamNearest-Prioritaet: Falls moeglich, gelten folgende Regeln: Test-Block > Describe/Context-Block > File-Command. Das Verhalten muss getestet werden (Cursor im Test, zwischen Tests, ausserhalb von Describe/Context).
- Reporter-Payload-Schema: Wenn ein Custom-Reporter verwendet wird, soll dessen JSON-Payload dokumentiert und stabil sein (z. B.
{ name, status, file, location, output }), damit Parser/Quickfix/Detail-Output konsistent bleiben. - Failed-Only-Logik: Failed-Only muss auf den letzten Fehlermeldungen basieren und nur die fehlerhaften Tests erneut ausfuehren. Die Pattern-Strategie (z. B. Titel-only vs. Full-Name) muss getestet werden.
- CI-Installations-Snippet: Die Neovim-Installation in CI soll als „authoritative snippet“ behandelt werden und in Runner-Repos 1:1 uebernommen werden.