Unit Testing
Giacomo Petronio – O3 Enterprise
https://github.com/hijackit/swtesting
Intro
 Software Testing:
◦ È una buona idea?
◦ Processo costoso
 tempo, conoscenza
 manutenzione
 Vantaggi??
Perché (1) QA
 Software Di Qualità!
◦ Correttezza, robustezza, affidabilità, …
◦ Manutenibilità evolutiva, correttiva, riusabilità
 1 Bug  meno qualità!
 N Bug  …
Perché (2)
 Domanda: perché?
 Risposta: per verificare che ‘funziona’.
Problema
Programma
(soluzione)
Problema
risolto?
Funziona??
 Troppo generico..
 Quand’è che funziona?
 Quando saprò se risolve il mio problema?
Si da per scontato che saremo in grado di
dire se la nostra soluzione funziona
Quando funziona?
 Soddisfa i requisiti
Insieme dei requisiti
 Soluzione problema
 Programma funziona
1° step: definizione dei requisiti
Contratto che il SW deve rispettare
I test possono essere considerati come un modo
per catturare e implementare i requisiti
Requisiti e test
 Una cosa sola
 1 requisito  1+ test
 1 requisito, 0 test == 0 requisiti
Categorie di test
 Test di accettazione
 (Stress test)
 Test funzionali
 Test di integrazione
 Unit test
Criterio:
 Oggetto sotto verifica
 Scopo della verifica
Unit test
 Scopo: “funziona”?
 Oggetto: singola classe
 Altre caratteristiche:
◦ Code coverage
Unit test
 API Design
 Documentazione vivente
Unit test
 Refactoring
 Code confidence
 Regression testing
Definire Unit Test
 Non dovrebbe
◦ Comunicare con DBMS/rete/filesystem
◦ Aver bisogno di un ambiente configurato
 Dovrebbe essere
◦ Veloce
◦ Ripetibile
◦ Indipendente
Definire Unit Test
 Meno pignoli!
◦ Può accedere a DBMS (in-memory dbms)
◦ Può accedere al filesystem
◦ Può accedere alla rete
Velocità Ripetibilità Indipendenza
xUnit
 JUnit
 CppUnit
 NUnit
 PHPUnit
 PyUnit
 …
Idea di base
 La ricetta per un buon test
◦ Fixture (contesto)
◦ Test case
◦ Check
Kent Beck’s testing framework paper
http://www.xprogramming.com/testfram.htm
JUnit
 MyClassTest
◦ Fixture: @Before method
◦ Test Case: @Test method
◦ Check assert
ESEMPIO…
Best practices
 N model classes  N test classes
 Assert precisi
assertTrue(shape.area != 0);
assertTrue(shape.area == 50);
Best practices
 White box / Black box
Process proc = new Process();
proc.start();
assertEquals(proc.status, Status.Running);
assertTrue(proc.isRunning());
Best practices
 Come testare metodi privati
◦ non testare
◦ reflection
◦ cambiare visibilità
◦ (nested test-class)
ReflectionLegacy code?
Non testareCodice nuovo?
Visibilità default
Nuova classe
Best practices
 Nome classe
◦ TriangleTest
 Package
◦ src/main/java/it/units/inginf/shapes
 Triangle.class
 Rectangle.class
◦ src/test/java/it/units/inginf/shapes
 TriangleTest.class
 RectangleTest.class
Best practices
 Nome test-case (metodi)
◦ Verbosità è ok
test01(){ … }
test02(){ … }
testAreaIsEmpty(){ … }
testTriangleIsNotARectangle(){ … }
areaShouldBeEmpty(){ … }
areaShouldBeExactly50(){ … }
triangleShouldNotBeEqualToARectangle(){ … }
Best practices
 Eccezioni
◦ Attributo expected
@Test(expected=IllegalArgumentException.class)
invaldAddressShouldNotBeAccepted(){
WebClient client = new WebClient(“WRONG!”);
}
@Test
invaldAddressShouldNotBeAccepted(){
try{
WebClient client = new WebClient(“WRONG!”);
fail();
} catch(IllegalArgumentException e){}
}
Tecniche di testing
 Classi di equivalenza e valori al confine
◦ Coprire tutti gli input
◦ Minimizzare la ridondanza
0 6 16 65
4€0€ 8€ 5€
5 test-case, uno per classe di equivalenza
8 test-case, uno per confine di ciascuna classe
Tecniche di testing
 Esplorazione del grafo
◦ Macchine a stato
◦ Transazioni e stato interno
int left = 1;
int right = 1;
public void incLeft(){ left++; }
public void incRight(){ right++; }
public String getId(){
return left + “.” + right;
}
Tecniche di testing
1:1
2:1
3:1 1:2
1:2
2:1 1:3
T1 T2
Stato iniziale X;Y X;Y
Evento incLeft incRight
Effetto X++ Y++
Stato finale X+1;Y X;Y+1
1° livello: 2 test-case
2° livello: 4 test-case
3° livello: 8 test-case
…
T1 T2
Codice testabile
 SOLID principles
◦ Single responsibility
◦ Open/Closed
Codice testabile
 SOLID principles
◦ Liskov substitution
AClass {
client.doGreatThings();
}
Client {
…
}
SubClient extends Client {
…
}
Codice testabile
 SOLID principles
◦ Interface segregation
IDoOneThing {
doOneThingA();
}
IDoManyThings {
doThingA();
doThingB();
doThingC();
}
IDoAnotherThing {
doOneThingB();
}
Codice testabile
 SOLID principles
◦ Dependency inversion
class JapaneseGuy {
playWith(PlayStation ps){
ps.play();
}
}
class JapaneseGuy {
playWith(IConsolle c){
c.play();
}
}
Concrete, Abstract
Concrete Abstract
Esempio
MovieLister
+ moviesDirectedBy
<<Interface>>
MovieFinder
+ findAll()
MovieFinderImpl
<<crea>>
Classe concreta usa classe concreta
http://martinfowler.com/articles/injection.html
Testare una classe
 Isolare la classe
◦ Individuare tutte le dipendenze
◦ Prendere il controllo (IoC)
 Classe testabile
◦ Poche dipendenze
◦ Dipendenze astratte
Inversion Of Control (IoC)
 Dipendenze vengono fornite
 Diversi pattern
◦ Dependency Injection (DI)
MovieLister
<<Interface>>
MovieFinder
MovieFinderImpl
<<crea>>
Assembler <<crea>>
<<inject>>
IoC: Dependency Injection
 Constructor injection
◦ Dipendenze esplicite
 Setter injection
◦ Dipendenze meno esplicite
◦ Rende testabile classe esistente
 Framework…
◦ Guice
◦ Spring
◦ CDI (J2EE 6)
IoC: Service Locator
MovieLister
<<Interface>>
MovieFinder
MovieFinderImpl
<<crea>>
ServiceLocator Assembler
<<crea>>
<<chiede>>
DI Framework: Guice
 Es. servizio di pagamento
https://code.google.com/p/google-guice/wiki/Motivation
RealBillingService
<<Interface>>
CreditCardProcessor
PaypalProcessor
<<Interface>>
TransactionLog
DBTransactionLog
<<Interface>>
BillingService
+ chargeOrder(order, creditCard)
Stub e Mock
 Isolare la classe
 Se ha dipendenze?
◦ Sostituirle con oggetti controllati
 Stub
◦ Non hanno logica interna
◦ Comportamento sempre uguale
◦ Non si effettuano verifiche sugli stub
◦ Es. finta risorsa web
Stub e Mock
 Mock
◦ Programmabile
 Quando metodo riceve X
 Restituisci Y
 Lancia eccezione
 …
◦ Verifiche sui mock
 Numero di chiamate ad un metodo
 Parametro passato ad un metodo
 …
Mocking library: Mockito
 Mock lifecycle:
◦ Crea mock a partire da interfaccia
◦ Programma comportamento atteso
◦ Utilizzo indiretto (da parte del SUT*)
◦ Verifica dell’utilizzo
SUT = System Under Test, classe sottoposta a verifica
Mockito: esempio
MovieFinder finder = mock(MovieFinder.class)
when(finder.findAll()).thenReturn(allMovies);
MovieLister lister = new MovieLister(finder);
Lister.moviesDirectedBy(“Martin Scorsese”);
verify(finder).findAll(); // verifica la chiamata
ESEMPIO…
Mockito: possibilità
MovieFinder finder = mock(MovieFinder.class)
when(finder.findAll()).___________
.thenReturn(allMovies);
.thenReturn(none, all);
.thenThrows(new RuntimeException());
.then( callback );
MovieLister lister = mock(MovieLister.class)
when(lister.moviesDirectedBy(_____)).then(…);
“Martin Scorsese”
anyString()
any()
Mockito: spies
List list = new ArrayList();
List spy = spy(list);
// calls real method!
spy.add(“one”);
spy.add(“two”);
// verify
verify(spy).add("one");
 Utile per testare codice esistente
Test di risorse web
 Esempio con Jetty (OnlineMovieFinder)
OnlineMovieFinder Risorsa web
Tester
Jetty Server
Servlet Stub
ESEMPIO…
Test Driven Development
 Test first!
 TDD mantra:
◦ RED
◦ GREEN
◦ REFACTOR
Test Driven Development
 Ho un metodo calcolaX(a, b)
 Ho bisogno di un test che verifica TUTTO!
 Dati a, b vorrei ottenere X
 Se a < 0, vorrei avere un errore
 Se b == 0, vorrei…
1° test
2° test
3° test
Test Driven Development
 What is the common, expected case?
 What are some possible unusual cases?
 How many external dependencies do I have?
 What system failures could I reasonably encounter here?
http://www.codinghorror.com/blog/2005/04/good-test-bad-test.html
 Costringe ad affrontare domande scomode
 Costringe a pensare prima di scrivere
The real value of unit testing is that it forces
you to stop and think about testing.

Unit Testing

  • 1.
    Unit Testing Giacomo Petronio– O3 Enterprise https://github.com/hijackit/swtesting
  • 2.
    Intro  Software Testing: ◦È una buona idea? ◦ Processo costoso  tempo, conoscenza  manutenzione  Vantaggi??
  • 3.
    Perché (1) QA Software Di Qualità! ◦ Correttezza, robustezza, affidabilità, … ◦ Manutenibilità evolutiva, correttiva, riusabilità  1 Bug  meno qualità!  N Bug  …
  • 4.
    Perché (2)  Domanda:perché?  Risposta: per verificare che ‘funziona’.
  • 5.
    Problema Programma (soluzione) Problema risolto? Funziona??  Troppo generico.. Quand’è che funziona?  Quando saprò se risolve il mio problema? Si da per scontato che saremo in grado di dire se la nostra soluzione funziona
  • 6.
    Quando funziona?  Soddisfai requisiti Insieme dei requisiti  Soluzione problema  Programma funziona 1° step: definizione dei requisiti Contratto che il SW deve rispettare
  • 7.
    I test possonoessere considerati come un modo per catturare e implementare i requisiti Requisiti e test  Una cosa sola  1 requisito  1+ test  1 requisito, 0 test == 0 requisiti
  • 8.
    Categorie di test Test di accettazione  (Stress test)  Test funzionali  Test di integrazione  Unit test Criterio:  Oggetto sotto verifica  Scopo della verifica
  • 9.
    Unit test  Scopo:“funziona”?  Oggetto: singola classe  Altre caratteristiche: ◦ Code coverage
  • 10.
    Unit test  APIDesign  Documentazione vivente
  • 11.
    Unit test  Refactoring Code confidence  Regression testing
  • 12.
    Definire Unit Test Non dovrebbe ◦ Comunicare con DBMS/rete/filesystem ◦ Aver bisogno di un ambiente configurato  Dovrebbe essere ◦ Veloce ◦ Ripetibile ◦ Indipendente
  • 13.
    Definire Unit Test Meno pignoli! ◦ Può accedere a DBMS (in-memory dbms) ◦ Può accedere al filesystem ◦ Può accedere alla rete Velocità Ripetibilità Indipendenza
  • 14.
    xUnit  JUnit  CppUnit NUnit  PHPUnit  PyUnit  …
  • 15.
    Idea di base La ricetta per un buon test ◦ Fixture (contesto) ◦ Test case ◦ Check Kent Beck’s testing framework paper http://www.xprogramming.com/testfram.htm
  • 16.
    JUnit  MyClassTest ◦ Fixture:@Before method ◦ Test Case: @Test method ◦ Check assert ESEMPIO…
  • 17.
    Best practices  Nmodel classes  N test classes  Assert precisi assertTrue(shape.area != 0); assertTrue(shape.area == 50);
  • 18.
    Best practices  Whitebox / Black box Process proc = new Process(); proc.start(); assertEquals(proc.status, Status.Running); assertTrue(proc.isRunning());
  • 19.
    Best practices  Cometestare metodi privati ◦ non testare ◦ reflection ◦ cambiare visibilità ◦ (nested test-class) ReflectionLegacy code? Non testareCodice nuovo? Visibilità default Nuova classe
  • 20.
    Best practices  Nomeclasse ◦ TriangleTest  Package ◦ src/main/java/it/units/inginf/shapes  Triangle.class  Rectangle.class ◦ src/test/java/it/units/inginf/shapes  TriangleTest.class  RectangleTest.class
  • 21.
    Best practices  Nometest-case (metodi) ◦ Verbosità è ok test01(){ … } test02(){ … } testAreaIsEmpty(){ … } testTriangleIsNotARectangle(){ … } areaShouldBeEmpty(){ … } areaShouldBeExactly50(){ … } triangleShouldNotBeEqualToARectangle(){ … }
  • 22.
    Best practices  Eccezioni ◦Attributo expected @Test(expected=IllegalArgumentException.class) invaldAddressShouldNotBeAccepted(){ WebClient client = new WebClient(“WRONG!”); } @Test invaldAddressShouldNotBeAccepted(){ try{ WebClient client = new WebClient(“WRONG!”); fail(); } catch(IllegalArgumentException e){} }
  • 23.
    Tecniche di testing Classi di equivalenza e valori al confine ◦ Coprire tutti gli input ◦ Minimizzare la ridondanza 0 6 16 65 4€0€ 8€ 5€ 5 test-case, uno per classe di equivalenza 8 test-case, uno per confine di ciascuna classe
  • 24.
    Tecniche di testing Esplorazione del grafo ◦ Macchine a stato ◦ Transazioni e stato interno int left = 1; int right = 1; public void incLeft(){ left++; } public void incRight(){ right++; } public String getId(){ return left + “.” + right; }
  • 25.
    Tecniche di testing 1:1 2:1 3:11:2 1:2 2:1 1:3 T1 T2 Stato iniziale X;Y X;Y Evento incLeft incRight Effetto X++ Y++ Stato finale X+1;Y X;Y+1 1° livello: 2 test-case 2° livello: 4 test-case 3° livello: 8 test-case … T1 T2
  • 26.
    Codice testabile  SOLIDprinciples ◦ Single responsibility ◦ Open/Closed
  • 27.
    Codice testabile  SOLIDprinciples ◦ Liskov substitution AClass { client.doGreatThings(); } Client { … } SubClient extends Client { … }
  • 28.
    Codice testabile  SOLIDprinciples ◦ Interface segregation IDoOneThing { doOneThingA(); } IDoManyThings { doThingA(); doThingB(); doThingC(); } IDoAnotherThing { doOneThingB(); }
  • 29.
    Codice testabile  SOLIDprinciples ◦ Dependency inversion class JapaneseGuy { playWith(PlayStation ps){ ps.play(); } } class JapaneseGuy { playWith(IConsolle c){ c.play(); } } Concrete, Abstract Concrete Abstract
  • 30.
    Esempio MovieLister + moviesDirectedBy <<Interface>> MovieFinder + findAll() MovieFinderImpl <<crea>> Classeconcreta usa classe concreta http://martinfowler.com/articles/injection.html
  • 31.
    Testare una classe Isolare la classe ◦ Individuare tutte le dipendenze ◦ Prendere il controllo (IoC)  Classe testabile ◦ Poche dipendenze ◦ Dipendenze astratte
  • 32.
    Inversion Of Control(IoC)  Dipendenze vengono fornite  Diversi pattern ◦ Dependency Injection (DI) MovieLister <<Interface>> MovieFinder MovieFinderImpl <<crea>> Assembler <<crea>> <<inject>>
  • 33.
    IoC: Dependency Injection Constructor injection ◦ Dipendenze esplicite  Setter injection ◦ Dipendenze meno esplicite ◦ Rende testabile classe esistente  Framework… ◦ Guice ◦ Spring ◦ CDI (J2EE 6)
  • 34.
  • 35.
    DI Framework: Guice Es. servizio di pagamento https://code.google.com/p/google-guice/wiki/Motivation RealBillingService <<Interface>> CreditCardProcessor PaypalProcessor <<Interface>> TransactionLog DBTransactionLog <<Interface>> BillingService + chargeOrder(order, creditCard)
  • 36.
    Stub e Mock Isolare la classe  Se ha dipendenze? ◦ Sostituirle con oggetti controllati  Stub ◦ Non hanno logica interna ◦ Comportamento sempre uguale ◦ Non si effettuano verifiche sugli stub ◦ Es. finta risorsa web
  • 37.
    Stub e Mock Mock ◦ Programmabile  Quando metodo riceve X  Restituisci Y  Lancia eccezione  … ◦ Verifiche sui mock  Numero di chiamate ad un metodo  Parametro passato ad un metodo  …
  • 38.
    Mocking library: Mockito Mock lifecycle: ◦ Crea mock a partire da interfaccia ◦ Programma comportamento atteso ◦ Utilizzo indiretto (da parte del SUT*) ◦ Verifica dell’utilizzo SUT = System Under Test, classe sottoposta a verifica
  • 39.
    Mockito: esempio MovieFinder finder= mock(MovieFinder.class) when(finder.findAll()).thenReturn(allMovies); MovieLister lister = new MovieLister(finder); Lister.moviesDirectedBy(“Martin Scorsese”); verify(finder).findAll(); // verifica la chiamata ESEMPIO…
  • 40.
    Mockito: possibilità MovieFinder finder= mock(MovieFinder.class) when(finder.findAll()).___________ .thenReturn(allMovies); .thenReturn(none, all); .thenThrows(new RuntimeException()); .then( callback ); MovieLister lister = mock(MovieLister.class) when(lister.moviesDirectedBy(_____)).then(…); “Martin Scorsese” anyString() any()
  • 41.
    Mockito: spies List list= new ArrayList(); List spy = spy(list); // calls real method! spy.add(“one”); spy.add(“two”); // verify verify(spy).add("one");  Utile per testare codice esistente
  • 42.
    Test di risorseweb  Esempio con Jetty (OnlineMovieFinder) OnlineMovieFinder Risorsa web Tester Jetty Server Servlet Stub ESEMPIO…
  • 43.
    Test Driven Development Test first!  TDD mantra: ◦ RED ◦ GREEN ◦ REFACTOR
  • 44.
    Test Driven Development Ho un metodo calcolaX(a, b)  Ho bisogno di un test che verifica TUTTO!  Dati a, b vorrei ottenere X  Se a < 0, vorrei avere un errore  Se b == 0, vorrei… 1° test 2° test 3° test
  • 45.
    Test Driven Development What is the common, expected case?  What are some possible unusual cases?  How many external dependencies do I have?  What system failures could I reasonably encounter here? http://www.codinghorror.com/blog/2005/04/good-test-bad-test.html  Costringe ad affrontare domande scomode  Costringe a pensare prima di scrivere The real value of unit testing is that it forces you to stop and think about testing.