Università degli Studi di Bologna Facoltà di Ingegneria Testing Prima di rilasciare una qualsiasi applicazione/librerie è buona norma effettuare una serie di test opportuni Fondamenti di Informatica T2 Modulo 2 Corso di Laurea in Ingegneria Informatica Anno accademico 2008/2009 Ogni parte di codice distribuita andrebbe testata in modo da verificarne il corretto funzionamento Il testing può essere realizzato in due modi: Realizzando applicazioni di test specifiche Utilizzando framework di supporto per la realizzazione di test da far girare in modo automatico 2 Esempio Esempio public class Counter private int value; public Counter() value = 0; public int getvalue() return value; public void inc() value++; public void reset() value = 0; class Counter Metodi da testare! Counter - value: int + getvalue() : int + inc() : void + reset() : void Si vogliono testare i metodi inc() e reset() in modo tale il comportamento del contatore risulti coerente con quanto ci si aspetta Come fare??? 3 4 Soluzione 1 public static void main(string[] args) System.out.println( Initial: + counter.getvalue()); System.out.println( Current: + counter.getvalue()); System.out.println( Current: + counter.getvalue()); Initial: 0 Current: 2 Current: 0 Soluzione 1 Il funzionamento è stato testato, il contatore funziona!!!! Il test si basa su un controllo manuale del comportamento analizzando l output dell applicazione di test stessa Codice inutilmente replicato per le stampe ed i controlli Praticamente ingestibile con componenti complessi. Difficile testare tutto! 5 6
Soluzione 2 Soluzione 2 public static boolean CheckCounter() boolean ok = true; if (counter.getvalue()!= 0) System.out.println( Error in Initialization. ); if (counter.getvalue()!= 2) System.out.println( inc() not working. );... if (counter.getvalue()!= 0) System.out.println( reset() not working ); return ok; public static void main(string[] args) if(checkcounter()) System.out.println( OK! ); else System.out.println( FAILED! ); OK! 7 8 Soluzione 2 Il funzionamento è stato testato, il contatore funziona!!!! Il controllo è effettuato dall applicazione di test che ritorna successo o insuccesso. Codice inutilmente replicato per le stampe e i controlli Non integrabile con gli ambienti di sviluppo JUnit Cos è? Un piccolo framework di test scritto in Java composto da una serie di classi che compiono il lavoro più ripetitivo (es: contare e riportare gli errori e i test falliti, far girare i test in batch, ecc.). Com è? Consente di effettuare il cosiddetto Unit Testing (da cui il nome) ovvero di effettuare verifiche di funzionamento di piccole porzioni, o unità, di codice (un metodo, una classe, max un componente tipicamente una classe). Non automatizzabile esecuzione automatica dei test Dov è? E integrato all interno dei principali ambienti di sviluppo, Eclipse compreso ma funziona anche a linea di comando! 9 10 JUnit Definiamo una Test Fixture, un entità che contiene un insieme di casi di test volti a verificare il funzionamento di un unità di codice (una classe che contiene i test) Una Fixture è realizzata tramite una classe i cui metodi possono essere i casi di test di cui sopra JUnit Test Runner Ogni metodo di test è riconosciuto tramite annotation e NON per nome. È così possibile dare nomi significativi ai metodi di test! L ordine di esecuzione dei metodi di test è NON DETERMINISTICO. D ora in avanti Test Fixture e Classe di Test saranno considerati sinonimi 11 12
Assert Sono i metodi di verifica Metodo assertequals(expected, current) asserttrue(condition) assertfalse(condition) assertnull(value) assertnotnull(value) assertsame(expected, current) assertnotsame(expecte d, current) fail Descrizione Verifica che valore sia uguale al valore che ci si aspetta. (Utilizza il metodo equals per il confronto) Verifica che la condizione sia vera Verifica che la condizione sia false Verifica che il valore sia nullo Verifica che il valore sia nullo Verifica che il riferimento sia uguale al riferimento che ci si aspetta Verifica che il riferimento non sia uguale al riferimento che ci si aspetta Fa fallire il test 13 Eclipse facilita la creazione dei test tramite wizard Tasto destro sulla classe che si intende testare New Junit Test Case 14 Il Wizard permette la selezione dei metodi della classe da testare così da creare lo scheletro della Fixture di test. Selezione dei metodi di cui si vogliono effettuare i test IMPORTANTE!!!!! Impostare JUnit 4 altrimenti la sintassi per i test è DIVERSA!!! Per creare i metodi di After, Before, AfterClass, BeforeClass Viene creato lo scheletro dei test, uno per ogni metodo selezionato da testare 15 16 Esecuzione in Eclipse import static org.junit.assert.*; import org.junit.*; import core.counter; Pulsante run as ->Junit Test sulla Fixture che si intende Eseguire Verde per i test passati Rosso per i falliti Metodo di test riconosciuto public class CounterTest tramite Annotation public void inittest() Verifica che il valore sia quello atteso 17 18
public void inctest() int expected = 2; public void resettest() 19 20 Il funzionamento è stato testato, il contatore funziona!!!! Il controllo è effettuato dall applicazione di test che ritorna successo o insuccesso. Integrazione con IDE (Es. Eclipse) Automatizzazione dei test Fattorizzazione dei test È possibile eseguire alcune operazioni comuni: Prima e dopo l esecuzione di tutti i test di una classe di test Prima e dopo l esecuzione di un test singolo Tali operazioni sono identificabili sempre tramite annotation che vengono identificate dal motore di test: Class: marca un metodo statico che viene eseguito PRIMA di tutti i test contenuti in una classe di test : marca un metodo che viene eseguito PRIMA di ogni metodo di test @After: marca un metodo che viene eseguito DOPO ogni metodo di test @AfterClass: marca un metodo statico che viene eseguito DOPO tutti i test contenuti in una classe di test 21 22 import static org.junit.assert.*; import org.junit.*; private Counter counter; public void setup() counter = new Counter(); Viene Eseguito prima di ogni metodo di test fattorizza codice comune a tutti i test public void inittest()... 23... public void inctest() int expected = 2; public void resettest() 24
Class @After @After @AfterClass Esecuzione dei Test Codice non replicato sfruttando sapientemente Class,, @After, @AfterClass Test Test 25 26