Introduzione al Test Driven Development

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    4 Favorites

    Introduzione al Test Driven Development - Presentation Transcript

    1. TEST-DRIVEN DEVELOPMENT Ennio Masi – 961/85 Prof. Sergio Di Martino Ingegneria del software 2 – 2007/08
    2. Sommario
      • Cos’è il TDD?
      • Il TDD e l’XP
      • Unit Testing e xUnit Framework
      • TDD Mantra
      • I princìpi
      • TDD Patterns
      • Legacy code
      • I tipi di test
      • Benefici e limiti
    3. Cos’è?
      • Test-Driven Development
      • Test-First Programming
      • Test-Driven Design
    4. Cos’è? (2)
      • E’ una tecnica iterativa di sviluppo del software.
      • L’obiettivo del TDD è il design del software, non la sua validazione .
    5. TDD e l’XP
      • Il TDD è una pratica agile.
      • L’XP è una metodologia agile.
    6. TDD e l’XP (2)
      • Il TDD nasce dall’estrazione di due concetti fondamentali dell’XP:
        • Test First Programming
        • Refactoring
    7. TDD e l’XP (3)
      • Il TDD è il cuore dell’ Extreme Programming .
      • TDD può essere applicato senza l’aggiunta delle altre pratiche dell’XP.
      • L’XP segna una strada da seguire per essere preparati ai cambiamenti futuri.
      • Il TDD cerca di controllare il gap tra le decisioni ed i feedback durante lo sviluppo.
    8. Obiettivi del TDD
      • Rendere lo sviluppo migliore e più rapido.
      • Mantenere il codice sempre documentato.
      • Ottenere codice flessibile e facilmente estendibile.
      • Diminuire la presenza di bug nel codice di produzione.
    9. Unit Testing e xUnit Framework
    10. Unit Test
      • Un test non è di unità se:
        • comunica con il database
        • comunica in rete
        • modifica il database
        • non può essere lanciato in parallelo ad altri test
        • bisogna effettuare diverse operazioni per lanciare il test
      “ Unit tests run fast. If they don’t run fast, they aren’t unit tests.”
    11. Unit Test ed il TDD
      • Sono rilasciati con il codice di produzione.
      • Nel TDD una funzionalità è rilasciata soltanto se vi è associata almeno uno Unit Test.
      • Consentono di effettuare il refactoring di una funzionalità senza “paura”.
      • Meno debugging.
    12. I Mock Objects
      • Un mock object è una simulazione di un oggetto reale.
      • Implementa l’interfaccia dell’oggetto da simulare ed ha il suo stesso comportamento.
      • Forniscono una risposta pre-impostata.
      • Servono per capire se l’oggetto che li usa lo fa correttamente.
      • Utilissimi per testare unità senza legarsi ad oggetti esterni.
    13. I Mock Objects (2)
      • Per superare una validazione utilizzando i mock, gli oggetti che li usano devono chiamare il metodo corretto con i parametri giusti e nell’ordine che ci aspettiamo. ( mock’s validation )
      • Un oggetto che semplicemente simula un oggetto reale, senza effettuare la verifica detta al punto precedente non è un mock, è uno stub .
      • Esistono implementazioni dei Mock Objects per moltissimi linguaggi. ( http://www.mockobjects.com )
    14. Esempio
      • Utilizzare un mock in questo caso consente di effettuare il testing senza l’ausilio del vero database di produzione.
      • Il mock deve avere la stessa interfaccia dell’oggetto che implementa il database e lo stesso comportamento dalla prospettiva del software client.
      L’esempio classico è quello di implementare un mock object che simuli la connessione ad un database:
    15. Esempio (2) DBConnection.java public interface DBConnection { void connect(); void close(); } public class MockDBConnection implements DBConnection { private boolean connected = false; private boolean closed = false; public void connect() {connected = true;} public void close() {closed = true;} public boolean validate(){ return connected && closed;} } MockDBConnection.java
    16. xUnit Framework
      • Ha diversi utilizzi
        • Design del software
        • Implementazione del codice
        • Debugging
        • Ottimizzazione delle performance
        • Quality Assurance (QA)
      E’ un tool software che consente di scrivere e lanciare unit test. E’ il core del TDD
    17. xUnit Framework (2)
      • JUnit
      • CppUnit
      • Nunit
      • PyUnit
      • vbUnit
      Nel 1999 Kent Beck presentò uno unit test framework per il linguaggio Smalltalk (SUnit) Da quel framework sono stati effettuati molti porting:
    18. L’architettura
    19. Assert Dal seminario su JUnit: “ Gli Assert sono metodi che consentono di asserire che una certa condizione è vera o falsa.”
    20. Assert (2)
      • assertTrue([message], condition) : Il test è superato se la condizione è vera
      • assertFalse([message], condition) : Il test è superato se la condizione è falsa
      • assertNull([message], Object) : Il test è superato se il riferimento all’oggetto è NULL.
      • assertNotNull([message], Object) : il test è superato se il riferimento all’oggetto non è NULL.
      • assertEquals([message], value1, value2) : il test è superato se value1 == value2.
      • assertNotEquals([message], value1, value2) : il test è superato se non vale che value1 == value2
      • fail() : wrapper di assertTrue(false)
    21. Assert (3)
      • (Teoria) Una regola generale è che ogni test deve contenere soltanto un assert.
      • (Pratica) Spesso i metodi di test contengono più assert oppure assert singoli ma composti da più condizioni legate da operatori logici.
    22. Testing degli errori
      • public void testXXX ()
      • {
      • try
      • {
      • //an operation
      • fail(“eccezione non avvenuta”)
      • }
      • catch (Exception e)
      • {}
      • ...
      • }
      • Questo test genera un’eccezione e controlla che sia gestito come ci aspettiamo.
      • Nell’esempio ci aspettiamo che sia lanciata l’eccezione nel momento i cui è chiamata anOperation .
      • Il test fallisce se l’eccezione non avviene, mentre va a buon fine se l’eccezione viene lanciata.
      • fail è equivalente ad assertTrue(false ) ma è più leggibile.
      E’ fondamentale testare la gestione degli errori. Viene utilizzato il metodo fail .
    23. Testing degli errori (2) public void testXXX () { try { //an operation } catch (Exception e) { fail(e.getMessage()); } ... } E’ fondamentale testare la gestione degli errori. Viene utilizzato il metodo fail .
      • Questo test genera un’eccezione e controlla che sia gestito come ci aspettiamo.
      • In questo esempio ci aspettiamo che non sia lanciata l’eccezione nel momento in cui è chiamata anOperation .
      • Il test fallisce se l’eccezione avviene, mentre va a buon fine se l’eccezione non viene lanciata.
      • fail è equivalente ad assertTrue(false ) ma è più leggibile.
    24. Il processo di sviluppo: TDD Mantra
    25. Le regole d’oro del TDD
      • Si scrive nuovo codice solo se un test automatico è fallito.
      • Eliminare i duplicati.
      Test-First Programming + Refactoring
    26. Implicazioni tecniche
      • Ogni programmatore scrive i propri test.
      • Fornire risposte rapide ai piccoli cambiamenti.
      • Codice con alta coesione e basso accoppiamento, altrimenti risulta difficile fare i test.
    27. TDD Mantra Primo step Think Think : ragionare per piccoli passi Focalizzarsi sul comportamento che il codice deve avere.
    28. TDD Mantra Think “ Vogliamo sviluppare una libreria aritmetica che agisca solo su numeri non negativi” Esempio aritLib.py
    29. TDD Mantra Think Esempio
      • Ragioniamo sulla somma:
        • Se in input vi sono due numeri non negativi, ritorniamo
      • la somma.
        • Se almeno uno dei due input è negativo allora ritorna -1
    30. TDD Mantra Secondo step Think Red Bar : scrittura dei test. Focalizzarsi sul comportamento della classe e la sua interfaccia pubblica. Red bar
    31. TDD Mantra Secondo step Think import aritLib import unittest class AritLibTest ( unittest.TestCase ): knownValues = ((0, 0, 0), (1, 1, 2), (2, 3, 5), (-1, -1, -1), (-10, 10, -1),(10, -5, -1), ) def testAdd ( self ): for x, y, sum in self .knownValues: result = aritLib.add(x, y) self .assertEquals(sum, result) Red bar
    32. TDD Mantra Secondo step Think ERROR : testAdd (__main__.AritLibTest) ---------------------------------------------------------------------- Traceback (most recent call last): File “AritLibTest.py”, line 11, in testAdd result = aritLib.add(x,y) AttributeError : 'module' object has no attribute 'add' ---------------------------------------------------------------------- Ran 1 test in 0.000s FAILED (errors=1) Red bar class AritLibTest ( unittest.TestCase ): knownValues = ((0, 0, 0), (1, 1, 2), (2, 3, 5), (-1, -1, -1), (-10, 10, -1),(10, -5, -1), ) def testAdd ( self ): for x, y, sum in self .knownValues: result = aritLib.add(x, y) self .assertEquals(sum, result) IL TEST FALLISCE PERCHE’ LA FUNZIONE ANCORA NON ESISTE!
    33. TDD Mantra Terzo step Think Red bar Green Bar Test fallito Green Bar : scrittura del codice. Scrivere solo il codice necessario per superare i test scritti in precedenza.
    34. TDD Mantra Terzo step Think Red bar Green Bar Test fallito aritLib.py def add (x, y): if x < 0: return -1 if y < 0: return -1 return x+y
    35. TDD Mantra Terzo step Think Red bar Green Bar Test fallito aritLib.py def add (x, y): if x < 0: return -1 if y < 0: return -1 return x+y ---------------------------------------------------------------------- Ran 1 test in 0.000 s ---------------------------------------------------------------------- OK Vengono lanciati i test scritti in precedenza senza modificarli.
    36. TDD Mantra Quarto step Think Red bar Green Bar Test fallito Refactoring Refactoring : semplificare ed aggiustare il desing della funzionalità sviluppata. In questa fase non bisogna assolutamente modificare la semantica della funzionalità implementata!
    37. TDD Mantra Quarto step Think Red bar Green Bar Test fallito Prima def add (x, y): if x < 0: return -1 if y < 0: return -1 return x+y Refactoring Dopo def add (x, y): if x < 0 or y < 0: return -1 return x+y
    38. TDD Mantra Quarto step Think Red bar Green Bar Test fallito Refactoring Dopo def add (x, y): if x < 0 or y < 0: return -1 return x+y ---------------------------------------------------------------------- Ran 1 test in 0.000 s ---------------------------------------------------------------------- OK Vengono lanciati i test scritti in precedenza senza modificarli.
    39. I princìpi Think Red bar Green Bar Test fallito Refactoring
      • “ Code once, test twice”
      • “ Clean code that works”
      • KISS: Keep It Short & Simple
      • YAGNI: You Ain’t Gonna Need It
    40. Quando fermarsi?
      • Quando il sistema effettivamente funziona.
      • Il sistema ha superato il 100% dei test.
      • Non c’è codice duplicato.
      • Il sistema dovrebbe avere meno classi e metodi possibile.
    41. Bad smells …
      • C’è qualcosa che non va se …
        • E’ necessario testare metodi privati/protetti.
        • Necessitiamo di testing White Box.
        • E’ necessario configurare il sistema prima di lanciare i test.
        • I test funzionano ad intermittenza.
        • I test sono molto lenti.
    42. Implicazioni sociali
      • Il TDD consente di “gestire” le paure durante lo sviluppo.
      • La paura ha molti aspetti negativi durante lo sviluppo:
        • rende incerti
        • toglie la voglia di comunicare
        • rende timorosi davanti ai feedback
        • rende nervosi
    43. Implicazioni sociali (2)
      • Il TDD consente di gestire le “paure” durante lo sviluppo:
        • si procede al rilascio del codice solo se ha superato il 100% dei test previsti.
        • Il design va sempre di pari passo con lo sviluppo.
        • Il TDD consente ai programmatori di conoscere perfettamente il codice.
    44. La velocità
      • Nel TDD è importante la velocità con la quale i test sono eseguiti.
      • Se i test non fossero veloci allora sarebbero una distrazione.
      • Se i test non fossero veloci allora non sarebbero lanciati con alta frequenza: che vantaggio avrebbe il TDD?
      “ Unit tests run fast. If they don’t run fast, they aren’t unit tests.”
    45. Le linee guida
    46. TDD Patterns
      • Red Bar patterns :
        • Comincia da un test semplice.
        • Se hai un’idea nuova aggiungi il test alla lista ma rimani su quello che stai facendo.
        • Aggiungi un test per ogni difetto trovato.
        • Se non riesci ad andare avanti butta via tutto e riscrivilo.
    47. TDD Patterns
      • Testing patterns :
        • Se il test richiede troppo tempo per funzionare allora dividilo in parti più semplici.
        • Se i test hanno bisogno di oggetti complessi allora usa i mock objects.
        • Mantieni il log dell’esecuzione dei test.
        • Se lavori solo lascia rotto l’ultimo test della giornata.
        • Se lavori in team lascia sempre i test funzionanti.
    48. TDD Patterns
      • Green Bar patterns :
        • Scrivi il codice più semplice per passare il test.
        • Scrivi l’implementazione più ovvia per superare il/i test corrente/i.
        • Se un’operazione lavora su collezioni allora scrivi l’implementazione prima sul singolo oggetto e dopo generalizza.
    49. Focused integration testing ed End-to-End testing
    50. Focused integration testing
      • Un focused integration test è focalizzato a testare:
        • la comunicazione con il database
        • la comunicazione in rete
        • la comunicazione con il filesystem
        • la comunicazione con oggetti esterni
      Gli unit test da soli non bastano, il codice deve comunicare con l’esterno.
    51. Focused integration testing (2)
      • Se necessitiamo di molti integration tests
      • allora c’è qualcosa che non va.
      • Es. Se tutte i business object parlano
      • direttamente con il database allora il codice
      • non ha un buon design!
      • Il codice che parla con l’esterno non è né
      • ben coeso nè ben accoppiato.
    52. Focused integration testing (2)
      • Se necessitiamo di molti integration tests
      • allora c’è qualcosa che non va.
      • Es. Se tutte i business object parlano
      • direttamente con il database allora il codice
      • non ha un buon design!
      • Il codice che parla con l’esterno non è né
      • ben coeso nè ben accoppiato.
      Un miglior design prevede che vi sia un’unica classe che parli con il database.
    53. End-to-end Testing
      • Serve per testare l’intero sistema:
        • Test di intere storie di utilizzo del sistema, dalla GUI utente all’utilizzo del database …
      • Contro :
        • Difficile da portare a termine.
        • Difficile da settare.
        • Difficile individuare gli errori.
        • Molto lento.
        • Non automatizzabile.
    54. La velocità di esecuzione dei test
      • Unit tests : un centinaio al secondo.
      • Focused integration tests : una decina al secondo.
      • End-to-end tests : diversi secondi per ogni singol test.
    55. Il TDD ed il Legacy Code
    56. Legacy Code
      • Problemi:
        • Mancanza di documentazione
        • Difficile da capire in profondità
        • Non è progettato pensando alla “testabilità”
      “ Legacy code is code without tests”
    57. Legacy Code (2)
      • I passi per affrontare il legacy code:
      • Inizia a scrivere test per capire se il legacy code (una sua parte) è stato ben compreso.
      • Adatta il test finchè non funziona bene .
    58. Legacy Code (3)
      • Problemi:
        • Quanto codice è stato testato ?
        • Quali aree necessitano di testing ?
        • Quali sono i rischi del codice?
      Difficile avere una visione d’insieme del codice
    59. Benefici del TDD
      • Si mantiene il codice semplice
      • Sviluppo rapido
      • I test sono sia design che documentazione
      • Facile comprensione del codice
      • Bug trovati presto nello sviluppo
      • Meno debugging
      • Basso costo dei cambiamenti
    60. Limiti del TDD
      • Curva di apprendimento alta
      • I manager sono restii ad applicarlo
      • Richiede una grande disciplina
      • Difficile applicarlo alle GUI
      • Di difficile applicazione a Legacy Code
    61. Riferimenti
      • Test-Driven Development: By Examples Kent Beck 2002
      • Test-Driven Development: A pratical guide Astels
      • Unit Test Frameworks Paul Hamill

    + Ennio MasiEnnio Masi, 2 years ago

    custom

    2352 views, 4 favs, 1 embeds more stats

    Seminario presso l'Università degli studi di Napol more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 2352
      • 2350 on SlideShare
      • 2 from embeds
    • Comments 0
    • Favorites 4
    • Downloads 46
    Most viewed embeds
    • 2 views on http://www.odino.org

    more

    All embeds
    • 2 views on http://www.odino.org

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories