Dezvoltarea Eficientă cu Scrum: Dincolo de Prototipul Inițial
Un plan de testare minimal în Scrum poate fi comparat cu un Proof of Concept (POC) dus la extrem.
În prezent, majoritatea proiectelor de succes debutează cu un POC, o evaluare restrânsă a unei idei. Aici, se analizează tehnologia și funcționalitățile selectate, evaluându-se impactul potențial asupra utilizatorilor. Odată validată ideea ca fiind rentabilă, se formează o echipă completă care se ocupă de proiectarea, dezvoltarea produsului complet și implementarea acestuia în producție.
Acesta este scenariul ideal pentru o echipă Scrum. Aceasta poate crea rapid un prototip, adăugând funcționalități importante la fiecare sprint. Utilizatorii pot monitoriza progresul în timp real, observând cum ideea prinde contur în aproximativ 10 sprinturi. Această abordare lasă o impresie puternică (scopul principal al unui POC), dar are și o particularitate: activități de testare minime sau inexistente. Chiar și ideea de a testa pare o glumă în acest context.
Nu este o activitate care să-i încânte pe membrii unei echipe Scrum, care preferă să dezvolte fără procese restrictive. Testarea, prin natura ei, tinde să încetinească procesul. Și cine ar dori încetinirea când obiectivul principal este impresionarea utilizatorului final?
Situația care apare dacă echipa continuă în același ritm după încheierea perioadei POC este ceea ce numesc un „POC pe steroizi” – un sistem în producție, care crește în dimensiune și complexitate, dar care se comportă ca un POC. Un produs complet, plin de erori ascunse și aspecte neexplorate, gata să cedeze la prima provocare.
Pe măsură ce proiectul avansează, echipei îi va fi din ce în ce mai dificil să mențină lansări stabile, deoarece rezolvarea problemelor devine tot mai complexă.
Vă prezint câteva tehnici care s-au dovedit eficiente în situații similare. Consider că acestea sunt cele mai bune practici pentru implementarea unor procese de testare solide, fără a compromite prea mult ritmul de dezvoltare – scopul oricărei echipe Scrum.
Distribuiți Efortul
Când ne confruntăm cu probleme nedorite, soluția este simplă: împărțirea efortului.
Mă refer la crearea unui plan care va necesita puțin efort suplimentar din partea dezvoltatorilor, dar care va contribui semnificativ la obiectivul comun pe termen lung, gradual și constant.
#1. Dezvoltarea Codului de Test Unitar pentru Fiecare Componentă Nouă
Dacă reușiți să convingeți echipele Scrum să includă în definiția sa de „Terminat” dezvoltarea testelor unitare pentru fiecare cod nou creat, pe termen lung, acesta va fi un mare succes.
Motivele sunt destul de clare:
- Va obliga dezvoltatorii să ia în considerare diverse căi non-standard ale codului.
- Aceste teste unitare pot fi integrate în pipeline-urile DevOps și rulate la fiecare implementare în mediul de dezvoltare sau de testare. Valorile rezultate pot fi exportate și utilizate pentru a arăta utilizatorilor gradul de acoperire a cazurilor de testare, direct legat de codul sursă.
Cel mai important este să începeți cât mai repede. Cu cât testele unitare sunt dezvoltate mai târziu, cu atât va fi mai dificil pentru dezvoltatori să le adauge în cadrul unui sprint.
- Va fi necesar un efort semnificativ pentru a dezvolta teste unitare pentru codul existent. Unele porțiuni de cod ar putea fi create de alt dezvoltator, iar cunoștințele exacte despre cum ar trebui să funcționeze fiecare parte a codului nu sunt întotdeauna clare. În unele cazuri, adăugarea unui test unitar la codul modificat poate dura mai mult decât dezvoltarea modificării funcționalității (o situație neprevăzută în timpul planificării sprintului).
#2. Crearea unei Rutine de Executare a Testelor Unitare în Mediul de Dezvoltare
Înainte de a crea o cerere de tragere pentru a uni codul nou în ramura principală, devine o practică standard testarea atât a codului caracteristicii, cât și a codului de testare unitară în mediul de dezvoltare. Astfel, se asigură că:
- Codul de test unitar funcționează corect pentru fiecare componentă (la urma urmei, este tot cod care trebuie verificat). Acest pas este adesea ignorat complet. Se presupune că, dacă testul unitar este integrat în pipeline-ul DevOps, acesta va fi executat și testat undeva în mod automat. Însă, aceasta înseamnă doar amânarea problemelor pentru etapele superioare ale sprintului, când echipa are mai puțin timp și mai mult stres pentru a finaliza fiecare sarcină.
- Noul cod de caracteristică este testat de dezvoltator pentru funcționalitatea de bază. Acest test nu va verifica complet funcționalitatea business, dar va confirma că codul se comportă conform intenției dezvoltatorului (ignorând, deocamdată, o eventuală neînțelegere a logicii de business în timpul dezvoltării).
#3. Executarea Testelor Unitare După Fuzionarea Codului în Ramura Principală
Este una să ai cod funcțional în ramura locală (unde doar dezvoltatorul lucrează la o nouă funcționalitate), dar este cu totul altceva ca același cod să funcționeze după cererea de tragere și fuzionarea în ramura principală.
Ramura principală conține modificări de la alți membri ai echipei Scrum. Chiar dacă conflictele sunt rezolvate, codul rezultat este, practic, o altă porțiune netestată, fiind riscant să o trimitem mai departe fără a ne asigura că funcționează corect.
Astfel, este eficient să solicităm executarea aceluiași test unitar, realizat anterior în mediul de dezvoltare, și în mediul construit din versiunea codului ramurii principale.
Pentru dezvoltatori, acesta ar putea fi un pas suplimentar, dar nu necesită un efort considerabil. Nu trebuie creat nimic nou, ci doar repetat ceva ce a fost deja făcut.
Acest pas poate fi omis în anumite cazuri:
- Testele unitare automate din pipeline-urile DevOps sunt atât de extinse încât acoperă și testarea manuală realizată anterior.
Deși atingerea acestui nivel este fezabilă, nu am întâlnit niciodată această situație în practică. Ar necesita prea mult timp din partea dezvoltatorilor să creeze teste unitare automatizate atât de detaliate. Proprietarul produsului ar putea refuza ca echipa să dedice atât de mult timp acestei activități, deoarece ar influența direct numărul de sarcini finalizate într-un sprint.
Preferința pentru conținutul sprintului nu trebuie să fie o scuză pentru a neglija sau minimaliza testele unitare. În caz contrar, echipa se va confrunta din nou cu o acoperire insuficientă a testelor unitare, iar recuperarea va fi dificilă (efortul de finalizare a testelor unitare devenind mai mare decât cel de modificare a codului pentru un sprint).
Din aceste motive, recomand reexecutarea testelor unitare pe versiunea de cod master fără ezitare. Efortul este minim în comparație cu valoarea adăugată.
Acest lucru asigură că ramura principală este pregătită pentru testarea lansării. Va ajuta și la identificarea majorității erorilor tehnice, permițând următoarei faze să se concentreze exclusiv pe verificarea funcționalității business.
Pregătirea pentru Testarea Funcțională
Toate activitățile de testare anterioare conduc la o concluzie importantă: codul din ramura principală este lipsit de erori tehnice și poate fi executat fără probleme în fluxurile funcționale end-to-end.
Această fază poate fi realizată cu ușurință de o singură persoană, care nici măcar nu trebuie să aibă cunoștințe tehnice.
De fapt, este preferabil ca aceasta să fie realizată de cineva independent de dezvoltatori, dar care înțelege modul în care utilizatorii business se așteaptă să se comporte codul. Sunt două activități principale de realizat:
#1. Testarea Funcțională a Noilor Sarcini din Sprint
În mod ideal, fiecare sprint ar trebui să aducă funcționalități noi (creșterea obiectivului sprintului). Este important să ne asigurăm că noua parte software funcționează corect, astfel încât utilizatorii business să fie mulțumiți. Ei așteaptă cu nerăbdare această funcționalitate.
Este dezamăgitor când funcționalitatea promisă este lansată, doar pentru a constata că nu funcționează corect.
De aceea, testarea corectă a noilor funcționalități din sprint este crucială. Pentru a asigura succesul, este recomandabil să colectăm din timp cazurile de testare relevante de la părțile interesate (proprietarul produsului sau utilizatorii finali) și să creăm o listă cu toate testele necesare pentru conținutul sprintului.
La prima vedere, poate părea complex, dar experiența arată că este gestionabil de o singură persoană. Sprinturile sunt de obicei scurte (două săptămâni), iar conținutul nou nu este foarte mare, deoarece sprintul include și activități suplimentare (sarcini tehnice, documentație, design).
Cazurile de testare sunt executate cu scopul de a verifica funcționalitatea dorită. Dacă apar probleme, este contactat doar dezvoltatorul responsabil pentru rezolvarea defectului.
Astfel, dezvoltatorii vor dedica timp minim testării funcționale și se pot concentra în continuare pe activitățile preferate.
#2. Executarea Testelor de Regresie
Cealaltă parte a testării funcționale este verificarea faptului că funcționalitățile existente continuă să funcționeze după următoarea lansare. Pentru asta sunt testele de regresie.
Cazurile de testare pentru regresie trebuie actualizate și revizuite periodic înainte de fiecare lansare. În funcție de proiect, acestea trebuie să fie simple, dar să acopere funcționalitățile de bază și fluxurile importante care traversează întregul sistem.
De obicei, fiecare sistem are procese care ating domenii diferite, acestea fiind candidații ideali pentru cazurile de testare de regresie.
În unele cazuri, testele de regresie acoperă implicit și funcționalitățile noi din sprint, de exemplu, dacă noua sarcină modifică o anumită parte a unui flux existent.
Așadar, nu este dificil să finalizezi testele de regresie împreună cu testarea funcțională a noilor sarcini, mai ales dacă acest lucru se întâmplă regulat înainte de fiecare lansare și dacă lansările nu sunt foarte frecvente.
Insistați pe Testele de Asigurare a Calității Înainte de Fiecare Lansare
Testul de asigurare a calității (QA) este pasul final înainte de lansarea în producție. Adesea, este omis, fiind considerat neimportant, mai ales dacă echipa Scrum este presată pentru conținut nou.
Chiar și utilizatorii business pot spune că sunt interesați de noi funcționalități și nu de menținerea celor existente sau reducerea numărului de defecte. Dar, pe termen lung, aceasta este cauza principală a încetinirii echipei de dezvoltare, iar utilizatorii nu vor primi nici ei ceea ce își doresc.
Testul QA trebuie realizat de persoane din afara echipei Scrum, ideal de către utilizatorii business într-un mediu dedicat, cât mai apropiat de mediul de producție. Alternativ, proprietarul produsului poate înlocui utilizatorii finali.
În orice caz, acesta trebuie să fie un test funcțional, realizat din perspectiva utilizatorului, fără legătură cu echipa dev Scrum. Acesta va prezenta o viziune finală asupra produsului, posibil într-un mod neașteptat de echipa Scrum (un caz deloc ideal, dar posibil). Este încă timp pentru corecții de ultim moment.
Alternativ, poate deveni clar că așteptările nu au fost bine înțelese de echipa Scrum, caz în care se poate conveni asupra unui plan de acțiune, înainte de lansarea în producție. Nu este un scenariu ideal, dar este preferabil decât să admitem eșecul imediat după o lansare considerată un succes.
Ce urmează?
Aplicarea acestor practici în activitatea zilnică Scrum va duce la lansări mai stabile și previzibile, fără a întârzia lansările în producție, fără a petrece tot sprintul pregătindu-vă pentru următoarea lansare sau fără a forța echipa să facă ceva ce nu-i place sau nu știe cum să facă eficient.
Dar nu trebuie să vă opriți aici.
Un subiect important este includerea testelor de performanță. Acestea sunt adesea ignorate, fiind considerate inutile. Însă, este greu de crezut că un sistem de producție poate evolua în timp fără verificări periodice ale performanței.
Un alt pas înainte este introducerea testelor automate.
Am acoperit deja testele automate unitare. Dar, puteți dezvolta și teste complete de regresie, automatizate end-to-end, care să ruleze după fiecare implementare în mediul de testare. Această abordare ar elibera și mai mult echipa de dezvoltare, dar necesită o echipă dedicată pentru dezvoltarea și întreținerea testelor automate. Ar fi o muncă constantă, deoarece, la fiecare modificare a codului, testele automate existente ar putea deveni invalide și ar trebui actualizate. Este un efort pe care puțini sunt dispuși să îl suporte, deși beneficiile pentru echipa dev Scrum ar fi semnificative.
Aceste subiecte depășesc scopul acestui articol. Este necesar să găsiți un program și un calendar potrivit pentru fiecare tip de test menționat, astfel încât să încadrați activitățile într-un sprint. Voi aborda aceste aspecte data viitoare!