- leaga_skills.ps1: expune skill-urile in ~/.claude/skills prin symlink (citit si de Claude Code, si de opencode), fara copiere - rutare zona->skill in reguli_lucru pct. 7, README, AGENTS.md; skill-ul devine proprietarul procedurii, docurile raman referinta conditionata - rec_skills.md: decizia, inventarul si cum se adauga un skill nou
7.9 KiB
7.9 KiB
name: roa-vfp-headless-test
description: Ruleaza si depaneaza teste VFP 9 fara IDE (headless) cu vfp9.exe -A -T "<script.prg>" din PowerShell, plus testele UI cu formular real, harness si screenshots. Foloseste skill-ul cand utilizatorul cere sa "ruleaza testul headless", sa "reproduca bug-ul", sa "scrie un test UI pentru formularul X", sa "depaneze eroarea la runtime", sa vada "de ce s-a agatat testul", sa interpreteze log.txt sau sa verifice ca testul chiar a rulat dupa un fix. Acopera lantul complet: init mediu auto, precompilare izolata, rulare cu timeout, watchdog pentru dialoguri native, raport de rezultate. Nu re-descoperi capcanele deja platite (SAFETY ON sub -A, .FXP/.ERR stale, INKEY(0) blocant, mock-uri in fisierul testat, DO...WITH prin referinta, dialog "View Parameter") - sunt distilate aici, iar sursa canonica e in COMUN\docs.
Rulare si depanare teste VFP headless (fara IDE)
Distinge "headless" (script .prg, fara UI vizibil) de testul UI cu formular real si screenshots. Ambele se lanseaza de aici; ambele au aceleasi capcane de baza. Fara log/png, testul nu exista.
Cand se foloseste
- "ruleaza testul headless", "ruleaza testul", "de ce s-a agatat testul".
- "reproduce bug-ul", "depaneaza eroarea la runtime", "am eroare in log.txt".
- "scrie un test UI pentru formularul X", "fa screenshots la pasul Y".
- Orice VFP care pare blocat: proces viu, CPU ~0, niciun rand nou in log.
- NU pentru editare de .vcx/.scx pe text sau cautare in binare - alte skill-uri.
Pasi
- Alege harness-ul de mediu dupa PROIECT:
test_init_env_auto_roafacturare.prgaici, variantele_roacont/_roagest/_acnpro/_roadefpentru celelalte produse. Init gresit incarca alt working copy si valideaza cod vechi, silentios. - Scrie scriptul: prima linie
SET SAFETY OFF+SET TALK OFF, apoi PATH/CLASSLIB/PROCEDURE ca in aplicatie, apoiON ERRORcare logheazaERROR(),MESSAGE(),PROGRAM(),LINENO()cu STRTOFILE si continua (fara WAIT WINDOW - headless nu are consola).QUITobligatoriu la final. - Replica doar liniile relevante din Show; pentru forme modale pune
WindowType = 0. - Precompileaza izolat, in proces copil:
_precompile.ps1. Fara astavfp9 -A test.prgdeschide intermitent editorul in loc sa ruleze (log gol). - Ruleaza cu timeout (comanda in
## Scripturi). Pentru dialoguri native, watchdog-ul. - Citeste DOAR esecurile din raportul de teste, nu logurile brute.
- Test UI:
.prgcuPUBLIC gcUILog, gcSyncDir, dummy-uri reale pe INFRASTRUCTURA (goExecutor, goApp, poAct, cursoarele cerute de Init),WindowType=0,Show(), pe fiecare pasDO HarnessStep WITH <n>, '<mesaj>', la finalDO HarnessDone WITH 'done'. Apoivfp_ui_harness.ps1 -TestPrg <test.prg> -Steps @('pas0',...); ruleaza-l in background sau cu timeout 300-600s si NU porni VFP separat (orchestratorul il lanseaza singur). - Inainte de orice asertiune, dovedeste ca noul cod e incarcat (
ClassLibrary= calea asteptata,CREATEOBJECTpe clasa noua intr-un TRY) - altfel validezi alt working copy.
Capcane
Condensat; fiecare are istoric scump in COMUN\docs\depanare_testare_vfp.md (sec. 6-7) si
COMUN\docs\testare-ui-vfp.md. Consulta-le inainte sa schimbi scriptul sau sa invinuiesti codul.
-Asi-Tsunt obligatorii amandoua: fara-Tprocesul sta pe splash, simptom identic cu o eroare de compilare.-Aignora config.fpw si porneste SAFETY ON.- SAFETY ON sub
-A: primulSTRTOFILE/COMPILEpeste fisier existent scoate dialogul modal "overwrite?" si agata pana la timeout (proces viu, pare agatat).SET SAFETY OFFprima linie; logheazaSET("SAFETY")siSET("RESOURCE")la start. - ON ERROR: dupa RETURN executia CONTINUA => o singura cauza produce CASCADA. PRIMA eroare din secventa e cea reala; 1940/1939 pe WITH/ENDWITH e zgomot. Erorile din TRY/CATCH nu ajung in log.
.FXP/.ERRstale agata reluarea chiar dupa fix, sub ACELASI nume (CPU=0, Responding=True, nimic in log; seamana cu blocaj de retea). Sterge-le la fiecare reluare sau da nume nou. Verifica daca.ERRe de la rularea asta, nu de la una anterioara.INKEY(0, ...)nu e poll, e asteptare NELIMITATA: timerii VFP nu se declanseaza, nimic nu poate debloca din interiorul procesului. FolosesteINKEY(0.01, 'H').- Mock in ACELASI fisier cu functia apelata NU e prins de
SET PROCEDURE ... ADDITIVE: pune mock-ul pe functia pe care o apeleaza codul TESTAT, nu pe capatul lantului; proba ca mock-ul a castigat, INAINTE de actiunea care poate deschide dialog. DO ... WITHpaseaza PRIN REFERINTA si variabila devine invizibila sub numele ei => dialog nativ "View Parameter" blocant, fara log si fara eroare. Paranteze:DO proc WITH (gnAn), (gnLuna).- Hung vs slow: proces viu + CPU ~0 + niciun rand nou in log = asteapta un dialog sau un fisier
(exista
.ERR?; enumera ferestrele cuEnumWindows/GetWindowThreadProcessId;-SyncDirnepasat => semafoare asteptate in alt folder). CPU mare = inca ruleaza. Urmareste mtime-ul log-ului, nu "log ne-gol" (un vfp9 zombi tine log stale). - Timeout: rulari intermediare ~90s/test, pauza 0.5s intre pasi; retry NUMAI la "start ratat", nu la "start lent" (la rece, zeci de classlib-uri). Fara suite in paralel - harness-ul omoara instantele vfp9 proprii, filtrate pe linia de comanda.
- Alte capcane UI, pe scurt: fara
SELECT-SQLpe cursorul legat de grid;ZAP(nuDELETE ALL) pe cursorii ceruti de Init; cursorii cu EXACT indecsii fluxului real;ALLTRIM(camp) == 'lit'; variabile care nu colizioneaza cu functii built-in (loCk->LOCK()); assert pe starea de DUPA resincronizarea formularului;_SCREEN.ActiveFormnu merge headless, foloseste_SCREEN.Forms. - Testele exerseaza fluxul REAL al utilizatorului; popularea directa a cursoarelor da PASS fals.
- Nu injecta input real (
keybd_event/SendInput) - masina e partajata; dismiss-ul se face doar cu mesaje Windows tintite pe handle (watchdog-AutoDismiss).
Criterii de acceptare si dovada
Fara dovada, testul NU s-a rulat. "Gata" nu se accepta pe baza ca procesul a terminat.
- Headless: log-ul arata numarul de PASS/FAIL si PRIMA eroare reala (nu cascada), plus
SET("SAFETY")/SET("RESOURCE")la start siQUITla final. Dovada = calea log-ului + extractul de esecuri dinraport_teste.ps1. - UI: PNG-uri
screenshots\step_<n>_<eticheta>.pngpentru fiecare pas si semaforul final/done.txt;ClassLibrarydovedeste ca s-a incarcat codul corect. - Un test care "trece" dar valideaza alt working copy, sau care populeaza direct cursorii in loc sa treaca prin fluxul real, e PASS fals - echivalent cu un esec.
- Bug: dovada e log-ul cu eroarea + linia, INAINTE de fix; dupa fix, exact aceeasi comanda da PASS. Fara ambele rulari, bug-ul nu e inchis.
Scripturi
Toate in D:\ROA\ROAFACTURARE\COMUN\utile\Teste\:
D:\ROA\ROAFACTURARE\COMUN\utile\Teste\vfp_ui_harness.ps1- orchestrator UI:powershell -File vfp_ui_harness.ps1 -TestPrg <test.prg> -Steps @('pas0','pas1').D:\ROA\ROAFACTURARE\COMUN\utile\Teste\watchdog_vfp.ps1- dialoguri native:powershell -File watchdog_vfp.ps1 -Script <test.prg> -AutoDismiss(captura PNG + text).D:\ROA\ROAFACTURARE\COMUN\utile\Teste\_precompile.ps1- precompilare izolata, rulata in proces copil (Start-Process -Wait).D:\ROA\ROAFACTURARE\COMUN\utile\Teste\raport_teste.ps1- sumar PASS/FAIL din loguri.- Comanda headless, lansata din PowerShell cu timeout:
vfp9.exe -A -T "<script.prg>" <param>, cu$p.WaitForExit(120000)si$p.Kill()daca nu iese. - Mediu:
D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto_roafacturare.prg. - Handshake UI:
ui_harness.prg,mock_amessagebox.prg(incarcate cuSET PROCEDURE ... ADDITIVE).
Referinta (doar la nevoie)
- Doar daca depanezi headless sau lucrezi la harness UI, citeste
COMUN\docs\depanare_testare_vfp.md(sec. 6-7) siCOMUN\docs\testare-ui-vfp.md.