Scuzati-ma ca ma bag, dar de ce considerati Unit Testing-ul asa de primordial?
Ai exact două modalități de a te asigura că o aplicație funcționează corect:
- testarea manuală a fiecărei funcționalități;
- testarea automată începând la cel mai de jos nivel - unit testing.
Orice proces manual ce implică mai mult de un pas este supus greșelii umane; în plus, cât de încrezător ești să te apuci să faci modificări majore la o aplicație ce nu o poți testa în câteva secunde (sau hai, minute)?
Gândește-te la testarea automată ca la o alegere între următoarele:
- Intră pe pagina X, apasă butonul Y, completează formularul Z cu valorile greșite și apasă submit (să vezi dacă merge validarea) completează formularul Z cu valori corecte și apasă submit (înmulțește asta cu numărul de pagini existente)
$ phpunit && jasmine && casperjs
Ce preferi?
Pai si cate pagini testezi de obicei, de cate ori ?
Unit testing-ul mi se pare inutil si fara acuratete (cel putin pentru ce siteuri dezvolt eu).
PS. Nu am niciun fel de experienta in domeniu unit testing, fac totu manual, implementez ceva functie noua o testez manual in browser sa vad eu exact ce se intampla sa dau eu inspect element si sa vad consola si dom-ul.
Dacă nu ai teste automate, atunci când vei modifica o funcție (sau o metodă dintr-o clasă) va trebui să testezi manual toate secțiunile în care acea funcție e folosită.
Caz concret (cred că am mai precizat de asta mai demult): acum vreo trei ani am lucrat la un site relativ complex. Funcționalități extra pe WP ce țineau de user management, administrarea unor widgets, un API extern și alte câteva chestii extra, toate combinate între ele. Toate acestea au fost implementate în aceiași perioadă, prin urmare știam exact cum funcționează și de ce, putând să modific orice, fără nici o problemă.
Anul trecut clientul a venit cu ceva adaosuri și modificări la două dintre funcționalitățile mai sus menționate. Acum, nu știu cum ar fi procedat alții, dar pentru mine a fost o adevărată aventură, pentru că era vorba de un site ce era în producție, iar orice modificare făcută nu trebuia să afecteze în vreun fel funcționalitățile existente: orice modificare mai serioasă era însoțită de o testare amănunțită a funcționalităților, astfel încât să fiu sigur că totul era cum ar fi trebuit. Aș zice că toată această testare manuală mi-a triplat timpul necesar implementării noilor cerințe.
A fost momentul în care am zis că unit testele sunt al dracului de utile, chiar dacă la o primă vedere sunt o pierdere de vreme
Dacă site-urile dezvoltate de tine conțin logică (adică cel puțin un if
) ai nevoie de teste.
Bullshit. Eu sunt de altă părere, și urmează să argumentez.
Poti sa mergi mult si bine fara unit testing. E adevarat insa ca la un moment dat, cand aplicatia o sa fie prea complexa, o sa fie nevoie si o sa fie foarte complicat de facut toate testele de la 0.
Ah, clar că poți, dar chiar vrei să faci asta?
Ce vreau să spun este: cu cât este aplicația mai complexă, cu atât va fi mai dificil să o modifici dacă nu ai teste. Și dacă nu începi să le scrii de când ai doar câteva linii de cod, când vei începe? Când vei avea descurajator de multe linii?
Chestia e ca majoritatea aplicatiilor nu ajung complexe. Asa ca o sa te trezesti cu x0% efort in plus la o aplicatie care poate ca nu ajunge sa faca ce voiai ca nu mai ai buget.
In primul rand ca nu testetezi, ci doar faci design-ul clasei/obiectelor. Ca ai dupa si niste teste automate, este un bonus.
Desi nu practic (inca) Unit Testing-ul, iti pot spune de ce e important : shop online mare, in spate o mizerie de cod ( deja primit - vorbesc de JS ). Am fost nevoit sa fac mici update-uri care au fu*tut totul si la fiecare bug primit trebuie sa iau manual toate posibilitatile, si crede-ma, sunt destule la o pagina de checkout ( e vorba de magazin online ). Cred ca e prima data cand simt cu adevarat lipsa unei automatizari pentru testarea functionalitatii.
PS : nu am citit ce s-a discutat mai sus
Nu prea s-a specificat aici, dar unit testing-ul poate fi foarte bine inlocuit la website-uri mai mici cu integration testing.
Acelasi rezultat, dar cu un efort moderat avand in vedere ca nu toate site-urile au complexitatea necesara pentru unit testing.
Guys, complexitatea minima necesara pentru a introduce Unit Testele este primul if
ce scrii. Lucrurile sunt chiar invers, s-ar putea sa nu ai nevoie de Integration Tests sau E2E Tests sau API Tests mult timp, mai ales pentru aplicatii mici, dar Unit Testele sunt esenta. Nu degeaba pe piramida aia ai 90% Unit Teste.
Uite un exemplu simplu. Ai metoda M1 cu un singur if
, adica 2 cai de executie C1 si C2. Si ai metoda M2 similara, cu caile de executie C3 si C4. Daca faci Unit Testing, vei avea cate un singur test pentru fiecare cale C1, C2, C3 si C4. Adica 4 teste pentru 4 cai.
Daca faci teste de integrare sau End-to-End (E2E), trebuie sa parcurgi caile urmatoare de executie (presuspunand ca metodele se apeleaza intre ele): C1->C2, C1->C3, C2->C1, C2->C3. In cazul a doua metode cu doua cai de executie fiecare, ai tot 4 teste de scris. Dar sa vedem ce se intampla cand intra in schema si a trea metoda in lantul de executie, tot cu 2 cai de executie, adica M3 cu C5 si C6.
Va trebui sa adaugi inca 2 Unit Teste in asa fel incat sa acoperi toate caile de executie. Adica ai crestere liniara.
Dar daca folosest teste de Integrare sau E2E, te vei confrunta cu o problema. Numarul cailor tale va creste exponential. Vei avea: C1->C3->C5, C1->C3->C6, C1->C4->C5, C1->C4->C6, C2->C2->C5, C2->C3->C5, C2->C3->C6, C2->C4->C5, C2->C4->C6, adica 8 variante. Sper ca nu am omis nici unul, ca mi-a fost greu sa le scriu chiar si la acest nivel de baza. Cu alte cuvinte ai 2^3 combinatii in loc de 2*3 combinatii.
Formula se complica foarte tare pe masura ce nu toate metodele tale comunica intre ele si au cai de executie diferite. Va doresc succes sa testati o aplicatie de de 10 metode cu minit cate 2 cai de executie pe fiecare prin teste de integrare se E2E. Exceptie fac cazurile cand metodele sunt izolate si nu comunica intre ele, caz in care testele tale de integrare de fapt nu integreaza nimic si sunt de fapt teste unit exersate de la un nivel pre inalt.
Ce zic eu e ca daca pleci la drum scriind teste n-o sa lansezi niciodata un MVP in timp util si probabil o sa termini banii mult inainte de validare. Dar hei, codul arata foarte frumos si e bug free.
Dacă știi totul de la început și nu se va mai schimba nimic la proiect, atunci da, poți să te duci direct să scrii cod fără nici un fel de grijă. Dar a scrie cod este un proces de descoperire a ceea ce contează pentru cei care faci proiectul. Iar acest lucru se întâmplă prin comunicare atât la nivel de sistem cât și la nivel de obiecte unde se află unit-testingul(designul). Iar acest ciclu nu ar trebui să fie mai mare de 20 minute pentru core domainul respectiv dacă bineînțeles ai descoperit limbajul folosit de cei pentru care faci proiectul. Dar deja mă duc spre bdd sau specification by example, așa că mă opresc aici.
Plus "The only way to make the deadline – the only way to go fast – is to keep the code as clean as possible at all times."
Uncle Bob, Clean Code
Mie mi se pare ca vorbiti din carti si n-ati avut niciodata de luat decizii de cost. Din punctul de vedere al programatorului, normal ca e mai bine sa o iei metodic, usor, cu unit testing la tot codul, cu specificatii clare, fara schimbari majore. Corect. But that’s not happening in real life.
@AdrianBasalic Ca sa nu ti se para ca vorbim din carti, eu am lucrat si asa, si asa. De vreo 5 ani am adoptat TDD si lucrez cu systeme de CI. Daca vrei sa-ti fac ceva fara TDD, imi va lua dublu la timp. Cu alte cuvinte, dupa ce te obisnuiesti, lucrezi de 2 ori mai repede cu TDD decat fara. Si nu, nu am dat citat, vorbesc din experienta.
Ti se pare, TDD chiar imbunatateste viteza de dezvoltare (mai ales daca iei in calcul defectele pe care le previi din start).
Vorbesc din experienta, chiar daca am citit si carti.
Am facut putin Unit Testing, dar e un cosmar cand iti vin bug-uri din productie pe banda rulanta si mai trebuie sa le rezolvi pe loc, oricum incerc sa imi reconsider prioritatile si software-ul stabil prin unit testing sau orice modalitate e una dintre ele alaturi de arhitecturi software si framework-uri.
Nu știu dacă am mai scris pe forum Am scris la un moment dat despre o poveste interesantă despre TDD. Hai să reiau și să spun și cum s-a terminat.
Anul trecut am lucrat la o aplicație cordova/backbone. Am scris teste pentru tot ce am putut și am crezut că ar trebui testat. Rezultatul? În afară de câteva metode ce interacționau cu device-ul (geolocație, cameră etc), totul era testat (coverage pe la vreo 75%).
Cu câteva excepții minore, toate bug-urile au fost de UI (alinieri, fonturi etc). Bugurile de logică raportate au fost rezolvate în felul următor: am scris un test în așa fel încât să reproducă bug-ul (adică să pice testul), am scris/modificat codul aplicației să treacă testul. Toate features noi au urmat același șablon: teste, scris cod.
A fost proiectul cu cele mai puține bug-uri raportate…
Am avut noroc de un timeline rezonabil și o aplicație nu foarte complexă, astfel încât am reușit să mai învăț una-alta. Clientul a fost foarte neîncrezător la început, dar când a văzut cum se face progresul a fost impresionat.