Spesso il software prodotto con approcci tradizionali non risponde alle reali esigenze del cliente (scarsa qualità esterna).
Anche se ci si sofferma molto sulle attività di specifica dei requisiti, si corre il rischio di concedere più tempo ai cambiamenti delle esigenze reali!
Spesso il software è di qualità interna scadente (per i tempi rapidi di consegna, le tecnologie mutevoli, la quantità di software richiesta):
È un approccio evolutivo allo sviluppo software in cui si scrive prima un test che fallisce, e poi si scrive il relativo codice.
Differisce dagli approcci tradizionali, in cui prima si scrive il codice e poi (forse) lo si testa.
TDD è uno stile di sviluppo/ progettazione, non è una tecnica di testing.
In TDD la programmazione e lo unit test non sono attività separate.
In TDD, si può scrivere nuovo codice solo se un test automatico è fallito.
TDD Mantra: “Only ever write code to fix a failing test“.
Permette di scrivere software migliore e più rapidamente (costruendo software in piccoli incrementi- 1 test alla volta).
Evita la paura nello sviluppatore che:
Produce codice pulito e che funziona (in modo opposto allo sviluppo architecture driven, in cui si fanno prima tutte le decisioni).
Consente agli sviluppatori di produrre un insieme di test di regressione automatizzabili, man mano che sviluppano.
La presenza di difetti nel codice può dipendere dalla mancanza di test, o dalla mancata esecuzione di test che abbiano evidenziato tali difetti.
Invece:
Si trasformano i requisiti in una serie di test eseguibili, e poi si prosegue implementando codice che rispetta tali test, piuttosto che requisiti verbali mal compresi.
Red/Green/Refactor è il TDD mantra, e descrive I tre stati che si attraversano nello scrivere codice col TDD.
Scrivi un test che non funzionerà (red).
Fai in modo che il test funzioni, scrivendo solo il codice necessario a superarlo (green).
Migliora (ristruttura – il codice ed i test).
Esegui tutti i test per assicurarsi che non ci siano problemi.
Ripeti finchè non trovi altri test.
Fase Add a Test
Fase Run a Test
Quando tutti i test saranno passati, si può pensare a migliorare il codice prodotto.
Si può pensare ad eliminare codice duplicato, a migliorarne l’espressività, riducendo l’accoppiamento e migliorandone la coesione.
Dopo il Refactoring, i test vanno rieseguiti.
Se i test non passano (Red) è stato fatto qualche errore col refactoring che dovrà essere corretto, per far di nuovo passare tutti i test (Green).
Questi passi vanno ripetuti fino a che non si riusciranno a trovare altri test per scrivere nuovo codice.
La definizione di Martin Fowler [1]:
Restructuring of software by applying a series of internal changes that do not affect its observable behavior:
[1] Refactoring: Improving the Design of Existing Code, Martin Fowler, Addison-Wesley (1999)
Si vuole sviluppare un motodo che, dati due Interi, restituisce l’intero che è la somma dei due parametri.
L’XP è un metodo agile.
Il TDD è una pratica agile che nasce dalla combinazione di due concetti fondamentali dell’XP:
Il TDD è una pratica che può essere applicata anche senza le altre pratiche dell’XP.
Lo scopo del TDD è di ridurre la distanza fra decisioni e feedback durante lo sviluppo.
Un test non è di unità se:
Per eseguire lo Unit Test possono essere necessarie le Fixture ed i Test Doubles (Doppioni).
Fixture
Test Doubles
I moduli testati hanno bisogno di essere chiamati (dai Driver).
I moduli chiamati devono essere sostituiti da altri (Stub).
I Mock-Objects non sono Stub! [Fowler]
In genere lo stub è molto più semplice di un Mock-Object.
Gli stub forniscono risposte preconfezionate (con valori prefissati) a chiamate fatte durante il test, senza rispondere di solito a nulla che sia al di fuori di ciò che è previsto per il test.
I mock hanno implementazioni più sofisticate che consentono di verificare il comportamento dell’unità testata (e non solo lo stato)
verificando ad esempio le collaborazioni avute con altri oggetti ed il relativo ordine di esecuzione.
Tratto da: Test Driven - Practical TDD and Acceptance TDD for Java Developers (Lasse Koskela)- Manning Ed. 2008.
Un mock object è una simulazione di un oggetto reale.
Implementa l’interfaccia dell’oggetto da simulare ed ha il suo stesso comportamento.
Possono fornire una risposta pre-impostata.
Possono verificare se l’oggetto che li usa lo fa correttamente.
Utilissimi per testare unità senza legarsi ad oggetti esterni.
Vediamo come attraverso un esempio.
Es.: La classe Client (da testare) usa i metodi di Helper.
Ma la classe Helper non può essere usata perché:
public class MockHelper implements IHelper
{
public MockHelper ( )
{
}
public Object helperMethod( Object aParameter )
{
Object result = null;
if ( ! aParameter.toString().equals("expected" )
{
throw new IllegalArgumentException( "Unexpected parameter: " + aParameter.toString() );
}
result = new String("reply");
return result;
}
}
In genere i Mock sono in grado di fare controlli sul comportamento dell’oggetto testato e sulle sue interazioni con altri oggetti.
Lo sviluppo di Mock Objects è supportata da diversi frameworks, o librerie (come JMock in Java).
É un Framework per creare mock objects a run time.
Usa le Java reflection per creare una classe mock object che implementa una certa interfaccia.
É un progetto open source project ospitato su SourceForge.
Testing Frameworks
Test framework per il Test di Accettazione
Ci sono strumenti come Fit e Fitnesse, incentrati su tabelle per descrivere i test eseguibili e che impiegano forme visuali per facilitare la collaborazione tra developers, testers, e business analysts con nontechnical stakeholders.
Strumenti per supportare Continuous Integration
La definizione di Martin Fowler:
È una pratica di sviluppo software in cui i membri del team di sviluppo integrano il proprio lavoro frequentemente, almeno una volta al giorno. Ogni integrazione è verificata da strumenti automatici che eseguono il build e riesegueno tutti i test sulla nuova configurazione, per trovare errori di integrazione rapidamente.
2. Ciclo di Vita e Processi Software
3. Processi per lo sviluppo rapido del software
4. Sviluppo Agile del Software
5. Test Driven Development (TDD)
7. Component Based Software Engineering (CBSE): Generalità
8. Component Based Software Engineering (CBSE): Il processo di svi...
9. Ingegneria del Software orientato ai Servizi
10. Ingegnerizzazione dei Servizi
11. I Processi di Manutenzione del Software
12. Reengineering, Refactoring e Reverse Engineering del Software
13. Verifica e Convalida del Software. Richiami e concetti di base ...
14. Tecniche di Testing Dinamico
15. Testing di Sistemi Object Oriented
16. Automazione del testing e Analisi Mutazionale
17. Tecniche di Analisi Statica del codice e il Debugging
18. Stima dei costi nei progetti Software
19. Il Modello COCOMO per la stima dei costi Software – La gestio...
20. Gestione e Miglioramento dei Processi di Produzione del Softwar...
21. La Valutazione della Qualità dei Processi Software – Il Capa...
D. Janzen, Test-Driven Development:Concepts, Taxonomy,and Future Direction, IEEE Computer-2005
Extreme Programming Explained (Kent Beck) – 1st and 2nd Edition
Test Driven Development (Kent Beck)
Test Driven : Practical TDD and Acceptance TDD for Java Developers (Lasse Koskela)