Test Driven Development (TDD) sauDevelopments Driven by testsîn franceză, este o metodă dedezvoltare software, care este de a proiecta unsoftwareîn pași mici, iterativ și incremental, scriind fiecare test înainte de a scriecod sursăși de a revizui codul continuu.
Inițial, tocmai scria testele înainte de codificare și se numea Test First Design . Apoi metoda a evoluat către o granularitate mai fină de dezvoltare: pentru o linie de test eșuată, se scrie o linie de producție de cod pentru a trece testul. Pentru a confirma această granularitate linie-linie între codul de testare și codul de producție, au apărut trei legi.
Aceste legi au diferite variante foarte asemănătoare între 2005 și 2008 (2005, 2006, 2007 și 2008), încă scrise de Robert C. Martin: sunt prezentate aici în conformitate cu termenii folosiți în 2008. Cu toate acestea, utilizarea expresiei „ testul unitar "în aceste legi este în mare parte confuz aici. Prin testul unitar, aceste legi nu desemnează un caz de test complet, ci de fapt o singură afirmație de test. Cazul complet de testare ar trebui obținut după ce a iterat de mai multe ori toate aceste 3 legi, știind că rezolvarea unei erori de compilare constituie deja o iterație în sine. În 2014, Robert C. Martin reformulează cele trei legi ale TDD și termenul „unitar” dispare.
Mai degrabă, o formulare exactă și fără ambiguități a acestor 3 legi ar fi după cum urmează.
Se face astfel o distincție între afirmația care a determinat eșecul testului și testul care eșuează în timpul executării sale. În plus, nu presupunem cea mai adecvată formă de test și nici nu ne restrângem la un singur posibil, care este cu atât mai pragmatic. Faptul de a pune cap la cap cele 3 legi ale TDD într-o singură iterație constituie ceea ce se numește un nanociclu al TDD. Rețineți că aceste 3 legi acoperă doar condițiile care trebuie respectate în TDD pentru a ajunge la un test de succes, exprimând minimalismul așteptat de la testul eșuat.
Procesul recomandat de TDD are cinci etape:
Acest proces se repetă în mai multe cicluri, până când problema inițială este complet rezolvată. Aceste cicluri iterative de dezvoltare sunt numite micro-cicluri ale TDD.
Testele utilizate în TDD fac posibilă explorarea și specificarea necesității, apoi specificarea comportamentului dorit al software-ului în funcție de utilizarea acestuia, înainte de fiecare etapă de codificare. Software-ul astfel produs este conceput atât pentru a satisface cu exactitate nevoia, cât și conceput pentru a face acest lucru cu o complexitate minimă . Acest lucru are ca rezultat un software mai bine conceput, mai bine testat și mai fiabil, cu alte cuvinte de o calitate mai bună.
Când testele sunt scrise după codificare, așa cum se întâmplă în mod tradițional, opțiunile de implementare constrâng scrierea testelor: testele sunt scrise conform codului și, dacă unele părți ale codului nu sunt testabile, nu pot fi testate. să nu fie testat. Dimpotrivă, testând înainte de codificare, folosim codul înainte de implementarea acestuia, astfel încât constrângerile definite de teste să fie impuse implementării: codul este scris conform testelor. Faptul de a scrie testele înainte de cod în TDD este, prin urmare, la originea implementărilor testabile, adică ușor de testat și 100% testabil. Cu toate acestea, testabilitatea codului promovează un design mai bun prin cuplare slabă și coeziune puternică, care evită erorile de proiectare obișnuite.
Deoarece fiecare test corespunde unei modificări minime a codului, un test face posibilă stabilirea unei conexiuni evidente între o regresie și sursa acesteia dacă nu reușește. Această legătură face din execuția testelor un moment esențial într-un ciclu TDD: captăm starea instantanee a software-ului și detectăm orice regresie în urma ultimei modificări. Într-adevăr, vrem cu orice preț să evităm modificarea codului în prezența unei regresii. Dacă da, nu se poate spune cu certitudine dacă testele eșuate se datorează schimbării actuale sau unei modificări anterioare. În acest sens, testele deja scrise constituie un ham împotriva accidentelor, desigur, unde s-ar pierde legătura dintre schimbare și regresie. Prin urmare, prezența unui astfel de ham face posibilă luarea în considerare cu seninătate a oricărei modificări de cod, indiferent dacă este vorba despre o transformare (modificare care afectează comportamentul) sau o reorganizare (modificare care nu modifică comportamentul), precum și livrările de software de la versiune la versiune.
Provocarea schimbărilor ciclice de cod este de a realinia proiectarea codului cu nevoile cunoscute, pentru a combate entropia software și a preveni datoria tehnică . Schimbarea proiectării codului fără a-și modifica comportamentul necesită testarea care asigură că nu există regresie. Pentru aceasta, ar trebui să folosim diferite forme complementare de testare, pentru a nu le rescrie la fiecare prelucrare a codului, indiferent de amploarea prelucrării: uneori teste pentru a verifica rezultatele exacte ale unui tratament, alteori teste pentru a verifica dacă componentele funcționează corect împreună , fără ca aceste teste diferite să se rupă din aceleași motive.
Deoarece testele sunt scrise înainte de codificare, acestea găsesc mai multe utilizări în TDD: ele servesc mai întâi pentru a rezolva o problemă prin ghidarea codificării prin fiecare pas, apoi furnizează un ham de teste împotriva regresiilor și, în cele din urmă, documentează comportamentul software-ului . Datorită utilizării testelor, TDD economisește productivitatea în mai multe moduri.
Când doi oameni se reunesc în perechi pentru a rezolva o problemă de programare, aceștia ocupă alternativ două roluri similare cu cele ale unui echipaj de mașină de raliu : șoferul, care deține cheia, codul, în timp ce primul ofițer supraveghează, face un pas înapoi și îl ghidează pilot în etape, apoi rolurile sunt schimbate la intervale regulate. Prin aplicarea TDD, o pereche poate schimba rolurile în moduri diferite: fie între două cicluri de dezvoltare atunci când iterați, fie între scrierea unui nou test eșuat și codarea unui nou comportament. A doua modalitate de schimb de roluri ne obligă să separăm preocupările testului de cele ale implementării și pune copilotul să contribuie doar la scrierea testului, în timp ce primul permite desfășurarea unui ciclu complet în timp ce ocupă același rol.