Unit Testing

45
Unit Testing Giacomo Petronio O3 Enterprise https://github.com/hijackit/swtesting

description

 

Transcript of Unit Testing

Page 1: Unit Testing

Unit Testing

Giacomo Petronio – O3 Enterprise

https://github.com/hijackit/swtesting

Page 2: Unit Testing

Intro

Software Testing:

◦ È una buona idea?

◦ Processo costoso

tempo, conoscenza

manutenzione

Vantaggi??

Page 3: Unit Testing

Perché (1) QA

Software Di Qualità!

◦ Correttezza, robustezza, affidabilità, …

◦ Manutenibilità evolutiva, correttiva, riusabilità

1 Bug meno qualità!

N Bug …

Page 4: Unit Testing

Perché (2)

Domanda: perché?

Risposta: per verificare che ‘funziona’.

Page 5: Unit Testing

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

Page 6: Unit Testing

Quando funziona?

Soddisfa i requisiti

Insieme dei requisiti

Soluzione problema

Programma funziona

1° step: definizione dei requisiti

Contratto che il SW deve rispettare

Page 7: Unit Testing

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

Page 8: Unit Testing

Categorie di test

Test di accettazione

(Stress test)

Test funzionali

Test di integrazione

Unit test

Criterio:

Oggetto sotto verifica

Scopo della verifica

Page 9: Unit Testing

Unit test

Scopo: “funziona”?

Oggetto: singola classe

Altre caratteristiche:

◦ Code coverage

Page 10: Unit Testing

Unit test

API Design

Documentazione vivente

Page 11: Unit Testing

Unit test

Refactoring

Code confidence

Regression testing

Page 12: Unit Testing

Definire Unit Test

Non dovrebbe

◦ Comunicare con DBMS/rete/filesystem

◦ Aver bisogno di un ambiente configurato

Dovrebbe essere

◦ Veloce

◦ Ripetibile

◦ Indipendente

Page 13: Unit Testing

Definire Unit Test

Meno pignoli!

◦ Può accedere a DBMS (in-memory dbms)

◦ Può accedere al filesystem

◦ Può accedere alla rete

Velocità Ripetibilità Indipendenza

Page 14: Unit Testing

xUnit

JUnit

CppUnit

NUnit

PHPUnit

PyUnit

Page 15: Unit Testing

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

Page 16: Unit Testing

JUnit

MyClassTest

◦ Fixture: @Before method

◦ Test Case: @Test method

◦ Check assert

ESEMPIO…

Page 17: Unit Testing

Best practices

N model classes N test classes

Assert precisi

assertTrue(shape.area != 0); assertTrue(shape.area == 50);

Page 18: Unit Testing

Best practices

White box / Black box

Process proc = new Process(); proc.start(); assertEquals(proc.status, Status.Running);

assertTrue(proc.isRunning());

Page 19: Unit Testing

Best practices

Come testare metodi privati ◦ non testare

◦ reflection

◦ cambiare visibilità

◦ (nested test-class)

Reflection Legacy code?

Non testare Codice nuovo?

Visibilità default

Nuova classe

Page 20: Unit Testing

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

Page 21: Unit Testing

Best practices

Nome test-case (metodi)

◦ Verbosità è ok

test01(){ … } test02(){ … }

testAreaIsEmpty(){ … } testTriangleIsNotARectangle(){ … }

areaShouldBeEmpty(){ … } areaShouldBeExactly50(){ … } triangleShouldNotBeEqualToARectangle(){ … }

Page 22: Unit Testing

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){} }

Page 23: Unit Testing

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

Page 24: Unit Testing

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; }

Page 25: Unit Testing

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

Page 26: Unit Testing

Codice testabile

SOLID principles

◦ Single responsibility

◦ Open/Closed

Page 27: Unit Testing

Codice testabile

SOLID principles

◦ Liskov substitution

AClass { client.doGreatThings(); }

Client { … }

SubClient extends Client { … }

Page 28: Unit Testing

Codice testabile

SOLID principles

◦ Interface segregation

IDoOneThing { doOneThingA(); }

IDoManyThings { doThingA(); doThingB(); doThingC(); }

IDoAnotherThing { doOneThingB(); }

Page 29: Unit Testing

Codice testabile

SOLID principles

◦ Dependency inversion

class JapaneseGuy { playWith(PlayStation ps){ ps.play(); } }

class JapaneseGuy { playWith(IConsolle c){ c.play(); } }

Concrete, Abstract

Concrete Abstract

Page 30: Unit Testing

Esempio

MovieLister

+ moviesDirectedBy

<<Interface>> MovieFinder

+ findAll()

MovieFinderImpl <<crea>>

Classe concreta usa classe concreta

http://martinfowler.com/articles/injection.html

Page 31: Unit Testing

Testare una classe

Isolare la classe

◦ Individuare tutte le dipendenze

◦ Prendere il controllo (IoC)

Classe testabile

◦ Poche dipendenze

◦ Dipendenze astratte

Page 32: Unit Testing

Inversion Of Control (IoC)

Dipendenze vengono fornite

Diversi pattern

◦ Dependency Injection (DI)

MovieLister

<<Interface>> MovieFinder

MovieFinderImpl <<crea>>

Assembler <<crea>>

<<inject>>

Page 33: Unit Testing

IoC: Dependency Injection

Constructor injection

◦ Dipendenze esplicite

Setter injection

◦ Dipendenze meno esplicite

◦ Rende testabile classe esistente

Framework…

◦ Guice

◦ Spring

◦ CDI (J2EE 6)

Page 34: Unit Testing

IoC: Service Locator

MovieLister

<<Interface>> MovieFinder

MovieFinderImpl <<crea>>

ServiceLocator Assembler

<<crea>>

<<chiede>>

Page 35: Unit Testing

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)

Page 36: Unit Testing

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

Page 37: Unit Testing

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

Page 38: Unit Testing

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

Page 39: Unit Testing

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…

Page 40: Unit Testing

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()

Page 41: Unit Testing

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

Page 42: Unit Testing

Test di risorse web

Esempio con Jetty (OnlineMovieFinder)

OnlineMovieFinder Risorsa web

Tester

Jetty Server

Servlet Stub

ESEMPIO…

Page 43: Unit Testing

Test Driven Development

Test first!

TDD mantra:

◦ RED

◦ GREEN

◦ REFACTOR

Page 44: Unit Testing

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

Page 45: Unit Testing

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.