AOT A O T Lab LABLAB Dipartimento di Ingegneria dell ... di controllo di P sia attraversato almeno...

90
Agent and Object T echnology Lab Dipartimento di Ingegneria dell’Informazione Università degli Studi di Parma AOT AOT LAB LAB Ingegneria del software A Testing Michele Tomaiuolo

Transcript of AOT A O T Lab LABLAB Dipartimento di Ingegneria dell ... di controllo di P sia attraversato almeno...

Agent and Object Technology LabDipartimento di Ingegneria dell’Informazione

Università degli Studi di Parma

AOTAOTLABLAB

Ingegneria del software A

Testing

Michele Tomaiuolo

2

AOTAOTLABLAB Qualità interne ed esterne

Le qualità su cui si basa la valutazione di un sistemasoftware possono essere: Interne, riguardano le caratteristiche legate allo sviluppo del

software e non sono visibili agli utentiEsterne, riguardano le funzionalità fornite dal sistema e sono visibili

agli utenti

Le categorie sono legate, non è possibile ottenerequalità esterne se il sistema non gode di qualità interne

3

AOTAOTLABLAB Qualità del prodotto e del processo

È anche possibile valutare un sistema secondo qualitàRelative al prodotto, riguardano le caratteristiche stesse del sistema

e sono sempre valutabiliRelative al processo, riguardano i metodi utilizzati durante lo

sviluppo del software

Le categorie sono legate, non è possibile ottenerequalità del prodotto se il sistema non gode di qualità delprocessoProduct quality is process quality

4

AOTAOTLABLAB Qualità esterne

Correttezza: il sistema rispetta le specificheAffidabilità (dependability): l’utente può dipendere dal

sistemaRobustezza: il sistema si comporta in modo ragionevole

anche in circostanze non previste dalle specificheEfficienza: usa bene le risorse di calcoloScalabilità: migliori prestazioni con più risorseSicurezza: authentication, authorization, accountingFacilità d’uso: un sistema è facile da usare se

l’interfaccia che presenta all’utente gli permette diesprimersi in modo naturale

5

AOTAOTLABLAB Valutazione delle qualità

Valutazione sulla base delle specificheCorrettezza e affidabilitàRobustezza: riguarda tutti i casi non trattati dalle specifiche

Valutazione dei committentiCorrettezza e facilità d’uso

Valutazione degli sviluppatoriRobustezza ed efficienza

6

AOTAOTLABLAB Qualità interne

Verificabilità: sistema basato su modello formaleRiusabilità: parti usabili per costruire nuovi sistemiManutenibilità

Riparabilità: facilitata la ricerca degli erroriEvolvibilità: aggiungere nuove funzionalità al sistemaAdattabilità: rispetto a cambiamenti del dominio applicativo

Interoperabilità: capacità di co-operare con altri sistemi,anche di altri produttori

Portabilità: può funzionare su più piattaforme hw/swComprensibilità: codice leggibile, documentazioneModularità: interazione tra componenti coesi

7

AOTAOTLABLAB Qualità del processo

Produttività, misura l’efficienza del processo nei terminidella velocità di consegna del sistema

Tempestività, misura la capacità del processo di valutaree rispettare i tempi di consegna del sistema

Trasparenza, un processo di produzione è trasparentese permette di capire il suo stato e di controllarne i passi

Agilità, misura la capacità del processo di consentire laproduzione in tempi ridotti (ridotto time-to-market)

8

AOTAOTLABLAB Costi del software

I costi del software sono spesso predominanti nei costi diun sistema Il costo del software in un PC spesso è maggiore di quello

dell’intero hardware

Il costo del software è principalmente nel mantenimentopiuttosto che nello sviluppo

Uno degli obiettivi principali dell’ingegneria del software èottenere un sviluppo cost-effective prevenendo perquanto possibile i costi di manutenzione

9

AOTAOTLABLAB Costo diretti

Costo delle risorse per lo sviluppo (costi diretti)Costo del personale sviluppatore, spesso predominante sugli altriCosto del personale di supportoCosto delle risorse di sviluppoMateriali di consumoAltri costi generali della struttura

10

AOTAOTLABLAB Costi indiretti

Altri costi, più aleatori (costi indiretti)Capacità, motivazione e coordinamento del personaleComplessità del sistema da realizzareStabilità dei requisitiCaratteristiche dell’ambiente di sviluppo

Costo di manutenzione ed evoluzione

11

AOTAOTLABLAB Evoluzione di un sistema software

Il software deve evolvere perché:Non sono stati colti correttamente i requisiti I requisiti non sono inizialmente notiCambiano le condizioni operative…

L’evoluzione è ineliminabile per gran parte delle tipologiedi sistemi, anche se i requisiti iniziali sono corretti ecompleti

12

AOTAOTLABLAB Manutenzione

Manutenzione è il processo di modifica di un sistemadopo il suo rilascio al fine di…Eliminare anomalie (manutenzione correttiva)Migliorare le prestazioni o altri attributi di qualità (manutenzione

perfettiva)Adattare a mutamenti dell’ambiente (manutenzione adattativa)

Costi della manutenzione:Spesso maggiori del 50% del costo totale del software75% (fonte Hewlett-Packard)70% (fonte Dipartimento della Difesa degli Stati Uniti)

Manutenzione correttiva: 20%Manutenzione perfettiva: 60%Manutenzione adattativa: 20%

13

AOTAOTLABLAB Dati sulla manutenzione

Esperienza di Hewlett-PackardLa maggior parte degli errori potrebbe essere scoperta mediante

tecniche sistematiche di revisione di progetto I moduli con maggior complessità del flusso di controllo hanno

maggiore probabilità di contenere errori

Alcuni datiSu 10 difetti scoperti durante il test, 1 si propaga nella

manutenzioneEliminare i difetti costa, in tempo, 4-10 volte per sistemi grossi e

maturi rispetto a piccoli e ancora in sviluppo Il costo di rimozione degli errori aumenta con il ritardo rispetto al

quale gli errori sono introdotti

14

AOTAOTLABLAB Problemi più attuali

Gestire sistemi vecchi ma non sostituibili (legacy system)Necessità di manutenzione adattativaProblemi dovuti alla tecnologia obsoleta

Gestire l’eterogeneità dei sistemi I sistemi sono sempre distribuiti e sono composti da una grande

varietà di sistemi hardware e software

Riduzione dei tempi di consegnaC’è una sempre maggiore pressione per ottenere tempi di

consegna brevi

15

AOTAOTLABLAB Verifica e validazione

La verifica e la validazione servono per mostrare che ilsistema È conforme alle specifiche Incontra i requisiti dell’utente

Comprende revisione e testing del sistema

Il testing di un sistema richiede di eseguire il sistema sucasi di test (test case) derivati dalle specifiche

16

AOTAOTLABLAB Testing

Le operazioni di testingpossono individuare la presenza di errori nel software

ma non ne possono dimostrare la correttezza-- E. Dijkstra

A cosa serve il testingVerificare il comportamento del sistema in un insieme di casi

sufficientemente ampio da rendere plausibile che il suocomportamento sia analogo anche nelle restanti situazioni

Le operazioni di testing si suddividono in:Testing in the small, riguardano moduli singoliTesting in the large, riguardano il sistema nella sua globalità

17

AOTAOTLABLAB Processo di Testing

Sub-systemtesting

Moduletesting

Unittesting

Systemtesting

Acceptancetesting

Componenttesting

Integration testing Usertesting

18

AOTAOTLABLAB Fasi di Testing (1/2)

Unit testingOgni singolo componente

Module testingOgni modulo, insieme di componenti interdipendenti

Sub-system testing Integrazione tra moduli in sotto-sistemi per individuare problemi

nelle interfacce tra i moduli

System testingSistema nel suo complesso, eventuali proprietà emergenti del

sistema

Acceptance testingCon i committenti per verificare l’accettabilità del sistema

19

AOTAOTLABLAB Fasi di Testing (2/2)

Requirementsspecification

Systemspecification

Systemdesign

Detaileddesign

Module andunit codeand tess

Sub-systemintegrationtest plan

Systemintegrationtest plan

Acceptancetest plan

Service Acceptancetest

Systemintegration test

Sub-systemintegration test

20

AOTAOTLABLAB Statement test

Valuta il corretto funzionamento di una porzione delcodiceAnalizzando il suo output in relazione ad input significativi

Verifica di copertura dei programmi (statement test)Un errore non può essere scoperto se la parte di codice che lo

contiene non viene eseguita almeno una voltaCriterio: selezionare un insieme di test T tali che, a seguito

dell’esecuzione del programma P su tutti i casi di T, ogni istruzioneelementare di P venga eseguita almeno una volta

Può essere eseguito solo conoscendo la struttura interna dellaporzione di codice (white-box testing)

21

AOTAOTLABLAB Branch test

Verifica di copertura delle decisioni (branch test)

Per ogni condizione presente nel codice è utilizzato un test cheproduca risultato vero e falso

Criterio: selezionare un insieme di test T tali che, a seguitodell’esecuzione del programma P su tutti i casi di T, ogni arco delgrafo di controllo di P sia attraversato almeno una volta

Può essere eseguito solo conoscendo la struttura interna dellaporzione di codice

22

AOTAOTLABLAB Branch and condition test

Verifica di copertura delle decisioni e delle condizioni

Per ogni porzione di condizione composta presente nel codice, siautilizzato un test che produca il risultato vero e falso

Criterio: selezionare un insieme di test T tali che, a seguitodell’esecuzione del programma P su tutti i casi di T, ogni arco delgrafo di controllo di P sia attraversato e tutti i possibili valori dellecondizioni composte siano valutati almeno una volta

Produce un’analisi più approfondita rispetto al criterio di coperturadelle decisioni

Può essere eseguito solo conoscendo la struttura interna dellaporzione di codice

23

AOTAOTLABLAB Testing in the large

Il white-box testing è impossibile per sistemi di grandidimensioni

Il sistema è visto come una scatola nera (black-boxtesting) e si vanno a verificare le corrispondenze di inpute output

L’insieme di test da utilizzare viene selezionato sullabase delle specifiche

24

AOTAOTLABLAB Esempio: fatture

Problema: il sistema riceve come input una fattura dicui è nota la struttura dettagliataLa fattura deve essere inserita in un archivio ordinato per dataSe esistono altre fatture con la stessa data fa fede l’ordine di arrivo

È inoltre necessario verificare che: Il cliente sia già stato inserito in archivio eVi sia corrispondenza tra la data di inserimento del cliente e quella

della fattura, …

Test set:1. Fattura con data odierna2. Fattura con data passata e per la quale esistono altre fatture3. Fattura con data passata e per la quale non esistono altre fatture4. Fattura il cui cliente non è stato inserito5. …

25

AOTAOTLABLAB Ispezione del software

Analisi del codice per capirne le caratteristiche e lefunzionalitàPuò essere effettuata sul codice oppure sullo pseudocodicePermette la verifica unitaria di un insieme di condizioniÈ soggetta agli errori di colui che la effettuaSi basa su un modello della realtà e non su dati reali

I due principali approcciCode walk-throughCode inspection

26

AOTAOTLABLAB Code walk-through

Analisi informale eseguita da un team di persone1. Opportuna selezione di porzioni del codice e valori di input2. Simulazione su carta del comportamento del sistema

Il numero di persone coinvolte deve essere ridotto Al fine di aumentare il clima di cooperazione all’analisi non

devono partecipare i manager

Il progettista deve fornire in anticipo documentazione del codice L’analisi non deve durare più di alcune ore L’analisi deve essere indirizzata solamente alla ricerca dei

problemi e non alla loro soluzione

27

AOTAOTLABLAB Code inspection

Analisi eseguita da un team di persone e organizzatacome nel caso del code walk-throughMira a ricercare classi specifiche di errori Il codice viene esaminato controllando soltanto la presenza di una

particolare categoria di errore, piuttosto che simulando unagenerica esecuzione

Le classi di errori che vengono solitamente ricercate conquesta tecnica sonoUso di variabili non inizializzateLoop infinitiLetture di porzioni di memoria non allocataRilascio improprio della memoria

28

AOTAOTLABLAB Program testing

Program testing is the process of executing a programwith the intent of finding errors

-- Glen Myers, “The art of Software Testing”

Buon test: buone probabilità di trovare erroriNon può dimostrare l’assenza di erroriPuò solo mostrare la presenza di errori

Ad alto consumo di risorse e tempoNon è insolito dedicare al testing il 40% degli sforzi

complessivi di un progetto

29

AOTAOTLABLAB Classificazione dei test

Tipi di testWhite boxBlack box test

Livelli di testUnit test Integration testSystem test

Ripetizione di testRegression test

30

AOTAOTLABLAB Testabilità

Qualità del software che influiscono sulla capacità dirilevare errori

Osservabilità – Risultato di un test raggiungibile e visibileControllabilità – Ingressi e stato di un programma

devono essere controllabili prima di eseguire un testDecomponibilità – Il programma deve essere diviso in

parti che possano essere testate individualmenteComprensibilità – L’intenzione del programmatore, sul

comportamento corretto del programma, deve esseredisponibile per il tester

Progettazione per testabilità

31

AOTAOTLABLAB Test utopia

In un mondo ideale, tutti i possibili percorsi di esecuzionedi un programma dovrebbero essere testati

Test totale di un programma: esecuzione di tutte lepossibili combinazioni di comandi ed espressioni relativealle strutture di controlloAnche in piccoli programmi, il numero di percorsi in un test totale è

molto ampio In molti programmi, non è noto il limite di percorsi di un test totaleNel mondo reale, bisogna selezionare il sottinsieme di percorsi del

test totale con maggiore probabilità di rilevare errori nel programma

32

AOTAOTLABLAB Prove matematiche

Una dimostrazione matematica di un programma è unaalternativa (principalmente accademica) al testing

Le post condizioni devono essere verificate dato cheLe precondizioni siano verificate Il programma termina

Si basa suAnnotazione del programma con asserzioni matematiche che

riflettono il comportamento attesi dal programmaProprietà che valgono per i vari costrutti del programmaLe dimostrazioni eseguite a mano avranno probabilmente più errori

che il programma stessoMaggiore fiducia solo da dimostrazioni automatiche

33

AOTAOTLABLAB Testing white box

Usa le strutture di controllo di un programma perderivare i test caseScopo: garantire che tutti i comandi e le espressioni di un

programma siano eseguiti almeno una volta

DesiderataTutti i percorsi indipendenti di una unità del programma siano

eseguiti almeno una voltaTutte le derivazioni logiche siano esercitateTutti i cicli e le strutture dati siano esercitati ai loro limiti

34

AOTAOTLABLAB Basic path testing

Tecnica di testing “white box”, che aiuta a scegliere uninsieme minimo di percorsi in un programma checoprono tutte le istruzioni e condizioni

Un percorso in una unità di programma è una sequenzadi comandi e condizioni, dall’inizio alla fine

Cammino indipendente: aggiunge almeno una nuovaistruzione o condizione rispetto ai cammini indipendentigià identificati

Approccio complessivo1. Tracciare un diagramma di flusso della unità2. Astrarre il diagramma in un grafo3. Trovare la complessità ciclomatica (diciamo n) – metrica di test4. Trovare n casi di test che seguono ciascun cammino indipendente

35

AOTAOTLABLAB Complessità ciclomatica

public static void P(){// Entrywhile(A) {X;if (B) {

if(C)Y;

elseZ;

// p} else {

V; W;}// q

}// Exit: r

}}

36

AOTAOTLABLAB Diagramma di flusso

37

AOTAOTLABLAB Grafo di flusso

Piccola astrazione rispetto ad un diagramma di flusso

A, rA, X, B, C, Y, p, q, A, rA, X, B, C, Z, p, q, A, rA, X, B, V, W, q, A, r

38

AOTAOTLABLAB Grafo di flusso

39

AOTAOTLABLAB Metrica e casi di test

Calcolare la metrica e trovare i casi di test sulla basedella complessità

Complassità ciclomatica: determinata sul grafo,usando semplici concetti della teoria dei grafiNumero di regioni del grafo di flusso, oNumero di nodi predicato + 1

Costruire un caso di test per ogni camminoindipendenteIl caso di test dovrebbe seguire il controllo del percorso

40

AOTAOTLABLAB Esempio: GCD

int gcd(int i, int j) {int small, large, remainder;if (i <= j)small = i;

elsesmall = j;

if (i <= j)large = j;

elselarge = i;

while (small > 0) {remainder = large % small; large = small; small = remainder;

}return large;

}void main() {int i, j;printf("Enter two positive integers: "); scanf("%d %d", &i, &j);printf("GCD of %d and %d is %d\n\n", i, j, gcd(i,j));

}

41

AOTAOTLABLAB Complessità di GCD

La complessità ciclomatica di GCD è 4In generale, la complessità ciclomatica è un limite

superiore per il numero di test case necessariNella funzione GCD, è possibile coprire tutte le righe di

codice con due test case

Si noti che in gcd le condizioni delle due strutture dicontrollo sono accoppiateCattiva programmazione!Potrebbe essere impossibile trovare dat che esercitino tutti I

cammini indipendenti

42

AOTAOTLABLAB Black box testing

Usa l’interfaccia di una unità di programma per costruireI test case

Lo scopo è dimostrare che viene prodotta l’uscitacorretta per input validi – in relazione ai requisitifunzionali

DesiderataTrovare gli errori funzionali: otteniamo i risultati attesi per dati input

di un metodo?Trovare errori di interfaccia: i dati sono passati correttamente tra i

metodi?Trovare errori di efficienza: il metodo è abbastanza veloce?

43

AOTAOTLABLAB Input per un test black box

Non è realistico – da un punto di vista combinatorio –testare un programma su tutti i possibili ingressi

Questione centrale: scelta valori d’ingressoPartizionamento degli ingressi in classi di equivalenzaSi ipotizza che sia sufficiente testare l’unità di programma su un

solo caso per classe

Si includono i casi limiteTipo collezioni vuote o piene

Si includono uno o più casi di input non validoCon controllo sui tipi e precondizioni lo spazio è limitato

44

AOTAOTLABLAB Partizioni d’equivalenza

// Exchange element i and j in tablepublic void swapElements(T[] table, int i, int j) {

. . .}

Partizioni d’equivalenza – tutte le combinazioni di:Table

Vuota, o non vuota i, j

Almeno uno tra i e j fuori dai limitiSia i che j dentro i limiti: i < j, i > j, i = j

L’uso di controllo dei tipi e controllo dei limiti riduce ilnumero di casi di test

45

AOTAOTLABLAB Partizioni d’equivalenza

// Find the largest element in table in between from and to.// Precondition: 0 <= from <= to <= table.Count-1public int findMaxIndex(T[] table, int from, int to) {

. . .}

Precondizioni ben scelte riducono il numbero di test

Partizioni d’equivalenza – tutte le combinazioni di:Table

VuotaElemento maggiore primo, ultimo o a metà in tableTutti elementi uguali

from e to from e to ai limiti della tabella from = to, from = to - 1, oppure lontani tra loro

46

AOTAOTLABLAB Regression testing

Lo scopo del regression test è trovare errori diregressioneErrori in un programma che prima era corretto, ed è stato modificato

di recenteUn errore di regressione è un errore che non c’era

Dopo la modifica di una perte P nel programma QTestare che la parte P funzioni correttamenteTestare che l’intero programma Q non sia stato danneggiato dalla

modifica

47

AOTAOTLABLAB Annotazioni

Forniscono dati su un programmaNon sono parte delle istruzioni del programma stesso

Usi: Informazioni per il compilatore - Per rilevare errori o sopprimere

warningElaborazione durante la compilazione o il deployment – Gli

strumenti software possono generare code, file XML ecc.Elaborazione durante l’esecuzione – Alcune annotazioni sono

disponibili a runtime

Le annotazioni possono essere applicate a classi, campi,metodi e altri elementi del programma

48

AOTAOTLABLAB Sintassi

All’inizio di una riga, (per convenzione su una rigapropria), può includere elementi con nome

@Author(name = "Benjamin Franklin",date = "3/27/2003“

)class MyClass() { }

@SuppressWarnings(value = "unchecked")void myMethod() { }

@SuppressWarnings("unchecked") // name omitted, just one elementnamed "value“

void myMethod() { }

@Overridevoid mySuperMethod() { }

49

AOTAOTLABLAB Documentazione

// metadata in commentspublic class Generation3List extends Generation2List {// Author: John Doe// Date: 3/17/2002// Current revision: 6// Last modified: 4/12/2004// By: Jane Doe// Reviewers: Alice, Bill, Cindy

// class code goes here}

// metadata in annotations@interface ClassPreamble {String author();String date();int currentRevision() default 1;String lastModified() default "N/A";String lastModifiedBy() default "N/A";String[] reviewers(); // Note use of array

}

50

AOTAOTLABLAB Documentazione

Dopo aver definito un tipo d’annotazione, si può usarefornendo i valori richiesti

@Retention(RetentionPolicy.RUNTIME) // keep info for runtime@Documented // add metadata to javadoc documentation@ClassPreamble (author = "John Doe",date = "3/17/2002",currentRevision = 6,lastModified = "4/12/2004",lastModifiedBy = "Jane Doe“reviewers = {"Alice", "Bob", "Cindy"} // Note array notation

)public class Generation3List extends Generation2List {// class code goes here

}

51

AOTAOTLABLAB Annotazioni per il compilatore

Tre annotazioni predefinite nelle specifiche dellinguaggio

@Deprecated Indica elementi non più in uso Il compoilatore genera un warning se un programma lo usaViene documentato in Javadoc

@Override Informa il compilatore che si sovrascrive un elemento della

superclasse

@SuppressWarnings Il compilatore non genera warningdeprecation:unchecked: uso di codice senza generics

52

AOTAOTLABLAB Elaborazione delle annotazioni

Possibile scrivere processori di annotazioni, per leggereun programma e agire a seconda delle annotazioni

Generazione automatica di codice ripetitivo

Occorre implementare AnnotationProcessor

Java 5: apt (annotation processing tool)Java 6: funzionalità inclusa nel compilatore javac

53

AOTAOTLABLAB JUnit

Caratteristiche principaliNovità delle ultime versioniTest parametrici, di eccezione e temporizzatiFixture flessibiliRaggruppamento ad esclusione di testTesting con Eclipse e Ant

54

AOTAOTLABLAB Il vecchio JUnit

Prima dell’aggiunta delle annotazioni in Java 5, ilframework JUnit (ver<4) aveva stabilito due convenzioniessenziali per il suo funzionamento

1. Ogni metodo scritto per funzionare come un test logicocominciava con la parola “test” Se un metodo cominciava così, es. testUserCreate, veniva

incluso nel processo di test (fixture eseguite prima e dopo)

2. Una classe veniva riconosciuta da JUnit comecontenitore di test solo se estendeva TestCase

Un test che violava una delle due convenzioni, nonveniva eseguito

55

AOTAOTLABLAB Esempio JUnit (ver<4)

import java.util.regex.Matcher;import java.util.regex.Pattern;import junit.framework.TestCase;

public class RegexTest extends TestCase {private String zipRegEx = "^\\d{5}([\\-]\\d{4})?$";

public void testZipCode() throws Exception {Pattern pattern = Pattern.compile(zipRegEx);Matcher m = this.pattern.matcher("12345");boolean isValid = m.matches();assertTrue("Zip code wasn’t validated", isValid);

}}

56

AOTAOTLABLAB JUnit 4

JUnit 4 usa le annotazioni di Java 5 per eliminarecompletamente entrambe le convenzioni

1. La gerarchia di classi non è più richiesta2. Ogni metodo che si vuole far fuzionare come test deve

essere annotato come @Test

Static import Gli static import di Java 5 permettono di usare più facilmente i

metodi della classe Assert, es. assertFalse I test non estendono più TestCase, nè alcuna classe

57

AOTAOTLABLAB Esempio JUnit 4

import java.util.regex.Matcher;import java.util.regex.Pattern;import org.junit.Test;import static org.junit.Assert.assertTrue;

public class RegexTest {private String zipRegEx = "^\\d{5}([\\-]\\d{4})?$";

@Testpublic void verifyGoodZipCode() throws Exception {

Pattern pattern = Pattern.compile(zipRegEx);Matcher m = this.pattern.matcher("22101");boolean isValid = m.matches();assertTrue("Zip code wasn’t validated", isValid);

}}

58

AOTAOTLABLAB Vantaggio delle annotazioni

Le annotazioni documentano chiaramente ciò che unmetodo dovrebbe fare

Non richiedono di conoscere il modello interno delframework e tutte le convenzioni

In precedenza era richiesta familiarità con le convenzionidi JUnit anche solo per capire un test case

Inoltre le annotazioni aggiungono altre potenzialità alprocesso di test

59

AOTAOTLABLAB Test di eccezioni

Come nelle vecchie versioni di JUnit, bisogna specificareche i test possono lanciare ExceptionFunzionamento normale: se un test lancia una eccezione, il

framework marca il test come fallito

Caso particolare se si vuole testare il lancio di una certaeccezioneSull’annotazione @Test si può specificare il parametro expectedRappresenta il tipo di eccezione che dovrebbe venir lanciata

L’esempio seguente mostra il test delle eccezioni primanella vecchia forma, e poi nella nuova, più chiara

60

AOTAOTLABLAB Esempio con eccezioni (ver<4)

import java.util.regex.Matcher;import java.util.regex.Pattern;import junit.framework.TestCase;

public class RegexTest extends TestCase {private String zipRegex = "^\\d{5}([\\-]\\d{4})?$";private Pattern pattern;

protected void setUp() throws Exception {this.pattern = Pattern.compile(this.zipRegex);

}public void testZipCodeGroupException() throws Exception {Matcher m = this.pattern.matcher("12345-4321");boolean isValid = m.matches();try {m.group(2);fail("No exception was thrown");

} catch(IndexOutOfBoundsException e) { }}

}

61

AOTAOTLABLAB Aggiornamento test di eccezioni

Le vecchie versioni di JUnit richiedono un po’ di codiceper creare un semplice test sulle eccezioniAggiungere un blocco try/catch Invocare il fallimento del test se l’eccezione non viene catturata

Test di eccezioni in JUnit 4Differenza principale: si usa il nuovo paramento expectedÈ possibile aggiornare vecchi test aggiungendo l’eccezione alla

annotazione @Test

62

AOTAOTLABLAB Esempio con eccezioni

import java.util.regex.Matcher;import java.util.regex.Pattern;import org.junit.BeforeClass;import org.junit.Test;

public class RegexTest {private static String zipRegex = "^\\d{5}([\\-]\\d{4})?$";private static Pattern pattern;

@BeforeClasspublic static void setUpBeforeClass() throws Exception {pattern = Pattern.compile(zipRegex);

}@Test(expected=IndexOutOfBoundsException.class)public void verifyZipCodeGroupException() throws Exception {Matcher m = this.pattern.matcher("12345-4321");boolean isValid = m.matches();m.group(2);

}}

63

AOTAOTLABLAB Test temporizzati

In JUnit 4, un test può prendere un valore di timeoutcome parametro

Il valore di timeout rappresenta il massimo intervallo ditempo che l’esecuzione del test può impiegare

Se il tempo scade, il test fallisce

@Test(timeout=1)public void verifyFastZipCodeMatch() throws Exception {Pattern pattern = Pattern.compile("^\\d{5}([\\-]\\d{4})?$");Matcher m = pattern.matcher("12345");boolean isValid = m.matches();assertTrue("Pattern did not validate zip code", isValid);

}

64

AOTAOTLABLAB Test da ignorare

Prima di JUnit 4, ignorare un test sbagliato o incompletoera possibile in maniera piuttosto rozzaAlterare il nome del metodo in modo da infrangere la convenzioneSpesso si aggiungeva un underscore prima del nome del metodo,

per indicare che il test non era da eseguire

JUnit 4 ha introdotto la chiara annotazione @Ignore Indica al framework di ignorare un certo metodo di testSi può anche passare un messaggio per documentare la decisione

agli altri sviluppatori, altrimenti ignari dei motivi dell’esclusione

65

AOTAOTLABLAB Esempio di test da ignorare

@Ignore("this regular expression isn't complete yet")@Testpublic void verifyZipCodeMatch() throws Exception {Pattern pattern = Pattern.compile("^\\d{5}([\\-]\\d{4})");Matcher m = pattern.matcher("12345");boolean isValid = m.matches();assertTrue("Pattern did not validate zip code", isValid);

}

66

AOTAOTLABLAB Perché usare le fixture

Le fixture incoraggiano il riuso, definendo del codice chedeve essere eseguito prima o dopo i test

Nelle vecchie versioni di JUnit ciò era implicito, sia che lefixture fossero implementate o no

JUnit 4 ha reso le fixture esplicite con le annotazioniCodice fixture eseguito solo se necessarioSi può specificare che certe fixture siano eseguite prima o dopo di

certi test, codice riusato

67

AOTAOTLABLAB Esempi di fixture

Esempi Inizializzare una classe che verrà testata in modi diversiPopolare un database prima di eseguire test dipendenti dai dati

In ogni caso, l’uso delle fixture permette di gestire meglioi test, sfruttando logica comune

Le fixture tornano utili specialmente quando molti testusano in parte la stessa logica In caso di problemi, si può analizzare il codice di setup concentrato

in un solo punto, anzichè scorrere tutti i test

68

AOTAOTLABLAB Fixture inflessibili

Le vecchie versioni di JUnit impiegavano un modello difixture poco flessibileL’esecuzione di ogni test veniva preceduta dal metodo setUp e

seguita dal metodo tearDown

Svantaggio: metodi eseguiti più volte, una per ogni testdefinito

Nelle versioni precedenti di JUnit era possibilespecificare di eseguire una fixture solo una voltaSi istanziava un oggetto TestSetup nel metodo suiteMa era una operazione abbastanza scomodaManeggiare le fixture poteva portare più grattacapi che benefici

69

AOTAOTLABLAB Esempio di fixture di test (ver<4)

import . . .public class RegexTest extends TestCase {private Pattern pattern;protected void setUp() throws Exception {this.pattern = Pattern.compile("^\\d{5}([\\-]\\d{4})?$");

}public void testZipCodeGroup() throws Exception {Matcher m = this.pattern.matcher("12345-4321");assertEquals("group(1) didn't match", "-4321", m.group(1));

}public void testZipCodeGroupException() throws Exception {Matcher m = this.pattern.matcher("12345-4321");boolean isValid = m.matches();try{m.group(2);fail("No exception was thrown");

} catch(IndexOutOfBoundsException e) { }}

}

70

AOTAOTLABLAB Esempio di fixture di classe (ver<4)

import java.util.regex.*;import junit.extensions.TestSetup;import junit.framework.Test;import junit.framework.TestCase;import junit.framework.TestSuite;import junit.textui.TestRunner;

public class RegexTest extends TestCase {private static Pattern pattern;

public static Test suite() {TestSetup setup = new TestSetup(

new TestSuite(OneTimeRegexTest.class)) {protected void setUp() throws Exception {pattern = Pattern.compile("^\\d{5}([\\-]\\d{4})?$");

}};return setup;

}. . .

71

AOTAOTLABLAB Esempio di fixture di classe (ver<4)

. . .public void testZipCodeGroup() throws Exception {Matcher m = pattern.matcher("12345-4321");boolean isValid = m.matches();assertEquals("group(1) didn't match", "-4321", m.group(1));

}public void testZipCodeGroupException() throws Exception {Matcher m = pattern.matcher("12345-4321");boolean isValid = m.matches();try {m.group(2);fail("No exception was thrown");

} catch (IndexOutOfBoundsException e) { }}

}

72

AOTAOTLABLAB Fixture in JUnit 4

Nuovo e migliorato modello di fixture in JUnit 4 JUnit 4 usa le annotazioni per eliminare molto overhead relativo alle

fixturePermette di eseguire una fixture per ogni test, per una intera classe,

o non eseguirla affatto

2 annotazioni per le fixture di livello classeA livello di classe ci sono @BeforeClass e @AfterClassUtili per ottimizzazione (es. collegamento a DB)

2 annotazioni per le fixture di livello metodo (test)A livello di metodo (o test) ci sono @Before e @AfterPossibile specificare dei test con una annotazione @Target

73

AOTAOTLABLAB Fixture di test

import . . .public class RegexTest {private static Pattern pattern;@Beforepublic static void setUpBeforeClass() throws Exception {pattern = Pattern.compile("^\\d{5}([\\-]\\d{4})?$");

}@Testpublic void verifyZipCodeNoMatch() throws Exception {Matcher m = this.pattern.matcher("1357");boolean notValid = m.matches();assertFalse("Pattern did validate zip code", notValid);

}@Test(expected=IndexOutOfBoundsException.class)public void verifyZipCodeGroupException() throws Exception {Matcher m = this.pattern.matcher("12345-4321");boolean isValid = m.matches();m.group(2);

}}

74

AOTAOTLABLAB Fixture di classe

import . . .public class RegexTest {private static Pattern pattern;@BeforeClasspublic static void setUpBeforeClass() throws Exception {pattern = Pattern.compile("^\\d{5}([\\-]\\d{4})?$");

}@Testpublic void verifyZipCodeNoMatch() throws Exception {Matcher m = this.pattern.matcher("1357");boolean notValid = m.matches();assertFalse("Pattern did validate zip code", notValid);

}@Test(expected=IndexOutOfBoundsException.class)public void verifyZipCodeGroupException() throws Exception {Matcher m = this.pattern.matcher("22101-5051");boolean isValid = m.matches();m.group(2);

}}

75

AOTAOTLABLAB Fixture multiple

Si possono specificare più fixture per un test caseLe annotazioni di JUnit4 possono essere ripetute,

marcando con @Before o @BeforeClass diversimetodi

Ma non si può specificare l’ordine di esecuzioneVengono eseguite prima le fixture delle classi genitore

76

AOTAOTLABLAB Test suite

Meccanismo usato per raggruppare logicamente dei tested eseguirli assieme

L’annotazione @SuiteClasses raggruppa una lista diclassi, passate come parametro, in una test suite

L’annotazione @RunWith permette di impostare diversiesecutori di test

Di solito si usa Suite, già incluso nel framework

Esempio che mostra come gestire le suite nelle diverseversioni di JUnit

77

AOTAOTLABLAB Esempio di test suite (ver<4)

import junit.framework.Test;import junit.framework.TestSuite;

public class JUnit3Suite {public static Test suite() {TestSuite suite = new TestSuite();suite.addTest(RegexTest.class);suite.addTest(ParametricRegexTest.class);suite.addTest(TimedRegexTest.class);return suite;

}}

78

AOTAOTLABLAB Esempio di test suite

import org.junit.runner.RunWith;import org.junit.runners.Suite;import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)@SuiteClasses({

ParametricRegexTest.class,RegexTest.class,TimedRegexTest.class})

public class JUnit4Suite {}

79

AOTAOTLABLAB Esecuzione dei test

Si può eseguire una classe di test di JUnit 4 da un IDEcome EclipseRun As JUnit test

Oppure da linea di comandoEseguire la classe org.junit.runner.JUnitCore, passando

come argomento il nome completo di una classe di test

java org.junit.runner.JUnitCore <test class name>

80

AOTAOTLABLAB Profilo d’esecuzione in Eclipse

81

AOTAOTLABLAB Esecuzione in Ant

<!-- Define any necessary Ant properties --><property name="src" value="./src" /><property name="lib" value="./lib" /><property name="classes" value="./classes" /><property name="test.class.name" value="com.xyz.MyTestSuite" /><!-- Set up the CLASSPATH to be used by JUnit --><path id="test.classpath"><pathelement location="${classes}" /><pathelement location="/path/to/junit.jar" /><fileset dir="${lib}"><include name="**/*.jar"/></fileset>

</path>

<!-- Define the Ant task for running JUnit --><target name="test"><junit fork="yes" haltonfailure="yes"><test name="${test.class.name}" /><formatter type="plain" usefile="false" /><classpath refid="test.classpath" />

</junit></target>

82

AOTAOTLABLAB Esecuzione di più test in Ant

. . .

<!-- Define the Ant task for running JUnit --><target name="test"><junit printsummary="yes" haltonfailure="yes">. . .<batchtest fork="yes"><fileset dir="${test.dir}">

<include name="**/*Test.java" /><include name="**/Test*.java" />

</fileset></batchtest>

</junit></target>

83

AOTAOTLABLAB Assert su array

Nuovo metodo di assert per confrontare il contenuto didue array

L’esempio seguente fallisce per le differenze tra glielementi

@Testpublic void verifyArrayContents() throws Exception {String[] actual = new String[] {

"JUnit 3.8.x", "JUnit 4", "TestNG"};String[] var = new String[] {

"JUnit 3.8.x", "JUnit 4.1", "TestNG 5.5"};assertEquals("the two arrays are not equal", actual, var);

}

84

AOTAOTLABLAB Test parametrici

In alcune applicazioni, può essere necessario scrivereun’enorme quantità di test

Nelle vecchie versioni di JUnit, la situazione eracomplicata

Per ripetere un test con diversi parametri occorrevascrivere un test case per ogni gruppo di parametri

JUnit permette le creazione di test generici che possonoessere eseguiti su parametri modificabili

Si può quindi creare un unico test case da eseguire piùvolte, una per ogni gruppo di parametri

85

AOTAOTLABLAB Test parametrici

Serie di passi per creare dei test parametrici

1. Creare un normale test, senza parametri2. Creare un metodo statico di fornitura dati: restituisce

una Collection, è annotato con @Parameter3. Aggiungere campi di classe per i parametri4. Scrivere un costruttore che riceve dei parametri e

inizializza i campi5. Specificare nella annotazione @RunWith che il test

case deve essere eseguito con la classeParameterized

86

AOTAOTLABLAB Esempio di test parametrico

Provare una espressione regolare su molti valoriSi noti che i valori di phrase e match non sono definiti

@Testpublic void verifyGoodZipCode() throws Exception {Matcher m = this.pattern.matcher(phrase);boolean isValid = m.matches();assertEquals("Pattern did not validate zip code", isValid, match);

}

87

AOTAOTLABLAB Fornitura dei parametri

Il passo successivo è creare un metodo di fornituraDeve essere static e deve restituire una CollectionDeve essere associato all’annotazione @ParametersEs. nel metodo si può creare un array multi-dimensionale diObject e convertirlo in una List

@Parameterspublic static Collection regExValues() {return Arrays.asList(new Object[][] {

{"22101", true },{"221x1", false },{"22101-5150", true },{"221015150", false }});

}

88

AOTAOTLABLAB Creare i campi e il costruttore

Ci sono due parametri, di tipo String e boolean, chedevono corrispondere a due campi nella classe

Poi bsogna creare un costruttore che colleghi i campi aivalori dei parametri

private String phrase;private boolean match;

public ParametricRegexTest(String phrase, boolean match) {this.phrase = phrase;this.match = match;

}

89

AOTAOTLABLAB Specificare la classe parametrizzata

Infine, bisogna specificare a livello di classe che il testdeve essere eseguito con la classe Parameterized,usando l’annotazione @RunWith

@RunWith(Parameterized.class)public class ParametricRegexTest {. . .

}

90

AOTAOTLABLAB Esecuzione di test parametrici

Nel test precedente, il metodo verifyGoodZipCodeviene eseguito 4 volte

Una volta per ciascuna coppia riportata dal metodo diproduzione dati regExValues