Un agent de cod scrie un test în câteva secunde, îl rulează, îl vede verde și trece mai departe — exact aici începe problema. Testarea automată cu agenți AI promite să scurteze partea cea mai plictisitoare din dezvoltare, dar o suită verde generată fără disciplină poate fi mai periculoasă decât lipsa testelor, pentru că dă încredere falsă exact acolo unde ai nevoie de ea cel mai mult. Ghidul de față e pentru developeri, QA engineers și tech leaduri care vor să folosească Cursor, Claude Code sau GitHub Copilot ca să genereze și să mențină teste unitare și de integrare fără să-și sacrifice suita pe termen lung.
De ce „verde” nu înseamnă „testat”
Raportul DORA 2025, publicat de Google Cloud pe baza a aproape cinci mii de răspunsuri din industrie, pune două cifre una lângă alta: 90% dintre respondenți folosesc deja AI la muncă, dar 30% raportează încredere mică sau inexistentă în codul generat. Cifrele contează mai puțin decât concluzia care le leagă: anunțul oficial al raportului spune explicit că adoptarea AI „continuă să aibă o relație negativă cu stabilitatea livrării de software”, pentru că accelerarea scrierii de cod expune slăbiciunile din aval — iar fără sisteme de control solide, printre care testarea automată robustă, o creștere a volumului de schimbări duce direct la instabilitate.
Testele nu sunt un moft de etapă. Sunt exact controlul despre care vorbește raportul.
Articolul de față tratează un singur subiect, îngust și practic: cum generezi teste unitare și de integrare cu un agent de cod și cum ții suita vie pe termen lung — nu cum se schimbă rolul de QA și nu cum testezi un sistem AI ca atare. Dacă vii din zona de testare și cauți unelte de automatizare E2E, self-healing sau disciplina de evaluare a aplicațiilor generative, ai nevoie de ghidul dedicat AI pentru QA și testare software — acolo e tratată transformarea rolului de tester și testarea sistemelor AI ca atare. Aici rămânem strict la codul determinist, cel pe care îl scrie sau îl modifică un agent în depozitul tău, și la testele care îl verifică.
Cum generezi teste utile cu un agent, nu doar teste care trec
Regula care separă o suită utilă de una decorativă se decide înainte de prima linie generată: sursa de adevăr pentru un test trebuie să fie cerința, nu implementarea deja scrisă. Dacă ceri unui agent „scrie teste pentru acest fișier”, el va testa ce face codul. Dacă ceri „scrie teste care verifică acest comportament, inclusiv cazurile X și Y”, el va testa ce ar trebui să facă. Diferența nu se vede când codul e corect — se vede exact atunci când codul are deja un bug, caz în care primul tip de test îl „betonează”, iar al doilea îl prinde.
Cursor: bucla închisă generare → rulare → corectare
Pagina oficială de generare de teste a Cursor descrie exact acest mecanism: agentul citește fișierele de test deja existente din proiect ca să deducă framework-ul, convențiile de mock și stilul de denumire, apoi poate rula testele direct din terminal, citi output-ul unui eșec și corecta codul sau testul, reluând ciclul până trec. Automatizarea completă a rulării cere activarea opțiunii Auto-run; fără ea, tu rulezi manual fiecare iterație și verifici fiecare diff înainte să-l accepți.
Practic, cu cât suita existentă dintr-un proiect e mai consistentă, cu atât testele noi generate de agent respectă aceleași convenții — un motiv în plus să nu lași un modul fără nicio suită de referință înainte de a cere generare în masă. Fluxurile de lucru cu agenți multipli din Cursor — unul care implementează, altul care scrie teste în paralel, fiecare în propriul context — alături de configurarea regulilor .mdc specifice pentru fișierele de test și de alegerea modelului potrivit per sarcină, sunt tratate pe larg în cursul Cursor ca Pro.
Claude Code: verificare explicită și modelul „un agent scrie testul, altul scrie codul”
Documentația oficială Claude Code pornește de la o observație simplă: „Claude se oprește când munca pare gata. Fără un verificator pe care îl poate rula, «pare gata» e singurul semnal disponibil, iar tu devii bucla de verificare.” Recomandarea explicită este să dai agentului „un verificator pe care îl poate rula: teste, un build, o captură de comparat” — abia atunci bucla se închide singură: agentul lucrează, rulează verificarea, citește rezultatul și iterează până trece (code.claude.com/docs/en/best-practices).
Documentația dă și exemplul concret de prompt bine formulat pentru testare: în loc de „adaugă validare pe formular”, ceri „scrie o funcție validateEmail; cazuri de test: user@example.com e valid, invalid nu e valid, user@.com nu e valid; rulează testele după implementare”. Pentru teste punctuale pe cod existent, același document recomandă să specifici explicit scenariul și constrângerile: „scrie un test pentru foo.py care acoperă cazul în care utilizatorul e delogat; evită mock-urile.”
Cea mai interesantă recomandare pentru acest subiect e însă alta: documentația descrie un model de lucru „Writer/Reviewer” între două sesiuni separate, cu context curat fiecare, și adaugă explicit — „poți face ceva similar și cu testele: un agent scrie testele, altul scrie codul care să le treacă”. E, de fapt, TDD agentic, cu două instanțe care nu-și văd reciproc raționamentul, exact ca într-o echipă reală unde cine scrie testul nu e cine scrie implementarea. Documentația numește și eșecul specific pe care îl previne verificarea explicită — „decalajul încredere-apoi-verificare”: agentul produce o implementare plauzibilă care nu acoperă cazurile de margine, iar singurul remediu e verificarea obligatorie înainte de a considera treaba gata.
GitHub Copilot: teste ca punct forte, validare ca obligație, nu ca opțiune
Ghidul oficial de bune practici GitHub Copilot listează scrierea de teste printre punctele forte ale sugestiilor inline și recomandă explicit folosirea lor pentru „generarea de teste în dezvoltarea ghidată de teste” (test-driven development). Dar același document nu lasă loc de ambiguitate pe partea de verificare: „ar trebui să validezi mereu codul pe care îl sugerează” și, mai specific pentru subiectul nostru, „folosește teste automate și unelte ca să verifici munca Copilot”. Cu alte cuvinte, chiar producătorul uneltei spune că testul generat de ea nu e sursa finală de adevăr — e un draft care trece prin aceleași porți ca orice alt cod.
De ce procentul de acoperire minte
„Acoperirea de cod” (code coverage) măsoară ce linii au fost executate în timpul rulării testelor, nu dacă testul a verificat ceva relevant despre comportament. Diferența pare teoretică până vezi cercetarea care o cuantifică: Laura Inozemtseva și Reid Holmes au publicat la ICSE 2014 studiul „Coverage Is Not Strongly Correlated with Test Suite Effectiveness”, distins cu ACM SIGSOFT Distinguished Paper Award. Au analizat cinci sisteme Java de până la 724.000 de linii de cod, au generat 31.000 de suite de teste și au măsurat atât acoperirea (pe instrucțiuni, decizii și condiții), cât și eficiența reală de detectare a defectelor, folosind mutation testing ca etalon obiectiv. Concluzia: odată controlat numărul de teste din suită, corelația dintre acoperire și capacitatea reală de a prinde defecte rămâne doar slabă spre moderată. Acoperirea e utilă ca să găsești zonele netestate, dar e un semnal slab al calității unei suite.
Măsura mai fidelă, folosită chiar de studiul de mai sus ca etalon, e mutation testing: unelte precum Stryker (pentru JavaScript/TypeScript) sau PIT (pentru Java) modifică automat mici fragmente din codul sursă — inversează o condiție, schimbă + în -, elimină un return — și rulează suita împotriva fiecărei variante „mutante”. Dacă un test pică, mutația e „ucisă”; dacă toate testele trec pe codul stricat intenționat, mutația „supraviețuiește” și arată exact unde lipsește o asertie reală, nu doar o linie executată.
Legătura cu generarea asistată de AI e directă: un agent optimizat să „facă procentul de acoperire să crească” poate scrie teste care apelează o funcție fără să verifice nimic din rezultat — suficient ca linia să fie marcată „acoperită”, insuficient ca să prindă vreun bug. Cere întotdeauna comportamentul testat explicit în prompt, nu doar „acoperire mai mare”, și tratează procentul de acoperire ca pe un indicator de zone neatinse, nu ca pe un obiectiv în sine.
Teste fragile și flaky — capcana specifică a generării cu AI
Un test flaky (care trece și pică aleatoriu, fără nicio modificare de cod) e costisitor oricum ar fi scris, dar generarea cu agenți introduce un tipar propriu. O lucrare din 2026, deocamdată preprint, neevaluată încă de o conferință cu recenzare completă — „Beyond Test Presence: Assessing the Quality and Robustness of Agent-Generated Tests in Open-Source Projects” — a analizat static 204.673 fișiere de test din setul de date AIDev: 179.732 generate de agenți și 24.941 scrise de oameni. Rezultatele sunt specifice, nu impresii:
- Acoperirea cazurilor-limită: agenții ies în față — scor de varietate la verificări de graniță de 0,62 față de 0,32 la oameni, iar testarea explicită a cazurilor „null”/absente apare la 13,40% din testele agenților față de 8,3% la oameni.
- Puterea asertiilor: oamenii au un mic avans — 88,1% asertii puternice față de 85,37% la agenți.
- Riscul de flakiness: agenții generează mai multe teste cu risc ridicat — o rată candidată de 0,41 față de 0,30 la testele scrise de oameni, pe care autorii o atribuie în principal dependenței de fișiere reale (I/O) și de logică nedeterministă.
Concluzia autorilor merită reținută ca atare: agenții sunt mai riguroși la testarea de graniță, dar le lipsește „conștiința mediului de execuție” necesară pentru teste stabile și izolate (hermetice). Practic, un agent lăsat să decidă singur cum „simulează realist” un scenariu va fi tentat să folosească ceasul de sistem, sistemul de fișiere real sau un apel de rețea adevărat — exact ingredientele unui test flaky. Înainte să accepți un test generat, verifică dacă atinge una dintre aceste patru surse de nedeterminism: timpul (Date.now()/new Date() neinjectat), sistemul de fișiere, rețeaua sau un generator de numere aleatoare fără sămânță fixă. Dacă da, cere explicit varianta izolată: ceas simulat, sistem de fișiere în memorie, mock la marginea sistemului (nu la mijlocul logicii), random cu seed fix.
Menținerea suitei în timp: ce faci când un refactor rupe testele generate
Un test care pică după o schimbare de cod poate însemna două lucruri complet diferite, și confuzia dintre ele e principala sursă de frustrare în proiectele cu suite generate masiv: fie testul a prins o regresie reală, fie testul era cuplat la detalii de implementare care s-au schimbat fără ca și comportamentul public să se schimbe. Dacă un refactor care, prin definiție, nu schimbă comportamentul reușește să rupă zeci de teste simultan, problema aproape sigur nu e în codul nou, ci în felul în care au fost scrise testele vechi — asertau pe structura internă (ordinea apelurilor, numărul exact de interacțiuni cu un mock), nu pe contractul public al modulului.
Remediul practic are doi pași. Primul: ceri agentului să regenereze sau să ajusteze testele împotriva interfeței publice — intrare, ieșire, efecte observabile din afară — nu împotriva pașilor interni pe care tocmai i-ai schimbat intenționat. Al doilea, pentru cod vechi care nu are deloc teste înainte de un refactor mare: tehnica testelor de caracterizare, descrisă de Michael Feathers în Working Effectively with Legacy Code — teste care fixează comportamentul curent, inclusiv părțile lui ciudate, exact cât să poți schimba implementarea fără să schimbi ce face sistemul, și abia apoi corectezi ce era greșit, cu bună știință.
Pe partea de automatizare, verificarea nu trebuie să rămână un pas manual pe care îl uiți. Claude Code expune un sistem de hooks — evenimente ca PostToolUse (după fiecare editare) sau Stop (la finalul unei ture) — pe care le poți folosi ca „poartă determinist㔠care rulează suita de teste automat și blochează închiderea sesiunii până trece, fără să depindă de disciplina ta de a apăsa „rulează testele” de fiecare dată. Întregul ciclu de viață al hook-urilor, de la configurare la guardrails de securitate pentru un agent care rulează comenzi fără supraveghere constantă, e tratat ca modul dedicat în cursul Claude Code Mastery: Coding Agentic din Terminal. Important de delimitat: acesta rulează testele determinist, local sau în CI — ce verifică automat un agent într-un pull request deja deschis, sub formă de comentarii și gate-uri de merge, e un subiect separat, tratat în ghidul despre code review și CI cu agenți AI.
Checklist: ce verifici tu, ce lași agentului
Înainte să mergi mai departe, patru verificări care separă o suită de încredere de una decorativă:
- Sursa testului e cerința, nu implementarea. Ai specificat comportamentul așteptat în prompt, inclusiv cazurile de margine, nu doar „scrie teste pentru acest fișier”?
- Asertiile verifică ceva real. Un test care apelează o funcție fără să verifice rezultatul „trece” mereu — nu e un test, e zgomot statistic în raportul de acoperire.
- Testul pică pe codul stricat intenționat. Strică temporar implementarea (comentează o linie, inversează o condiție) și rulează testul: dacă tot trece, asertia e prea slabă pentru a conta.
- Testul nu depinde de mediul real. Fără ceas de sistem, fișiere reale, apeluri de rețea reale sau random fără sămânță — altfel ai acceptat deja un candidat la flakiness.
Regula „botul propune, omul aprobă”, valabilă pentru codul de producție, se aplică identic testelor: un test generat nu intră în suita principală fără ca cineva să fi citit asertiile, nu doar eticheta „PASS” din terminal.
Testarea codului vs. evaluarea sistemelor AI — nu confunda cele două
Tot ce am discutat presupune cod determinist: aceeași intrare produce aceeași ieșire, iar un test verifică exact asta. Când funcționalitatea testată e ea însăși un sistem AI — un prompt, un flux RAG, un agent care ia decizii — premisa de determinism dispare, iar disciplina corectă nu mai e suita clasică de teste unitare, ci evaluarea sistematică pe seturi reprezentative, cu scoring automat (evals) și, acolo unde ieșirea e text liber, un model-judecător (LLM-as-judge). Arhitectura acestui tip de evaluare, separată de testarea de cod clasică — observabilitate, seturi de evaluare, integrarea evals în pipeline-ul de release — e tratată în cursul Arhitectura Sistemelor AI la Scară, iar transformarea disciplinei de QA pe acest front e detaliată în ghidul deja menționat despre AI pentru testare software. Un test unitar clasic, cu asertie exactă pe un răspuns generativ nedeterminist, e un test care devine flaky prin construcție — indiferent cât de bine l-a scris agentul.
Întrebări frecvente
Pot să las un agent AI să scrie toată suita de teste a unui proiect care nu are deloc teste? Da, pentru teste de caracterizare — care fixează comportamentul curent, inclusiv părțile lui ciudate, înainte de un refactor sau o migrare. Nu și ca teste finale de acceptare: acelea trebuie să vină din cerință, verificate de cineva care știe care e comportamentul corect, nu doar cel actual.
Care e diferența reală dintre un procent de acoperire mare și o suită bună? Acoperirea arată ce linii au fost executate, nu dacă testul a verificat ceva relevant. Studiul lui Inozemtseva și Holmes (ICSE 2014) a găsit o corelație doar slabă spre moderată între acoperire și capacitatea reală de a prinde defecte, odată controlat numărul de teste din suită. Măsura mai fidelă e scorul de mutation testing: câte modificări artificiale ale codului sunt prinse efectiv de suită.
De ce sunt testele generate de AI mai predispuse la flakiness decât cele scrise de oameni? O analiză din 2026 pe aproape 205.000 de fișiere de test a găsit o rată de risc de flakiness de 0,41 la testele generate de agenți față de 0,30 la cele scrise de oameni, atribuită în principal dependenței de fișiere reale și de logică nedeterministă în loc de izolarea mediului de execuție (timp, fișiere, rețea, random). Cere explicit agentului variante hermetice: ceas simulat, sistem de fișiere în memorie, random cu sămânță fixă.
Cum mențin suita de teste după un refactor mare care o rupe aproape integral? Dacă un refactor care nu schimbă comportamentul reușește să rupă multe teste, problema e de obicei în teste — erau cuplate la detalii interne de implementare, nu la contractul public al modulului. Cere agentului să regenereze testele împotriva interfeței publice și automatizează rularea cu un hook determinist, nu doar manual, la final de sesiune.
Ce verific eu, manual, înainte să accept un test scris de un agent? Trei lucruri, în ordine: că asertia verifică efectiv rezultatul, nu doar că funcția a fost apelată; că testul pică dacă strici temporar implementarea intenționat; și că nu depinde de ceas real, fișiere reale sau rețea reală ca să treacă. Dacă toate trei sunt adevărate, testul merită să intre în suită.
Concluzie
Testarea automată cu agenți AI nu elimină disciplina de testare — o mută mai devreme în flux și o face mai ieftină, dacă respecți trei reguli simple: dai agentului cerința, nu doar codul, ca sursă a testului; ceri dovada rulării, nu doar afirmația că testul a fost scris; și păstrezi un om care citește asertiile înainte să le accepte, exact cum ai face cu orice alt cod de producție. O suită verde nu e scopul. Scopul e o suită care ar fi prins bug-ul pe care tocmai l-ai reparat, care rămâne stabilă când schimbi implementarea fără să schimbi comportamentul și care nu depinde de ceas, fișiere sau rețea reale ca să treacă. Restul — procentul de acoperire, viteza de generare, numărul brut de teste — sunt cifre comode, nu calitate.
Surse
- Google Cloud, anunțul oficial al raportului DORA 2025: https://cloud.google.com/blog/products/ai-machine-learning/announcing-the-2025-dora-report
- Cursor, pagina oficială de generare de teste: https://cursor.com/for/test-generation
- Anthropic / Claude Code, „Best practices for agentic coding”: https://code.claude.com/docs/en/best-practices
- GitHub, „Best practices for using GitHub Copilot”: https://docs.github.com/en/copilot/get-started/best-practices
- Inozemtseva, L. & Holmes, R., „Coverage Is Not Strongly Correlated with Test Suite Effectiveness”, ICSE 2014: https://cs.ubc.ca/~rtholmes/papers/icse_2014_inozemtseva.pdf
- Jhanglani, Desai, Kansara, AlOmar, „Beyond Test Presence: Assessing the Quality and Robustness of Agent-Generated Tests in Open-Source Projects” (preprint, 2026): https://arxiv.org/abs/2607.12068
Acest articol are scop tehnic și educativ. Cifrele citate din cercetare provin din sursele indicate la data redactării; un preprint nu a trecut încă prin recenzare completă de conferință — tratează-l ca atare.
Cursul care continuă acest articol
Cursor ca Pro: IDE AI-Native, Composer și Multi-Agent 2026 (Enterprise Edition)
Ai citit teoria. În curs o aplici: lecții structurate pe module, exerciții și quiz-uri cu feedback imediat, Profesorul AI integrat în fiecare lecție și progres salvat automat. La final primești o atestare privată de finalizare.
Din programa cursului
- Fundamente Cursor 3
- Composer Mastery
- Model Selection și Routing Inteligent
- Background Agents și Cloud
+ încă 7 module în programa completă
499 lei pe lună pentru acest curs, TVA 21% inclus · sau 1.999 lei pe lună pentru toate cele 25 de cursuri IT Pro (vezi ce înveți în tot parcursul).
Abonament lunar, cu reînnoire automată · anulezi oricând din contul tău · conținut digital cu acces imediat, vezi condițiile de retragere. Atestarea confirmă parcurgerea cursului și este privată — nu este diplomă și nu este calificare recunoscută de stat.