Ingegneria del software
Testing
Si fanno esperimenti con il comportamento del
programma allo scopo di scoprire eventuali errori
si campionano comportamenti
come ogni risultato sperimentale, fornisce indicazioni parziali relative al particolare esperimenti
GOAL: trovare "controesempi"
Tecnica dinamica rispetto alle verifiche statiche fatte dal compilatore
Testing / 2
Testing esaustivo (esecuzione per tuttii possibili ingressi) dimostra la correttezza
p.es. se programma calcola un valore in base a un valore di ingresso nel range 1..10, testing esaustivo consiste nel provare tutti i valori: per le 10 esecuzioni diverse si verifica se il risultato è quello atteso
Impossibile da realizzare in generale:
p.es. se programma legge 3 ingressi interi nel range 1..1000 e calcola un valore, testing esaustivo richiede 10^9 esecuzioni!
Testing funzionale
Proprietà
esprime il punto di vista di chi vuole/deve usare il modulo
esito del test comprensibile da chi non conosce l’implementazione
Varie tecniche per generare dati di test a partire da specifiche
Test di unità e di integrazione
Test di unità
verifica di un singolo modulo isolatamente
Test di integrazione
verifica di corretta interazione dei moduli
Il test di integrazione più difficile
comportamento da testare più complesso maggiore dimensione del codice
spesso interazione poco/mal specificata, e moduli di
JUnit
JUnit è il più famoso framework per i test unitari, creato da Kent Beck ed Erich Gamma
Risale ormai al 1997 e deriva da un lavoro iniziale di Beck per Smalltalk (SUnit)
Il successo è stato tale che la stessa filosofia è andata oltre la sola versione Java. La famiglia di framework che comprende tutti i diversi porting di JUnit si chiama xUnit
Versioni di JUnit
La versione ancora più usata di JUnit è la 3.8.1, che risale al 2002 (!)
Vecchia, ma è quella che “conoscono tutti”
La versione 4.x invece è la più moderna e sfrutta al
massimo le novità che il linguaggio Java ha avuto dal J2SE5.0 in poi.
Testcase
L'elemento base del framework è il TestCase
Il programmatore deve scrivere i TestCase. Ognuno di essi è una classe che contiene dei metodi di test, scritti dal programmatore
Nella versione 3.8.1 la classe deve estendere
junit.framework.TestCase, nella versione 4 le classi sono comuni POJO e si usano le annotation @Test
La prassi vuole che ci sia un TestCase per ogni classe da testare
Controllo di uguaglianza
AssertEquals
Verifica l'uguaglianza di due valori, o due oggetti Se valori, viene effettuato un test ==
Se oggetti, vengono chiamati i rispettivi equals()
assertEquals(2,2);
assertEquals(23, Hour.MAX);
assertEquals(“John”, person.getName());
assertEquals(expectedObj, actualObj);
Controllo di nullità
AssertNull / AssertNotNull
Verificano se un oggetto ha o meno il valore null assertNull(null); //ok
assertNull(new Object()); //ko
assertNotNull(new Object()); //ok assertNotNull(myObject); //?
Controlli booleani
AssertFalse / AssertTrue
Verificano se una condizione è vera o meno.
assertTrue(true); //ok assertFalse(true); //ko
assertTrue(Hour.MAX == 23);
assertTrue(user.isAuthenticated());
Controllo di uguaglianza
AssertSame
Verifica se due oggetti sono gli stessi (cioè, se le due reference puntano allo stessa istanza)
assertSame(new Object(),new Object()); //ko Object obj1 = new Object();
Object obj2 = obj1;
assertSame(obj1, obj2); //ok
setUp e tearDown
Sono metodi di TestCase e vengono chiamati
rispettivamente prima e dopo ogni testXXX() Luogo ideale per creare oggetti, aprire e chiudere connessioni al database, eccetera
Il codice è condiviso quindi tra tutti i test del TestCase
Nella versione 4 la dichiarazione è fatta attraverso le annotation
@Before (per il metodo setUp)
Testing con Junit
Creiamo una classe Calcolatrice con le operazioni di base public int somma(int primo, int secondo)
public int sottrai(int primo, int secondo) public int moltiplica(int primo, int secondo) public int dividi(int primo, int secondo)
Ora dobbiamo creare una classe di test per essere sicuri di aver implementato tutte le funzioni correttamente
Junit test
private Calcolatrice calcolatrice = null;
@Before
public void setUp(){
calcolatrice = new Calcolatrice();
}
@Test
public void testSomma() {
assertEquals( 4, calcolatrice.somma(10, -6));
}
… … [omissis] … …
@Test
public void testDividiPerZero() {
assertNull(calcolatrice.dividi(10, 0));
}
@After
public void tearDown(){
Junit - TestSuite
Nella versione 4 non esiste una vera e propria TestSuite ma può essere definita attraverso le annotation @RunWith e @SuiteClasses
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses( {CalcolatriceTest.class }) public class MyTestSuiteRunner {}