Câștiguri:
- Abilitatea de a preveni inteligența artificială să accepte comportamentul eronat ca fiind „corect” prin calcularea valorii așteptate în testele unitare, independent de regula de acceptare
- Abilitatea de a imprima teste rapide, independente și repetabile prin aplicarea principiilor AAA și FIRST și batjocorirea dependențelor externe
- Abilitatea de a testa teste cu mutație (ruperea codului) și de a recunoaște codul dificil de testat ca un miros de design
Cel mai mare și mai rapid strat al piramidei de testare este testarea unitară - testarea care verifică o funcție sau o mică bucată de cod, izolată de orice altceva. Mii de teste unitare rulează în câteva secunde și detectează o eroare în timp ce codul este încă pe ecranul dezvoltatorului. Inteligența artificială (AI) este poate cea mai competentă în producerea de teste unitare: îi dai o funcție, AI produce zeci de teste. Dar tocmai această comoditate dă naștere la cea mai mare capcană: AI produce cu ușurință teste care „luminează verde, dar nu verifică nimic” sau acceptă comportamentul curent (poate defectuos) al codului ca fiind „corect”. În această unitate veți învăța cum să scrieți teste de unitate cu adevărat protectoare cu AI și relația dintre codul testabil și AI.
Calitățile unui test unitar bun: FIRST
Testele unitare bune urmează principiile FIRST: Rapid, Independent (testele nu ar trebui să fie dependente unul de celălalt), Repetabil (repetabil — același rezultat în orice mediu), Auto-validare (clar trece/eșuat), La timp (la timp). Amintiți-vă de aceste principii atunci când AI produce teste; cereți în mod specific ca testul să nu depindă de lumea exterioară (bază de date reală, rețea, ceas) să fie „independent” și „repetabil”.
Model AAA și afirmație expresivă
Un test unitar solid urmează structura AAA: Aranjare (pregătire — configurați intrări și dependențe), Act (executare — apelați funcția testată), Assert (validați — comparați rezultatul cu valoarea așteptată). Cea critică este afirmarea. Cea mai obișnuită greșeală pe care o face AI este să obțină afirmația din rezultatul codului testat - logica „orice returnează codul este adevărat”. Acest lucru face ca testul să nu aibă sens. Modul corect este determinarea valorii așteptate în mod independent (din criteriile de acceptare, calculați-o manual).
Atenție: Dacă îi spuneți AI „scrieți un test pentru această funcție”, AI poate rula funcția și scrie rezultatul acesteia ca „așteptat”. Acest test trece chiar dacă funcția este falsă. În schimb, spuneți „calculați rezultatele așteptate conform acestor reguli, nu faceți referire la ieșirea curentă a funcției”.
Batjocuri, cioturi și dependențe
Testarea unitară necesită izolare. Dacă funcția dvs. depinde de o bază de date sau de API, acestea sunt înlocuite cu obiecte simulate (mock/stub - un substitut controlat, fictic, pentru dependența reală) în testare. Acest lucru face ca testul să fie rapid, independent și reproductibil. AI poate produce instalații simulate; Atenție însă la batjocura excesivă: dacă batjocorești totul, testul va verifica doar „ce returnează simularea”, nu logica reală. Echilibru: emulați lumea exterioară, executați logica reală testată.
Testabilitate și IA
Există un feedback interesant: codul care este greu de testat este adesea un cod prost conceput. Dacă AI are probleme la scrierea testelor pentru o funcție (prea multe dependențe, stare globală ascunsă, efecte secundare), acesta este un miros de design. Întrebarea AI „cum ați refactoriza acest cod pentru a-l face testabil” duce atât la testare mai bună, cât și la un cod mai bun.
Teste parametrizate și diversitatea datelor
Scrierea unui test separat de fiecare dată pentru a verifica aceeași regulă cu intrări diferite este atât obositoare, cât și dificil de menținut. Testarea parametrizată - o structură care rulează în mod repetat aceeași logică de testare pe o listă de intrări și rezultate așteptate - elimină această repetiție: un singur corp de test este alimentat cu zeci de perechi de intrări. AI este foarte eficient în producerea acestor tabele de rezultate așteptate de intrare atunci când îi oferiți regulile de acceptare; În special, tabelează sistematic valorile limită și clasele de echivalență.
Dar există și aici o capcană: AI tinde să obțină rezultatele așteptate în tabelul generat din codul testat. Această eroare este și mai periculoasă în testarea parametrizată, deoarece o singură logică incorectă invalidează zeci de linii. Prin urmare, calculați întotdeauna coloana rezultatului așteptat în mod independent conform regulii de acceptare și validați manual cel puțin câteva rânduri. De asemenea, cereți o coloană de descriere „ce reprezintă fiecare rând”; așa că atunci când se rupe un rând, vezi instantaneu care stare este ruptă.
Sfat: Adăugați în mod intenționat un „rând de capcană” la tabelul de testare parametrizat - adică, introduceți greșit rezultatul cu bună știință. Dacă acea linie nu devine roșie când rulați testul, testul dvs. nu verifică de fapt situația respectivă. Aceasta este o verificare rapidă.
Prompt slab / Prompt puternic
Slab: „Scrieți un test unitar pentru această funcție”.
Puternic: scrieți teste unitare [limbă/cadru] pentru funcția „taxCalculate(suma, rată). Regula de acceptare: rezultat = sumă * rata, rotunjită la 2 zecimale; suma negativă sau rata aruncă o eroare; returnează 0 dacă rata este 0. Folosiți structura AAA. Calculați manual valorile așteptate conform ACESTE reguli de ieșire; mare, rotunjite la zecimale). Lăsați numele fiecărui test să descrie regula pe care o verifică.
prompt puternic; Oferă regula de acceptare, așteptarea independentă a valorii așteptate, structura și cazurile marginale. Astfel, testul devine gardianul regulii, nu oglinda codului.
Tabelul de calitate a testului unitar
simptom
Test prost (încredere falsă)
test bun
afirmă
Niciuna sau „nu nulă”
Valoarea concretă așteptată
Sursa de valoare așteptată
Ieșirea funcției
Regula de acceptare / calcul manual
dependenta
DB real/rețea/oră
Izolat cu mock/stub
carcasă de margine
Doar drum fericit
limită, negativă, eroare
Când spargi codul
rămâne verde
devine roșu
Nume
test1, testMethod
descrie regula pe care o confirmă
Patru șabloane copiabile
1) Testarea unitară bazată pe reguli:
Rolul dvs.: inginer senior de testare software. Scrieți un test unitar pentru următoarea funcție cu [limbă/cadru]: [semnătură].Reguli de acceptare: [reguli].- Utilizați structura AAA.- Calculați manual valorile așteptate conform ACESTE reguli; NU faceți referire la ieșirea curentă a funcției. - Acoperiți limita, negativul, eroarea și calea fericită cu teste separate. - Lăsați fiecare nume de test să descrie regula pe care o verifică. - Simularea dependențelor externe; Faceți logica reală să funcționeze.
2) Controlul rezistenței la mutații:
Consultați aceste teste unitare. Enumerați 5 modificări minore pe care le-aș putea face codului testat (a - în loc de un +, a >= în loc de a >, o deplasare a limitei) și spuneți-mi pentru fiecare CARE dintre aceste teste va deveni roșu? Dacă niciunul nu este returnat, testul este insuficient.Cod + teste: [paste]
3) Examinarea testabilității:
De ce este dificil să scrieți un test unitar pentru această funcție? Dependență ascunsă, statut global, efecte secundare, există multe responsabilități? Sugerați o refactorizare minimă pentru a o face testabilă; nu schimba comportamentul. Cod: [paste]
4) Finalizare incompletă a scenariului:
Sunt prezentate următoarele funcții și teste disponibile. Enumerați ce comportament/carcasă de margine nu a fost NICIODATĂ testat (decalaj) și adăugați un test pentru fiecare. Funcție + teste: [paste]
trei mini cutii
Cazul 1 — Testați oglindirea codului. Un dezvoltator a cerut AI să scrie un test pentru funcția de rotunjire; 10 teste au fost verzi. De fapt, funcția se rotunjea în direcția greșită, dar AI-ul luase valorile așteptate din rezultatul funcției, așa că testele au considerat eroarea „adevărată”. Când valorile așteptate au fost calculate manual cu șablonul „condus pe reguli”, 4 teste au devenit roșii și eroarea reală a fost dezvăluită.
Cazul 2 – Valoarea controlului mutației. O echipă s-a bazat pe 45 de teste unitare. Am încercat 20 de modificări minore ale codului cu o „verificare a robusteței mutațiilor”; testele au prins doar 11 dintre ei. Restul de 9 perturbări au trecut în tăcere. Echipa a consolidat testele slabe; O eroare reală de calcul a fost surprinsă de aceste teste îmbunătățite în următoarea ediție.
Cazul 3 – Netestabilitatea este un miros de design. AI nu a putut scrie teste pentru o funcție de comandă, avea nevoie în mod constant de baza de date reală. Șablonul „evaluare testabilitate” a arătat că funcția a încorporat accesul la baza de date. Când injecția de dependență a fost eliminată, testele au putut fi scrise și codul a devenit mai curat.
Greșeli comune
- Deducerea valorii așteptate din cod. AI acceptă ieșirea funcției ca fiind „corectă”; test care confirmă codul defect.
- Testează fără aserțiune sau cu aserțiune trivială. „Nu a aruncat o eroare, a trecut” logica; Nu confirma nimic.
- Batjocură extrem. Batjocorind totul și testând doar ceea ce returnează simularea; logica reală nu este testată.
- Doar drumul fericit. Ocolirea stărilor limită, negative și de eroare.
- Nu testează prin spargerea codului. Aveți încredere în verde fără a verifica mutația.
- Ignorarea netestabilității. Nu recunoașteți și remediați designul prost în loc să faceți teste dure.
Pe scurt
Testele unitare sunt cel mai rapid și cel mai mare strat al piramidei de testare; Ea prinde greșeala în cel mai ieftin moment. AI este foarte capabil să producă teste unitare, dar cea mai mare capcană este scrierea de teste care presupun un comportament incorect ca fiind „corect”, obținând valoarea așteptată din codul însuși. Soluție: dați regulile de acceptare, calculați manual valorile așteptate, aplicați principiile AAA și FIRST, bateți joc de lumea exterioară și rulați logica reală și testați fiecare test prin mutație (ruperea codului). Codul care este greu de testat este un semn de design care trebuie reparat.
Sarcina de aplicare
Selectați o funcție care conține o regulă de afaceri din propriul proiect. Scrieți reguli de acceptare și cereți AI să scrie teste cu șablonul „testare unitară bazată pe reguli”; Aveți valorile așteptate calculate manual. Apoi aplicați „verificarea robusteței mutației”: faceți cel puțin 5 mici întreruperi în cod și măsurați câte teste devin roșii. Adăugați un nou test pentru corupții neprinse. Raportați câte întreruperi au fost surprinse (cum ar fi scorul de mutație).
lista de verificare
- [ ] Am dat regulile de acceptare și am calculat manual valorile așteptate.
- [ ] M-am asigurat că testele nu au derivat valoarea așteptată din cod.
- [ ] Am stabilit teste independente urmând ghidurile AAA și FIRST.
- [ ] Am batjocorit dependențele externe și am rulat logica reală.
- [ ] Am acoperit cazuri limită, negative și de eroare.
- [ ] Prin spargerea codului (mutația) am dovedit că testele într-adevăr protejează.