View
4.470
Download
3
Category
Preview:
DESCRIPTION
Java Unit Testing - part 3
Citation preview
JUnit (2)
Ing. Fabrizio GianneschiJava User Group Sardegna Onlus
http://www.jugsardegna.org
Java Unit Testing
Fixture
● Scrivere i test è divertente, ma può diventare anche ripetitivo– La ripetitività crea brutto codice, difficile da mantenere
● Una delle maggiori fonti di duplicazione del codice sono le inizializzazioni degli oggetti
● JUnit mette a disposizione il meccanismo delle fixture
● Una fixture è un insieme di dati o risorse comuni, necessarie in più test
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
● Riducono le LOC dei test
● Il codice delle fixture è condiviso quindi tra tutti i test del TestCase– Se alcuni non ne necessitano, forse è meglio mettere il
relativo codice comune in dei semplici utility method
Esempio
private Connection myConn; protected void setUp() throws Exception{ MyConn = DatabaseStub.createConnection();
}...
public void testXyz(){ Statement st = myConn.createStatement(); ...
}protected void tearDown() throws Exception{ myConn.close();}
Eseguire la fixture una volta sola
● In alcuni casi, può essere utile eseguire la fixture una volta sola per tutta la suite
● Anziché ricorrere a degli ineleganti flag, si usa il pattern Decorator (o Wrapper), tramite la classe TestSetup
TestSetuppublic class DbTest extends TestCase{ public static Test suite(){ TestSuite suite = new TestSuite(DbTest.class); TestSetup wrap = new TestSetup(suite){ public void setUp() throws Exception{ } public void tearDown() throws Exception{ }
}; return wrap;
} public void testXXX(){ ...}}
Esercizi
Differenze tra Junit 3.8.x e 4.x
Cambio package
● Le classi principali stanno ora in org.junit.* anziché in junit.framework.*
JUnit 3.8.1:
package com.mycompany;
import junit.framework.*;
...
Cambio package
● Le classi principali stanno ora in org.junit.* anziché in junit.framework.*
JUnit 4.x:
package com.mycompany;
import org.junit.*;
...
Meno dipendenze● Le classi di Test sono ora POJO e non ereditano più da TestCase– Una classe è di test se c'è almeno un metodo annotato
come @Test
JUnit 3.8.1:
import junit.framework.TestCase;public class CalculatorTest extends TestCase{ ...}
Meno dipendenze● Le classi di Test sono ora POJO e non ereditano più da TestCase– Una classe è di test se c'è almeno un metodo annotato
come @Test
JUnit 4.x:
public class CalculatorTest { ... @Test public void ....}
Più espressività● I metodi di test non devono più obbligatoriamente avere
la forma testXXX()– Viene eseguito dal framework ogni metodo annotato come @Test
JUnit 3.8.1:
...
public void testMetodoUno(){...}public void nonMiEsegue(){...}public void testMetodoDue(){...}...
Più espressività● I metodi di test non devono più obbligatoriamente avere
la forma testXXX()– Viene eseguito dal framework ogni metodo annotato come @Test– Devono comunque restare void e senza parametri
JUnit 4.x:
@Test public void miEsegue(){...}@Test public void esegueAncheMe(){...}
public void nonMiEsegue(){...}...
Ancora più espressività
● Anche i metodi setUp() e tearDown() sono sostituibili con metodi annotati
public void setUp() --------> @Before
public void tearDown() --------> @After
Esempio:
@Beforepublic void initResources(){...}
Problema
● Se le classi di test non ereditano più da TestCase, come invocare le asserzioni?
In realtà, sta chiamandoAssert.assertEquals !
Soluzione:Grazie agli import statici di Java 5, rimane tutto come prima!
import static org.junit.Assert.*;...@Testpublic void myTestMethod(){ ... assertEquals(obj1,obj2);}
Sempre sulle asserzioni...
● È più semplice verificare la presenza di eccezioni
JUnit 3.8.1:
try{ metodoCheSollevaUnaException(); fail();}catch (Exception ex){ assertTrue(True) }
JUnit 4.x:
@Test(expected: Exception.class)public void verificaEccezione(){ ...}
No suite
● JUnit 4.x non fa uso delle suite come la precedente versione
import org.junit.runner.RunWith;import org.junit.runners.Suite;import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)@SuiteClasses({TestUno.class, TestDue.class, TestTre.class})public class JUnit4Suite { }
Timer
● È possibile ora controllare se un test impiega troppo tempo oppure va in timeout
@Test (timeout = 100)public void provaConnessione(){ ... url.openConnection(); ...}
1000 = 1 s
Ignorare i test
● In JUnit 3.8.1, tutti i metodi che non iniziano per “test” vengono ignorati dal framework
● JUnit 4.x consente di annotarli come @Ignore
● I TestRunner tengono conto dei test ignorati, per non perderli in mezzo al codice
@Ignore@Testpublic void metodoIgnorato(){ ...}
Altre novità
● Aggiunti metodi assert per testare i vettori– assertEquals(Object[], Object[])
● Due annotazioni comode per le fixture uniche per classe– @BeforeClass e @AfterClass (devono essere statici)
● Nuovo TestRunner, eliminata swingui
Test Parametrici
● JUnit 4.x dispone di una soluzione elegante al problema dei test da eseguire con un numero molto esteso di combinazioni di parametri in ingresso
● Si utilizzano così:– si crea il metodo @Test parametrico– si creano tante variabili d'istanza quanti sono i nomi sono
quelli dei parametri di @Test– si crea un costruttore del test che ha per parametri la n-
upla identica alle variabili d'istanza– si crea un metodo statico @Parameters che deve restituire
una Collection (contiene le n-uple di parametri con i valori)
– si annota la classe con @RunWith(Parameterized.class)
Esempio (1/2)@RunWith(Parameterized.class)public class ParameterTest{ private int par1; private String par2; public ParameterTest(int p1, String p2){ par1 = p1; par2 = p2; }
Esempio (2/2)@Parameterspublic static Collection creaParametri(){ ...return Arrays.asList(new Object[][] { {1, “pippo” }, {100, “paperino”}, {1000, “pluto”}}});}
@Test public void testParametrico(){ ...//qui uso par1 e par2 }}
Ant e JUnit 4.x
● Alcuni problemi con Ant <1.7
● Occorre aggiungere al TestCase il seguente metodo:
public static junit.framework.Test suite(){ return new JUnit4TestAdapter( RegularExpressionTest.class);
}
Licenza Creative Commons (sunto)
Attribuzione-Non commerciale-Condividi allo stesso modo
3.0 Unported
Tu sei libero di modificare, riprodurre, distribuire, comunicare al pubblico, esporre inpubblico, rappresentare, eseguire e recitare quest'opera.
Alle seguenti condizioni:
● Attribuzione. Devi attribuire la paternità dell'opera nei modi indicati dall'autore o da chi ti ha dato l'opera in licenza e in modo tale da non suggerire che essi avallino te o il modo in cui tu usi l'opera.
● Non commerciale. Non puoi usare quest'opera per fini commerciali.
● Condividi allo stesso modo. Se alteri o trasformi quest'opera, o se la usi per crearne un'altra, puoi distribuire l'opera risultante solo con una licenza identica o equivalente a questa.
● Testo completo della licenza completa su:http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode
Recommended