Introduzione al testing
description
Transcript of Introduzione al testing
Introduzione al testing
Dot Net Marche6° Workshop – 27 giugno 2008
Agenda Unit testing, introduzione Fixture Struttura di un test xUnit Test Doubling Test Di database
Software Testing Verificare la qualità generale del
software Trovare bug nelle applicazioni Verificare le specifiche Verificare l’integrazione tra sistemi Test di regressione …
Tipologie di testSystem Testing
• Esercita l’intero sistema come un tutt’uno• Serve a verificare le specifiche globali• Es: Performance testing, GUI testing, Security testing, Load testing
Integration testing
• Verifica l’integrazione tra le parti di uno stesso sistema• Verifica l’integrazione tra sistemi differenti
Unit Testing• Verifica piccole componenti del codice• Maggiormente automatizzabile• Test focalizzati su specifiche funzionalità di singoli oggetti• Regression Testing – verificano che le modifiche non abbiano causato una “regressione” delle funzionalità
Unit Testing Automatizzabile Scritto nello stesso linguaggio del
codice Supportato da framework standard Supporto fondamentale per
refactoring e cicli di vita agili Tecnologie standard, pattern e
linguaggio comune (www.xunitpattern.org)
Framework xUnit Test in 4 fasi [Four Phase Test]
Setup (viene impostata la situazione iniziale)
Exercise (si interagisce con il SUT) Verify (si verificano gli output con
asserzioni) Teardown (ripristino condizioni
iniziali) Test automatizzati tramite tool a
riga di comando e con interfaccia Integrazione con il sistema di
sviluppo
Anatomia di un test nUnitClasse contenente test
Shared fixture setup
Shared fixture cleanup
Fresh fixture setup
Fresh fixture cleanup
TestFixtureSetUpTestSetUpTest1TearDownTestSetUpTest2TearDownTestFixtureTearDown
Le qualtà di un buon test Automatizzato Indipendente dagli altri test Focalizzato “single assertion test” Robusto Veloce nell’esecuzione Ripetibile
Eseguito frequentementeEseguito automaticamente
I test sono codice “first class” Il codice dei test fa parte del
progetto e non è meno importante del codice sottoposto a test
I test vanno rifattorizzati e la qualità del codice deve essere tenuta alta
È necessario spendere tempo per creare buoni test
Avere buoni test ripaga nel lungo termine
Fixture
Fresh Fixture: ricreare le condizioni ad ogni test Transiente, al termine del test viene
eliminata Persistente, rimane al termine del
test Shared Fixture: una stessa fixture
viene riutilizzata per differenti test
Tutto ciò che deve essere fatto per creare le precondizioni di test del SUT
Fixture – Fresh TransientSetup
Exercise
Verify
TearDown
Fixture
Garbage Collector
Fixture – Fresh persistentSetup
Exercise
Verify
TearDown
FixtureSetup
Exercise
Verify
TearDown
Fixture
Test non ripetibiliInterazione tra i test
Fixture – CleanupSetup
Exercise
Verify
TearDown
FixtureCleanup
È necessario rimuovere manualmente la fixture nel teardown
Fixture – Cleanup LazySetup
Exercise
Verify
TearDown
FixtureSetup
Exercise
Verify
TearDown
FixtureCleanup
Si può posticipare la rimozione della fixture al momento in cui è necessaria
Fixture – Shared Setup
Exercise
Verify
TearDown
FixtureExercise
Verify
TearDown
Exercise
Verify
TearDown
La fixture è unica per una serie di testAumentare la velocità di esecuzione
Rischio di interdipendenza
Asserzioni Single assertion Test Le asserzioni debbono essere
chiare Usare nomi di test significativi
Asserzioni Delta Assertion: in caso di shared
fixture Confronti esterni: in caso di
necessità di veirifica di molti dati (Es. File)
Expected Object: Viene creato un oggetto che rappresenta il risultato atteso
Favorire interfacce fluenti che rendono le asserzioni più leggibili
Un piccolo esempio
Test Double Componenti difficili da testare a
causa di dipendenze (Database, altre librerie, etc)
Componenti dipendenti da un ambiente esterno (network, webservice, etc)
Test lenti a causa di interazione con componenti esterni poco performanti
FIXTURE
Test DoubleSetup
Exercise
Verify
TearDown
SUT DOC
Il SUT dipende da un componente esterno DOC (Depend-on Component)
Il DOC è al di fuori del nostro controllo (Network, WebService) oppure semplicemente difficile da impostare (Database, FileSystem)
Test Double Per risolvere i problemi precedenti si
può sostituire il SUT con un componente fittizio, creato appositamente per il test, e denominato “Test Double”
FIXTURESetup
Exercise
Verify
TearDown
SUT DOCTest Double
Differenti tiplogie di test double
Test Stub• Serve a fornire i dati di ingresso ad un sistema (Es. Stub Database(• Fornisce un implementazione temporanea per il test
Test Dummy• Componente che non fa assolutamente nulla (es. Dummy Logger)
Test Spy e Mock Object• Oltre a fornire i dati in ingresso verificano gli output indiretti del sut
Fake Object• Mima le funzionalità di un sistema in maniera minimale (es Memory Repository)
Un esempio di Test Double Si voglia testare un componente
che, dati gli ordini dell’ultimo mese, esegua delle complesse regole di business e spedisca una mail a seconda del risultato.
FIXTURESetup
Exercise
Verify
TearDown
SUT
DB
Back Door Manipulation Alternativo al test double, agire
indirettametne sul SUT manipolando il DOC
Impostare la fixture DataBase: Script di popolazione DataBase: DataLoader File System: Creare i file di input
Verificare l’output del sut agendo sul DOC Asserzioni sul contenuto del DB Confronto di file con Expected Object
Test di Database Test di stored procedure Test del Data Access Layer Test dei mapping di un ORM Test di performance
Le problematiche maggiori dei test di Database sono collegate all’impostazione
della fixture ed alla sua rimozioneI rischi sono di avere test erratici, non
ripetibili, fragili e interdipendenti
Come gestire i test dei database
Database Sandbox
• Ogni sviluppatore usa il suo database personale locale• Migliora le performance, minimizza le dipendenze evita i conflitti
Fixture Setup• Back Door Manipulation: generare lo stato iniziale precaricando il database con script o con dei
DataLoader.• Shared Fixture: Raggruppare i test per minimizzare il numero di fixture
Fixture Teardown• Table Truncation: Si cancella tutta la tabella dopo ogni test• ORM: effettuare il dispose delle cache e dei contesti• Transaction rollback: si effettua il rollback per annullare qualsiasi modifica• Delta assertion: si confronta l’output con lo stato all’inizio del test
Esempio di test di database Creazione del database di sandbox Creare un database in recovery
mode simple (evita il transaction log)
Copiare la struttura dal database master
Esempio di test di database Creare un preloader che funziona
con bcp e BULK INSERT Utilizzare il TransactionScope per
creare transazioni automatiche Creare singole classi di test
raggruppate per Fixture, dove la fixture non è altro che una serie di file con i dati da precaricare
Utilizzare la gestione automatica delle transazioni
Esempio di test di database
Il preload cancella tutto il contenuto di alcune tabelle e le precarica. Viene fatto all’inizio del test e costituisce una Shared Fixture
Prima di ogni test viene creato un TransactionScope, tutto il codice che accede al db è transazionale
Nel TearDown del singolo test viene annullata ogni modifica effettuando il rollback della transazione.
Esempio di test su db
Design for testability Scrivere codice favorendo la
possibilità di eseguire test Uso intensivo di IoC e DI
SUT
DO
C
DO
C
DO
CD
OC
SUT
DO
C
DO
C
DO
CD
OCI
I
I I
DB
LD
BL
DB
L
DB
L
Design for testability Test di metodi privati
PRIVATE
PROTECTED
TSSPROTECTED
PUBLIC
Design for testability Test Driven Development
Red -> Green -> Refactor
Scrivi Test
Verifica fallimen
toModifica codice
VerificaSuccess
oRifattori
zza
Domande??