depanare_testare_vfp.md 226->118 linii, testare-ui-vfp.md 133->90. - regula SAFETY/dialog modal si -A -T erau enuntate de 3 ori -> o data - cele 3 capcane "proces agatat" -> un singur algoritm de diagnostic in 3 pasi - studiul de caz CNRCRT si detaliile ROAGEST (jtva_coloane2, achizitie_import) reduse la regula generala + pointer catre scriptul de test - reguli_lucru pct.4 ramane doar pointer, fara detaliile duplicate de mediu - sters docs/bash.exe.stackdump (fisier de gunoi, negitat) Masuratorile si datele concrete pastrate integral. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RqJ7D5ftMbChDyz5mpVkCd
96 lines
6.9 KiB
Markdown
96 lines
6.9 KiB
Markdown
# Testare UI VFP headless cu harness + screenshots
|
|
|
|
Harness reutilizabil pentru teste care afiseaza un formular REAL (cu dependinte dummy, fara
|
|
Oracle), executa actiuni si valideaza vizual prin capturi. Valabil pentru toate proiectele VFP
|
|
din suita ROA. Alternativa la `testare-vfp-mcp.md` (care porneste programul principal intreg);
|
|
capcanele generale de rulare headless (`-A -T`, SAFETY, script agatat) sunt in
|
|
`depanare_testare_vfp.md`.
|
|
|
|
Fisiere in `COMUN\utile\Teste\`: `vfp_ui_harness.ps1` (orchestrator generic, parametrizat),
|
|
`_precompile.ps1` (precompilare izolata), `ui_harness.prg` (proceduri de handshake),
|
|
`mock_amessagebox.prg` (mock dialog) — infrastructura sta in radacina `Teste\`; suitele stau in
|
|
subfoldere pe subiect. Exemplu complet: `achizitie_import\test_import_nota_ui.prg` + `.ps1`.
|
|
|
|
**REGULA (Marius, 17/07/2026): testele pe aplicatii frontend exerseaza fluxul REAL al
|
|
utilizatorului** — formularul/butonul/metoda pe care o apeleaza aplicatia, NU introducerea
|
|
directa a randurilor in cursoare/tabele. Popularea directa sare peste validari/filtre/efecte
|
|
laterale si da PASS fals (caz real: un articol "adaugat" direct in cursor trecea testul, dar
|
|
prin fluxul real nu se adauga deloc). Mock-urile raman permise doar pe INFRASTRUCTURA (Oracle,
|
|
dialoguri modale), nu pe pasii fluxului testat.
|
|
|
|
## Test UI nou in 5 pasi
|
|
|
|
1. `.prg` de test: `PUBLIC gcUILog, gcSyncDir`; `SET SAFETY OFF` + `SET TALK OFF` ca PRIMA
|
|
linie (vezi capcana a); `SET PATH/CLASSLIB/PROCEDURE` ca in aplicatie; incarca ULTIMELE
|
|
`ui_harness.prg` si (daca ai dialoguri) `mock_amessagebox.prg`, cu `ADDITIVE`.
|
|
2. Creeaza dummy-urile minime (`goExecutor` cu metode reale, `goApp` pt. `ReadIni`, `poAct`
|
|
pt. curs valutar) + cursoarele cerute de Init (RecordSource-urile grilelor).
|
|
3. Instantiaza clasa, `WindowType=0` (modeless - `Show()` pe modal nu returneaza), `Show()`,
|
|
`WindowState=2`.
|
|
4. Pe fiecare pas: fa actiunea, verifica efectul in date (PASS/FAIL cu helper local), apoi
|
|
`DO HarnessStep WITH <n>, '<mesaj>'` (scrie ready_n, asteapta cont_n de la orchestrator sau
|
|
auto-continua dupa ~30s). La final `DO HarnessDone WITH 'done'`.
|
|
5. `powershell -File vfp_ui_harness.ps1 -TestPrg <test.prg> -Steps @('pas0',...)`.
|
|
PNG-uri in `screenshots\step_<n>_<eticheta>.png`; log in `<test>_log.txt`.
|
|
|
|
## Capcane / deblocari (toate confirmate in sesiune)
|
|
|
|
a. **`SET SAFETY OFF` + `SET TALK OFF` inaintea primului `STRTOFILE`.** Cu SAFETY ON, scrierea
|
|
log-ului existent scoate un dialog modal care blocheaza rularea (proces viu, "instanta
|
|
moarta"). Cu TALK ON, `SUM`/`CALCULATE` isi echo-eaza rezultatele peste formular in
|
|
screenshots.
|
|
b. **Lansarea orchestratorului**: prin tool cu timeout implicit (~120s) e omorat inainte de
|
|
final. Ruleaza-l in background + asteapta `done.txt`, sau timeout 300-600s. NU porni VFP
|
|
separat de orchestrator - si-l lanseaza singur.
|
|
c. **Asteptarea `ready_0`**: cu `.fxp` cald START apare in ~2s, la rece mult mai mult (zeci de
|
|
classlib-uri). `-ReadyTimeoutSec` generos (implicit 180s); retry NUMAI la "start ratat",
|
|
nu la "start lent". Detectia "a pornit" se face pe mtime-ul log-ului > momentul lansarii
|
|
(un log stale tinut de un vfp9 zombi pacaleste verificarea "log ne-gol") - omoara zombii
|
|
inainte de fiecare lansare.
|
|
d. **`vfp9 -A test.prg` deschide INTERMITENT editorul** in loc sa ruleze (log gol). Lanseaza
|
|
`.fxp`-ul PRECOMPILAT. Precompilarea (`COMPILE`+`QUIT`) atarna dupa COMPILE si, rulata in
|
|
ACEEASI sesiune powershell, otraveste lansarile ulterioare - ruleaza-o intr-un proces copil
|
|
izolat (`Start-Process -Wait _precompile.ps1`).
|
|
e. **Suitele NU se ruleaza in paralel**: `_precompile.ps1` face `Get-Process vfp9 | Stop-Process
|
|
-Force` (omoara toate instantele), deci un test lansat in paralel il ucide pe cel in curs.
|
|
f. **FARA FURT DE FOCUS (17/07/2026)**: `Graphics.CopyFromScreen` fura focus si se corupe daca
|
|
utilizatorul lucreaza in paralel - nu se mai foloseste. Capturile se fac cu `PrintWindow`
|
|
(user32, P/Invoke) pe `Process.MainWindowHandle`, flag `2` = `PW_RENDERFULLCONTENT`
|
|
(fallback `0` daca iese goala); merge cu fereastra acoperita, dar NU minimizata. Fereastra
|
|
se muta OFF-SCREEN (`SetWindowPos`, `HWND_BOTTOM`, x=-4000, `SWP_NOACTIVATE`) imediat ce
|
|
apare handle-ul si SE RE-IMPINGE la fiecare pas (VFP se reactiveaza singur la
|
|
`Show()`/dialoguri). Consolele powershell copil sunt `-WindowStyle Hidden` (sigur pentru
|
|
consola, NU pentru GUI VFP - ascunsa, `PrintWindow` poate reda gol). Implementat in
|
|
`vfp_ui_harness.ps1` (Take-Screenshot, Push-Offscreen, Wait-MainWindowHandle) si
|
|
`_precompile.ps1`.
|
|
g. **Mock de messagebox**: `FUNCTION amessagebox` care returneaza direct valoarea butonului
|
|
(6=Da), incarcat cu `SET PROCEDURE ... ADDITIVE` **PRIMUL**, inaintea fisierelor aplicatiei:
|
|
la nume duplicat de procedura VFP foloseste fisierul cautat PRIMUL (verificat empiric).
|
|
Astfel umbreste `amessagebox` si in apelurile din metodele de clasa.
|
|
h. **Cursorii ceruti de Init**: pre-populeaza-i INAINTE de instantiere (Init-ul recreeaza din
|
|
Oracle cursoarele goale, iar recrearea lasa grid-ul fara coloane, eroare 1925). Pune 1 rand
|
|
placeholder inainte, apoi **`ZAP`** dupa `Show()` — NU `DELETE ALL`, care lasa un rand fizic
|
|
sters si pointerul la EOF (cod care face `GO <recno>` da eroare 5, vezi
|
|
`conventie_go_recno.md`).
|
|
i. **Cursorii trebuie sa aiba EXACT indecsii creati de fluxul real** inainte de instantiere
|
|
(fluxul real ii creeaza in metoda apelanta, ex. un `INDEX ON ... TAG ord_doc` +
|
|
`SET ORDER TO` inainte de `CREATEOBJECT`). Fara ei cursorul ramane pe ordinea FIZICA, iar
|
|
logica de tip `GO TOP` + `LOCATE FOR ...` alege alt rand decat in productie - rezultat fals,
|
|
uneori in cascada la apeluri repetate. Verifica in codul apelant ce indecsi se creeaza si
|
|
replica-i identic.
|
|
j. **Mock-urile de date trebuie sa reproduca structura si semantica REALA a sursei** (view
|
|
Oracle: toate coloanele; relatii intre randuri: toate randurile implicate, nu unul singur cu
|
|
valori "compuse" manual in test). Un mock incomplet lasa campuri mereu NULL sau ascunde
|
|
pasul care se testeaza. Cand un flag global activeaza cod suplimentar (ex. `gl406`), acel
|
|
cod cere mock-uri in plus - verifica ce apeleaza si adauga metodele lipsa din dummy.
|
|
k. **`LOCATE FOR camp == 'literal'` pe camp `C(n)` padded nu gaseste nimic** (`==` e exact) -
|
|
foloseste `ALLTRIM(camp) == 'literal'`.
|
|
l. **`CREATEOBJECT`/`ADDPROPERTY` se comporta gresit apelate DINTR-O PROCEDURA in acest runtime
|
|
headless** (obiect returnat ca string de 30 spatii; `ADDPROPERTY` da eroare 11). Din
|
|
programul PRINCIPAL merg. Construieste obiectele-parametru INLINE in main, nu intr-un helper.
|
|
(Cauza neclara; reproductibil.)
|
|
m. **Fara `SELECT-SQL` pe cursorul legat de grid**: `SELECT ... FROM <cursor> INTO CURSOR` cat
|
|
timp cursorul e RecordSource-ul unui grid viu poate omori procesul vfp9 silentios (fara
|
|
eroare catchabila, fara semafor). Foloseste xBase nativ (`COUNT FOR ... TO`, `CALCULATE`,
|
|
`LOCATE`), care nu comuta zona de lucru a grid-ului.
|