Sei sulla pagina 1di 19
Cenni di Sviluppo agile: i TEST GianLuca DeMichelis gdemichelis@e-ssentia.it
Cenni di Sviluppo agile: i TEST
GianLuca DeMichelis
gdemichelis@e-ssentia.it
Argomenti trattati • Verifica del software – Motivazioni – Tipi di test – Il processo
Argomenti trattati
• Verifica del software
– Motivazioni
– Tipi di test
– Il processo di test
• Introduzione a JUnit
– Struttura dei test
– Esecuzione
– Costruzione di report
• Esempi di utilizzo
Correttezza del software • Le specifiche di un prodotto ne definiscono il comportamento atteso –
Correttezza del software
• Le specifiche di un prodotto ne definiscono il comportamento
atteso
– Un programma è corretto se ottempera a tali attese
• Determinare la correttezza tout court è un’operazione
impossibile
– Occorrerebbe dimostrare che il programma presenta il comportamento
atteso per tutti i possibili dati in ingresso
• Durante il ciclo di vita del prodotto le specifiche possono
cambiare
– Molto più spesso, a parità di specifiche, cambia nel tempo il progetto
(suddivisione in moduli e componenti) e l’implementazione
– Che impatto hanno i cambiamenti sul sistema nel suo complesso?
Testing • Verifica delle proprietà di un applicativo / sistema / modulo basata sull’esecuzione dello
Testing
• Verifica delle proprietà di un applicativo / sistema /
modulo basata sull’esecuzione dello stesso:
– A fronte di specifici dati in ingresso, si verifica che i dati in uscita
siano conformi a quelli attesi
• Nessun test può determinare la totale correttezza e
completezza del software
– Ma solo evidenziarne eventuali comportamenti erronei
• Obiettivo dei test
– Scegliere opportunamente i dati in ingresso, per massimizzare la
probabilità di individuare i possibili malfunzionamenti
Perché testare un programma? • Gli errori costano – Il costo dipende fortemente dalla fase
Perché testare un programma?
• Gli errori costano
– Il costo dipende fortemente
dalla fase in cui vengono
individuati
• Ovunque può nascondersi
un errore
– Alcune situazioni, però,
sono più probabili di altre
• I programmi evolvono
– Ogni volta che si modifica
qualcosa, occorre verificare
che tutto continui a
funzionare
Quando testare il software? • Prima si definisce l’insieme di test, prima si comprende cosa
Quando testare il software?
• Prima si definisce l’insieme di test, prima si
comprende cosa un dato
applicativo/sistema/modulo debba fare
– Build the right program
• Prima si eseguono i test, prima si identificano
eventuali malfunzionamenti
– Build the program right
• Ogni volta che il programma viene modificato,
occorre ri-verificare i test (regressione)
Cosa testare? • Test dei moduli – Verifica la coerenza e la funzionalità di ogni
Cosa testare?
• Test dei moduli
– Verifica la coerenza e la funzionalità di ogni singoli modulo,
considerato isolatamente
– Effettuato dai programmatori
• Test di integrazione (o di sistema)
– Verifica che le interazioni tra i diversi moduli avvengano in modo
coerente con il progetto di sistema
– Spesso effettuato da personale specializzato
• Test di accettazione
– Verifica della conformità alle specifiche fornite
– Effettuato dall’utente/committente
Test dei moduli • Un modulo è l’unità minima di programmazione o un piccolo insieme
Test dei moduli
• Un modulo è l’unità minima di programmazione o
un piccolo insieme di esse
– In Java, per lo più, coincide con una classe o un
insieme di classi correlate
• Test del modulo
– Si creano una o più istanze della/e classe/i
– Si invoca una sequenza di metodi
– Si confrontano i risultati ottenuti con quelli attesi
Automatizzare i test • Ad ogni (gruppo di) classe dovrebbe essere associato un test •
Automatizzare i test
• Ad ogni (gruppo di) classe dovrebbe essere associato un
test
• Il test è composto da codice che istanzia la classe e ne
invoca i metodi
– Dove collocare questo codice?
– Come eseguirlo automaticamente?
– Come interpretarne i risultati?
• Esistono appositi framework per semplificare questo
processo
Refactoring • Spesso, l’implementazione dei moduli evolve nel tempo – Le specifiche divengono più dettagliate
Refactoring
• Spesso, l’implementazione dei moduli evolve nel tempo
– Le specifiche divengono più dettagliate
– Si scelgono soluzioni implementative più adatte
(scalabilità, gestibilità, efficienza, …)
• Il codice viene “ristrutturato” senza cambiarne il
comportamento osservabile
– Occorre verificare che continuino a valere le stesse
proprietà
– Invocando i metodi e controllando i risultati
JUnit • Ambiente per effettuare test di regressione – Disponibile gratuitamente (GPL) sul sito http://www.junit.org
JUnit
• Ambiente per effettuare test di regressione
– Disponibile gratuitamente (GPL) sul sito
http://www.junit.org
• Obiettivo
– Accelerare la produzione di codice migliorandone la
qualità
• Offre meccanismi per
– Associare ad una classe un insieme di test
– Eseguire automaticamente i test
– Produrre un rapporto sui risultati
Principio di funzionamento • Ad ogni classe da testare, è associata una classe che esegue
Principio di funzionamento
• Ad ogni classe da testare, è associata una classe che
esegue il test
– Se la classe da testare si chiama Xxx, quella che
esegue il test si chiama XxxTest
– XxxTest estende junit.framework.TestCase
• Tale classe contiene un numero arbitrario di metodi il cui
nome comincia con “test”
– public void testYyy( ) { … }
– Invocati automaticamente dal framework
– Contengono un insieme di asserzioni
junit.framework. TestCase Principio di funzionamento * void setUp() * void tearDown() MyClass MyClassTest + void
junit.framework.
TestCase
Principio di
funzionamento
* void setUp()
* void tearDown()
MyClass
MyClassTest
+ void testAaa()
+ void testBbb()
+ void testCcc()
Asserzioni • Il test deve – Creare uno o più oggetti – Invocarne dei metodi
Asserzioni
• Il test deve
– Creare uno o più oggetti
– Invocarne dei metodi
– Confrontare il risultato ottenuto con quello atteso
• Il confronto si basa su metodi di tipo “assert” definiti nella classe TestCase
void assertEquals(Object o1, Object o2)
void assertTrue(boolean b)
void assertFalse(boolane b)
• Se la condizione non è verificata generano l’errore AssertionFailedError
– Altrimenti non fanno nulla
Esecuzione dei test (1) • Ogni test presuppone la disponibilità di oggetti della classe da
Esecuzione dei test (1)
• Ogni test presuppone la disponibilità di oggetti della
classe da testare
– Invece di crearli ex novo all’interno dei singoli metodi di test,
possono essere mantenuti in attributi della classe di test
– La loro inizializzazione deve avvenire nel metodo void setUp( )
– Il loro rilascio nel metodo void tearDown( );
• Selezione dei test
– La classe di test deve costruire un oggetto di tipo TestSuite
attraverso il metodo statico suite( )
– Tale oggetto raggruppa i test che si vogliono eseguire
– Può essere popolato automaticamente indicando, come
parametro del costruttore, la classe corrente
Esecuzione dei test (2) • All’atto dell’esecuzione – Viene istanziato un oggetto della classe di
Esecuzione dei test (2)
• All’atto dell’esecuzione
– Viene istanziato un oggetto della classe di test
– Per ogni metodo contenuto nella “suite”:
• Si inizializza il contesto di esecuzione attraverso il
metodo void setUp( )
• Si invoca il metodo di test
• Si ripristina il contesto di esecuzione tramite il metodo
void tearDown( )
– Se si verificano eccezioni a seguito di asserzioni fallite, il
framework le registra e ne visualizza una descrizione
riassuntiva
Esempio (1) import junit.framework.*; public class StringTest extends TestCase { private String s1, s2; protected
Esempio (1)
import junit.framework.*;
public class StringTest extends TestCase {
private String s1, s2;
protected void setUp() {
s1= “alfa”; s2= “beta”;
}
protected void tearDown() { s1=null; s2=null;
}
public void testConcatenation() {
assertEquals(s1+s2, “alfabeta”);
}
public void testSubstring() {
String tmp=s1.substring(1,3);
assertEquals(tmp,“lf”);
}
//…continua
//…class StringTest Esempio (2) public StringTest(String s) { super(s); } public static Test suite() {
//…class StringTest
Esempio (2)
public StringTest(String s) {
super(s);
}
public static Test suite() {
TestSuite suite = new TestSuite(StringTest.class);
return suite;
}
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
}
Eseguire i test • In modalità testuale – java StringTest Time: 0.05 Tests run: 2,
Eseguire i test
• In modalità testuale
– java StringTest
Time: 0.05
Tests run: 2, Failures: 0, Errors: 0
• In modalità grafica
– java junit.swingui.TestRunner