Il test-driven development (TDD) è un approccio allo sviluppo software che si basa sulla trasformazione dei diversi requisiti di un programma in una serie di test progressivi, prima che il software sia completo e completamente funzionante. Questo metodo è diverso dall’approccio classico alla programmazione che prevede prima la costruzione del software e solo successivamente la fase di testing. Nel test-driven development i test vengono scritti prima che venga scritto il codice. In questo articolo parliamo proprio di questo, cercando di spiegare cos’è il test driven development e come funziona il ciclo di lavoro di questo modello di sviluppo software.

Test-driven development

Il test-driven development è un approccio allo sviluppo software che sovverte la pratica comune con cui gli sviluppatori hanno scritto programmi per molti anni. Il modello classico alla programmazione prevede infatti che prima il software venga scritto e solo successivamente testato. Il test-driven development sovverte il modello classico della programmazione identificando prima i test per poi, solo successivamente, passare alla fase di scrittura del codice.

Il “padre” del test-driven development è Kent Beck, informatico statunitense e uno dei padri fondatori dell’extreme programming e del metodo agile. Beck nel suo libro Test Driven Developing: By Example del 2002 espone i principi e le applicazioni di questo modello di sviluppo software. La premessa alla base del TDD è che prima di iniziare a scrivere codice, bisogna scrivere il test. Il codice che viene scritto di conseguenza, dovrebbe essere testato e rifattorizzato continuamente.

Secondo Kent Beck questo modello non solo favorisce la produzione di software di qualità maggiore, ma consente anche agli sviluppatori di lavorare più serenamente, con maggiore fiducia nella propria capacità di risoluzione dei problemi e con meno stress.

Il ciclo del test-driven development

La regola aurea della TDD è riassumibile nella frase “Se non puoi scrivere un test per quello che stai per programmare, allora non dovresti nemmeno pensare di programmare”

“if you can not write a test for what you are about to code then you should not even be thinking about coding” Huang & Holcombe, 2009

Secondo il modello TDD, lo sviluppo di un qualsiasi programma dovrebbe seguire una serie di step che si ripetono in modo ciclico per ciascuna componente del software che si vuole implementare. Il ciclo del test-driven development è formato da un loop di 5 step che iterano fino alla conclusione del progetto e sono:

  1. Scrivi un test
  2. Esegui il test e valuta se fallisce
  3. Scrivi il codice in modo che il test non fallisca
  4. Esegui il test e vedi se il codice passa il test
  5. Fai refactoring del codice per renderlo migliore

Questi 5 step vanno implementati ogni volta che si desidera aggiungere una feature al programma in sviluppo.

ciclo del test driven development

Di Xarawn – Opera propria, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=44782343

Ora proviamo a spiegare passo dopo passo ogni singolo step del modello. Si parte, ovviamente, dallo step1.

1.Scrivi il test

Il primo step del test-driven development, decisamente il più controintuivo, è quello di scrivere prima il test del codice del programma. Il test dovrebbe essere specifico e coprire tutti i possibili casi che potrebbero verificarsi.

Facciamo un esempio, se si vuole aggiungere ad un programma una funzione che calcoli la media di due numeri, bisognerebbe scrivere un test che copra tutti i casi possibili, quindi sia numeri positivi che negativi, sia che questi siano interi o frazioni etc.

Questo passaggio aiuta a pensare a tutti i diversi casi che il tuo codice dovrà poi gestire. Ed è fondamentale!

2.Esegui il test e valuta se fallisce

Il secondo step nel test-driven development è l’esecuzione del test, per vedere se fallisce oppure no. Ovviamente ci si aspetta che il test fallisca. Anche questo passaggio è importante perchè da un valore al tuo test, ossia ti dice se ciò che hai scritto sta verificando realmente quello che vuoi verificare.

Se il test fallisce, questo significa che il tuo codice non fa ancora quello che vorresti. Buona notizia, puoi passare al punto 3. Se il test non fallisce, allora c’è un problema. Forse il test è troppo semplice o davvero poco specifico.

Oppure qualcuno ha già scritto una parte di codice e tu non lo sai…magari un tuo collega particolarmente scrupoloso ha fatto le ore piccole e si è dimenticato di seguire il modello. Possibile in un mondo non deterministico…ma altamente improbabile. Comunque se il test non fallisce torna al punto 1.

3.Scrivi il codice in modo che il test non fallisca

Dopo che hai appurato che il tuo test ha fallito, devi scrivere il codice del programma in modo da superarlo. Questa è ovviamente la parte centrale del test-driven development, perchè stai letteralmente scrivendo il codice che ti serve.

É importante scrivere solamente la minima parte di codice necessario perchè il programma passi il test. Infatti non ha molto senso scrivere più codice di quello che ti serve, perchè sarebbe una perdita di tempo. E il tempo è una risorsa finita, non abusarne, hai anche una vita….forse 😉

4. Esegui il test e vedi se il codice passa il test

Dopo che hai scritto il tuo codice, riesegui il test. Se lo supera, congratulazioni! Hai appena scritto del codice che fa quello che desideri! Ricorda però, il codice che hai scritto probabilmente non è perfetto, quindi non affezionartici troppo. Il prossimo step del test-driven development è quello in cui lo migliorerai.

Se invece il codice non passa il test, non ti preoccupare, torna allo step 3 e prova ancora. Se hai già implementato alcuni test dovrai eseguirli tutti. Se qualcuno fallisce rimetti mano al codice finche tutti i test non passano. Ma se sei stanco….cerca di riposare o pensare ad altro…le idee migliori arrivano quando non stai pensando troppo al problema.

5. Fai refactoring del codice per renderlo migliore

L’ultimo step del test-driven development prevede una fase di refactoring del codice per migliorarlo. Questo significa ottimizzare il design del codice, renderlo più leggibile, più efficente etc. E’ importante questo passaggio perchè ti aiuta a evitare di scrivere cattivo codice che diventa difficile da mantenere e da comprendere. A volte questo step viene chiamato “code review”, perchè stai effettivamente revisionando il codice nel tentativo di renderlo migliore.

Una volta che hai il codice migliorato, manco a dirlo, re-runna tutti i test. Se almeno uno non passa, hai rotto qualcosa. Ma puoi ritornare immediatamente sul codice e capire dove si trovi il bug, risolverlo e ritestare tutto quanto. Quando tutti i controlli sono passati puoi ritornare allo step 1 per una nuova feature.

Il ciclo del test-driven development è quindi iterattivo. Una volta conclusosi il processo, si riparte, con lo stesso rigore metodologico e la stessa impostazione.

Perchè usare il test-driven development?

In conclusione, perchè usiamo il test driven development nella gestione dei nostri progetti? Perchè lo riteniamo un ottimo modello per sviluppare codice, questo infatti ci costringe a pensare a cosa vuoi che il codice faccia davvero, prima ancora di scriverlo. Ci aiuta a scrive codice migliore perche abbiamo chiari obiettivi in mente che possiamo testare e valutare step by step.

É inoltre molto comodo perchè ci consente di identificare i bug prima, proprio perchè se il test è costruito bene e il codice non funziona, allora il test fallirà. Inoltre pensiamo sia un ottimo modo anche per imparare “come” programmare, perchè aiuta a farsi le domande giuste prima ancora di iniziare a scrivere del codice.

Aumenta anche il nostro senso di autoefficacia, ci sentiamo più in grado di gestire progetti importanti, senza farci spaventare troppo dalle tante insidie della programmazione. Certo non è un modello esente da limiti. Ma ci riserviamo per un prossimo articolo la nostra condivisione sui limiti del modello e i suoi punti deboli.

E i vantaggi per il cliente finale?

Il cliente vorrebbe sempre che il codice lavori come ha richiesto, che i programmi funzionino bene e che non ci siano problemi. E spesso si stupiscono…perchè il codice che programmiamo funziona davvero così!

Con il test-driven development siamo più tranquilli che il codice lavori come dovrebbe, perchè abbiamo già verificato serialmente la sua funzionalità.

Note

Beck, K. (2002). Test Driven Development: By Example. In AddisonWesley Longman. Retrieved from http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530

Desai, C., Janzen, D., & Savage, K. (2008). A survey of evidence for test-driven development in academia. ACM SIGCSE Bulletin, 40(2), 97–101. https://doi.org/10.1145/1383602.1383644

Huang, L., & Holcombe, M. (2009). Empirical investigation towards the effectiveness of Test First programming. Information and Software Technology, 51(1), 182–194. https://doi.org/10.1016/j.infsof.2008.03.007

Munir, H., Moayyed, M., & Petersen, K. (2014, April 1). Considering rigor and relevance when evaluating test driven development: A systematic review. Information and Software Technology, Vol. 56, pp. 375–394. https://doi.org/10.1016/j.infsof.2014.01.002

Nolan, G. (2017). Test Driven Development. In Agile Swift (pp. 131–167). https://doi.org/10.1007/978-1-4842-2102-0_6

Shull, F., Melnik, G., Turhan, B., Layman, L., Diep, M., & Erdogmus, H. (2010). What do we know about test-driven development? IEEE Software, 27(6), 16–19. https://doi.org/10.1109/MS.2010.152