The road to a Service Oriented Architecture is paved with messages
Test Driven Development @ Xe.Net
1. T.est D.riven D.evelopment
TDD or not TDD, that is the question...
» Mauro Servienti
Microsoft MVP - Visual C#
http://blogs.ugidotnet.org/topics
mauro.servienti@gmail.com
5. Agenda
» Perchè non testiamo e quali sono le conseguenze;
» Perchè testiamo e quali sono i vantaggi;
» Come il testing modifica il nostro modo di scrivere
codice, e perchè io ritengo sia un bene;
» Ha senso cercare di testare tutto?
» Anatomia dello Unit Testing;
» Introduzione a metodologie fortemente basate sul
testing: TDD e Test First;
» TDD: ne vale la pena?
7. Sondaggio
» Su le mani... E non mentite
Usate Unit Test(s)?
No?, perchè?
Avete mai fatto TDD?
No?, perchè?
8. Partiamo dalla fine...
» Ammettiamolo testare costa, e costa un sacco...
• In molti casi gli strumenti sono ancora immaturi;
• Non abbiamo un “compilatore” che, se non
scriviamo i test, non compila...;
• Non percepiamo il valore dei test perchè non
misuriamo quanto ci costano i bug;
» Shawn Farkas (il saggio mangiatore di
caramelle) una volta disse...
9. Quale è il problema:
» Noi scriviamo stupidaggini ;-):
• E’ inevitabile il software contiene bug;
» Noi non scriviamo la documentazione...:
• Il problema non è detto che sia la pigrizia e tenere la
sincronia è veramente oneroso;
» Qualcuno ci chiede le modifiche... e le vuole ieri:
• E’ colpa nostra, abbiamo abituato noi il cliente a tempi di
risposta rapidi;
• Ci limitavamo a scrivere la funzionlità... E i bug? Dopo..
» Purtroppo ci tocca modificare codice “legacy”;
10. Possiamo arginarlo...?
» Scriviamo stupidaggini:
• Keep it simple: possiamo asserire che se n parti
funzionano singolarmente allora funzioneranno
insieme? Si, quello che non sappiamo è se il
prodotto sarà quello atteso... ma è già un inizio;
• Single Point Of Responsability: non diamo troppe
responsabilità al nostro codice, anzi diamone una
sola;
• Compisition, composition, composition: creare
sinergia tra i componenti.
11. Possiamo arginarlo...?
» Noi non scriviamo la documentazione:
• Qualcuno dice che il codice è la documentazione,
secondo me è sbagliato, ma...:
• La documentazione è necessaria;
• La documentazione costa (in termini di fatica e non solo);
• Quindi perchè non scrivere un buon codice che sia parte
intergrante della documentazione?
• Facciamo un parallelo con il Code Coverage:
• 100% (C.C.) : 20% (C.C.) = Buon Codice : “Cattivo” Codice
• Un buon codice non è la documentazione ma è
nettamente meglio come il 100% di CC non è garanzia di
buon testing...ma il 20% è certezza di non testing...;
12. Possiamo arginarlo...?
» Qualcuno ci chiede le modifiche... e le vuole ieri;
» Purtroppo ci tocca modificare codice “legacy”;
• Questo è il vero problema, noi non abbiamo...
14. Confidenza, so what?
» Noi non conosciamo il nostro codice:
• Quante volte aprite una solution vecchia di sei mesi
e la prima domanda che vi fate è: funzionerà...?
• Quante volte “mettete mano” a codice:
• Vecchio: perchè il cliente vi chiede una modifica;
• Altrui: perchè qualcuno del team è semplicemente
ammalato;
• E vi chiedete: ma cosa si spaccherà?
• Lo sapete già che si spaccherà... , quello che non sapete
è dove...
15. Confidenza, so what?
» Chi ha confidenza con il codice?
• Il codice stesso...
• Quindi perchè non scrivere codice che ci garantisca
la confidenza?
• Fosse facile...
» Perchè ci serve la confidenza?
• Regressioni, regressioni e regressioni;
17. Testing, Architettura e Design:
» Cosa abbiamo visto:
• Siamo partiti da codice non testabile;
• L’impossibilità di non testare è uno smell:
• Questo ci ha detto che il design probabilmente non era dei
migliori, se non è facilmente testabile viola il SPoR Princ.;
• Abbiamo ridisegnato con in mente il test:
• Abbiamo ottenuto qualcosa di facilmente testabile;
• Abbiamo migliorato il design;
» I test migliorano il design?
Non necessariamente ma sono sicuramente un buon giudice
18. Ci sono test e test...
» Unit Test(s):
• unit == unitario;
• Hanno lo scopo di testare una singola funzionalità alla
volta;
• Indipendenti: ogni singolo test vive (deve) di vita propria;
• Testano il comportamento non l’implementazione;
• Devono essere minimali (altrimenti smell);
» Integration Test(s):
• Le singole parti che funzionano, perchè testate, devono
dimostrare di lavorare correttamente anche insieme;
• Dagli Unit Test(s) ereditano l’indipendenza;
19. Anatomia: “AAA” keep it simple
» In ottica keep it simple un test deve rispettare la
regola AAA:
• Arrange: è la fase di setup del test;
• Act: è la fase in cui viene eseguita l’operazione sotto
test;
• Assert: è la fase in cui vengono verificare le
assunzioni;
» Perchè un test sia comprensibile e utile, anche la
terminologia è importante:
• Expected, Target e Actual;
20. Gli strumenti essenziali
» Ci sono casi in cui dobbiamo testare oggetti che
hanno parecchie dipendenze e rischiamo di
dedicare troppo tempo alla scrittura dei test (che
poi devono essere anche manutenuti)...
• Mock: è un oggetto fittizio che mima il comportamento
di un altro, il comportamento è verificabile (Assert);
• Stub: è un oggetto fittizio che mima passivamente il
comportamento di un altro in maniera non verificabile;
• Partial Mock: è un oggetto che eredita parte del
comportamento dall’oggetto che impersona, il
comportamento è verificabile;
22. Come il testing, fatto prima, modifica il nostro modo di fare tutto?
23. Anatomia
» Si scrive il test:
• Test Barra rossa, garantita ;-)
» Si implementa la singola funzionalità:
• Test Barra verde?;
» Refactoring, se necessario:
• Test Barra???
» Questo processo:
• porta a far emergere il design;
• Aiuta a focalizzarsi sui requisiti;
24. Come procedo...
» Ma come arriviamo a definire cosa dobbiamo
realizzare?
• Intervista con il cliente: spesso e volentieri con
l’operatore non con l’IT manager del cliente;
• Le User Story;
• La formalizzazione del processo in un linguaggio
comprensibile all’utente... niente UML ;-)
26. Le Storie
» l'utente deve essere in grado di fare il Dispatch di un messaggio;
» l'utente deve essere in grado di sottoscrivere un messaggio sulla base
del tipo del messaggio stesso;
» l'utente deve essere in grado di fare l'unsubscribe di uno specifico
handler;
» l'utente deve essere in grado di fare l'unsubscribe a tutte le
subscription sulla base del tipo del messaggio;
» l'utente deve essere in grado di fare l'unsubscribe a tutte le
subscription che il subscriber ha fatto a prescindere dal tipo di
messaggio e dall'handler stesso;
» Il dispatch di un messaggio deve notificare tutti i subscriber;
28. Come procedo...
» È stato difficile? Sni...
• Serve esperienza, parecchia, per essere produttivi;
• Servono gli strumenti adatti:
• Tool di refactoring evoluti;
» A cosa porta:
• Design, design e design.
• Ma è buon design? Non è detto, il rischio è che sia
un design focalizzato per i test:
• Ad esempio la visibilità di tutto è public perchè i tool non
aiutano in questa direzione;
» Abbiamo alternative?
29. Non solo TDD
» TDD » Test First
• Design emergente; • Design upfront;
• Necessita anche skill • Necessita skill solo nel
architetturali (Pair design dei test;
programming);
• L’uso dei contratti
• Sentire gli smell comporta evidenzia gli smell più
molta esperienza; facilmente;
• Posso fare refactoring: si • Posso fare refactoring: si
• Chi scrive il test non è • Chi scrive il test può
influenzato da come ha essere influenzato da
pensato il design; come ha pensato il design;
Quindi... ne vale veramente la pena?
30. TDD e Unit Testing: mutuamente esclusivi?
» Ma se faccio TDD/Test First posso evitare di fare
Unit testing?
• Assolutamente no;
• Lo scopo dei test è quello di coprire le possibili
casistiche di interazione tra il mondo esterno e il
blocco di codice testato:
• Quante casistiche abbiamo?: Int32 Add( Int32 a, Int32 b );
» Quali strumenti abbiamo: il nulla...
31. What’s next...
» VS2010 Good News: Code Contracts & PEX.
void SampleMethod( Int32 argument )
{
CodeContracts.Requires( argument > 0 );
...
}
Compile Time Warning(s): san csc.exe ;-)
Possibilità di distribuire i contratti separatamente;
Integrazione con PEX;
32. Introduzione a posterieriori in soluzione “legacy”;
» Abbiamo tonnellate di codice veramente legacy
non coperto da test... Che facciamo lo testiamo?
• E’ estremamente costoso perchè quasi certamente
non abbiamo codice facilmente “testabile”;
• Ha senso?:
• Se devo fare pesanti refactoring potrebbe avere senso
investire tempo per creare una suite di test per verificare
le regressioni;
• Potrebbe avere senso introdurre test ad ogni bug che
verifichiamo, sempre in ottica regressioni;