Ce faceți cu unit testele?

In ultimul timp cu react și redux am deaface cu foarte multe fișiere schimbate la orice modificare. Clientul cere coverage de 80% in pipeline, la code review imediat comentează cineva dacă ceva nu e acoperit.

Totuși după ceva timp mi-am dat seama că îmi pierd tot cheful după ce am făcut task-ul și trebuie scrise unit teste la 20 de fișiere. Majoritatea cu reducere la state și funcții asincron în thunks.

Problema e că după ce îmi pierd interesul pierd timpul aiurea cu alte lucruri…

Nici nu se pune problema să scriu unit teste înainte de cod, e mult prea complexa aplicația cu prea multe componente integrate ca să știi unde să scrii logica înainte sa o implementezi.

Si mie imi vine greu sa le scriu si trec prin acelasi lucru ca si tine. Am de facut unit teste si de integrare pt un serviciu in aplicatie. Nu folosesc stack-ul tau, ci Java, Spring si Junit. Nu prea am experienta cu partea de testare.

Pana la urma ma impac cu ideea ca trebuie sa le scriu si o iau usor.

1 Like

Da, TDD e cam poveste in multe cazuri…

1 Like

Eu abia dupa 3 ani, dupa ce am trecut de la un limbaj la altul, am inceput sa fac teste. Asta pentru ca, la noua companie, pentru a pune o aplicatie in productie, e nevoie de un minimum de teste. Mi-am batut capul vreo doua zile pana am prins treaba cu mock-uirea serviciilor. Pentru cineva care e la inceput, e destul de greu sa faci diferenta intre teste corecte si teste inutile (ca unit teste).

Daca ai o aplicatie mare, o sa-ti ia timp si probabil o sa te si plictisesti sa te apuci acum sa faci teste. Daca pornesti de la 0, pare mai simplu ca pentru fiecare serviciu nou implementat, sa-i faci si testele imediat.

Ma uitasem odata la un video al lui Victor Rentea si spunea ca testele se fac dinaintea implementarii. Pe entitati, da, poti sa testezi validarile, actiunile. Par chiar misto, si te ajuta sa descoperi cazuri noi. Dar nu serviciile sau repourile, pentru ca pentru astea ai nevoie de date mockuite. Ori nu imi dau eu seama cum ai putea sa testezi ceva ce nu exista :crazy_face:

Chestia este ca TDD-ul nu e un one size fits all. Depinde de faza in care e proiectul deobicei si de cat de sigur vreti sa fiti cand mergeti inainte. Disclaimer: consider ca dev fara teste nu exista si ca si arhitect/senior dev trebuie sa faci testarea sa fie un proces cat mai smooth si seamless pentru ceilalti developeri. Asta inseamna ca testele trebuie sa fie cat de cat rapide, usor de rulat, conclusive si, mai ales, consistente.

Exista tot timpul un trade-off la teste. De exemplu, sa zicem ca ai o ora sa scrii un test.
In ora aia poti sa scrii un test care acopera cum se proceseaza o plata, sau un test care acopera prezenta butonului de plata.

  1. Ce e mai valoros pentru business-ul tau?
    Sa nu gaseasca clientul butonul de plata e destul de nasol, nu? Asa n-o sa fii niciodata platit si daca nu ai QA sa-ti zica ca iti lipseste butonul, o sa te miri de ce nu-ti intra banii.
    Destul de nasol. Dar, mai nasol este, clientul sa plateasca si sa vada ca i s-au tras din cont 1k USD in loc de 1 USD, sau mai rau clientul sa vada ca a platit dar tie sa nu-ti intre banii.
    Un buton poti sa-l pui usor cand observi lipsa lui, dar un sistem de plata e mai greu de rezolvat.

  2. Ce e mai valoros pentru stabilitatea sistemului tau? Aici ma refer si la long-term, care dintre teste o sa te ajute mai mult cand tu schimbi ca nebunul codul si ai nevoie de siguranta ca nu strici nimic din ce merge si e important?
    Well, un buton lipsa sau in plus, nu deranjeaza decat clientul :man_shrugging: (joke) . Imagineaza-ti cat de deranjant e pentru tine cand, inainte de un deploy sau merge, o sa rogi pe toata lumea sa mai testeze odata ca ti-e frica ca poate ai schimbat ceva critic. Timpul si linistea ta costa. Asta e un semn ca la un moment dat ai ales sa scrii testul gresit sau ca nu l-ai scris deloc :laughing:

Un exemplu poate stupid, dar o ora pe testul gresit cand nu ai mult timp de bagat in teste poate sa te impacteze foarte mult. Ah si, desigur, niciodata nu scrii testele si uiti de ele.
Testele sunt cod. Codul trebuie intretinut. Asta inseamna ca ambele exemple de mai sus trebuie intretinute. Poate la un moment dat o sa-ti pice random testul, o sa trebuiasca sa-l rezolvi ca sa te asiguri ca problema nu e de la codul din spate.

Deci toate testele sunt un trade-off intre timpul devului (care e cel mai valoros dpdv banesc intr-un proiect), si linistea sufleteasca pe care o sa o ai pentru business-ul tau si sistemul tau.

Code-coverage e o minciuna. Lumea reala e complicata si oamenii o sa-ti foloseasca softul intr-un fel in care nu te astepti. Poti sa ai code-coverage 100% si totusi sa ai flow-uri pe care nu le acoperi. Ba chiar, in cursa pentru code-coverage cat mai mare, iti inchizi sistemul la modificari. Ca sa-ti faci codul unit-testable, trebuie sa scrii intr-un anumit fel, sa iti faci totul mockuibil, samd. Toate lucrurile acestea fac dificila orice modificare. Si frustranta in acelasi timp, ca stii ca atunci cand faci o modificare o sa-ti pice mii de teste care defapt nu-s importante.

Exemplu de code-coverage 100% care e gresit in lumea reala. Sa zicem ca faci un unit-test unde testezi cum intra o comanda intr-un ecommerce si iti rezerva produsele. Faci totul testabil, mockuiesti, scrii testul, totul ok. WRONG. In lumea reala ai o baza de date, ai multiplii clienti, ai lock-uri, samd. Cand iti intra 2 comenzi in acelasi timp pe acelasi produs ce se intampla?

Merita sa faci totul testabil unitar? Dupa ce te lovesti de un caz de genul, incepi sa te gandesti la trade-off-ul de timp: faci totul unit-testable (care ia considerabil mai mult timp) vs testezi sistemul asa cum e si castigi niste timp, chiar daca nu castigi siguranta 100% peste tot, dar esti sigur ca ai un caz critic care nu va crapa.

Testele unitare sunt abstractizate de lumea reala, ele nu reprezinta neaparat un adevar ci o extra siguranta pentru tine. De-aia faci mock-uri, samd. Exemple pentru teste unitare bune: calculul totalului unei comenzi, calculul unui discount din total, daca un dto face o mapare buna, daca o clasa se poate instantia, daca se copiaza bine in memorie, etc. In principiu sunt bune ca sunt rapide is testeaza codul in sine( in nici un caz sistemul real ). Pentru ca testeaza codul in sine, ele sunt reliable ca singura variabila programatorul si modificarile aduse de el.

Testele de integrare sunt lente. Sau asa ar spune legenda. Traim intr-o lume in care iti poti rula majoritatea stack-ului local gratie Docker & friends, iar daca iti ruleaza local de ce ar fi foarte incet un test de integrare? Exista o penalizare de timp gratie lumii reale, dar macar asa esti sigur ca timpul ala in care faci o comanda e exact cam cat asteapta si clientul dupa request. Nu sunt asa de reliable ca si unit testele. Cum ai facuta infrastructura, ceva networking failures pot sa iti dea erori, db-ul poate sa-ti ramana in urma, testele se pot calca pe coada unele pe altele, etc. Aici depinde si de maiestria ta. Aici nu poti sa vorbesti de code-coverage ca iti testezi sistemul ca si un black box, ca si cum l-ar utiliza cineva.

SPAs and testing. Sau cum practic singura ta varianta sunt testele unitare acolo. SPA-urile, care sunt basically JS au nevoie de un browser sa mearga. Daca credeai ca testele de integrare sunt incete, stai sa vezi e2e testingul :laughing: E slow, e destul de unreliable, browserele faileaza, testele trebuiesc rerulate, memory leakuri, containere care iti crapa random, etc. Practic, aceleasi probleme pe care le ai cu chrome-ul o sa le ai si cu e2e testingul. Deci nu prea poti sa testezi lumea reala, exact ce face un utilizator foarte usor. (P.S. Daca cineva are update-uri pe tema asta, please share, eu nu m-am mai uitat de 1 an pe asta, poate au aparut niste chestii noi care chiar merg in Docker)

Iti inteleg frustrarea, stay strong :metal: TDD-ul e misused deobicei ca si plasa de siguranta de catre managerii care nu stiu ce se intampla prin cod. Cumva trebuie sa-i intelegi si pe ei ca mizeria aia de code-coverage e singura statistica legata de cod si implementare care chiar o inteleg mai profund (doar nu te astepti sa se uite chiar atent pe code-review? :laughing: ) si care chiar le dau siguranta.

TDD-ul folosit bine, trebuie sa permita echipei sa dezvolte intr-un ritm rapid produsul fara frica de a strica ceva pentru a putea face deployuri dese si multe. Deasemenea, cel mai important: nu trebuie sa le intre developerilor in cale. Cred ca aici multi manageri/arhitecti esueaza ca se uita doar la bottom-line si le este frica/nu au incredere in echipa si de asta se bazeaza pe code-coverage ca un fel de salvare miraculoasa de la esec.

7 Likes

M-am ocupat un an bun cu QA, timp in care am dezvoltat propriul framework de testare e2e pentru un proiect foarte dificil de testat, adică nu azi m-am apucat de testare.

Acum tot eu scriu unele teste e2e, dar problema mea e cu unit testele (in special cele care verifica mutațiile in state - e muncă de sisif).

Probabil o strategie ar fi să scriu testele după ce am depășit un anumit număr de fișiere schimbate.
Doar că la o sesiune de peer programming o să depășesc sigur numărul propus.

Eu îmi limitez scopul unit testelor la documentarea codului și la asigurarea că dacă se schimbă/șterge o linie de cod atunci nu afectează altceva. Nu ține neapărat de calitatea produsului final, dar categoric e util la refacturare.