1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA...

55
1 Testing e Debugging

Transcript of 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA...

Page 1: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

1

Testing e Debugging

Page 2: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

2

Perché? Che cosa? Quando?

• GOAL: software con zero difetti …MA impossibile da ottenere e garantire

• Necessaria una attenta e continua VERIFICA

• Tutto deve essere verificato: documenti di specifica, di progetto, dati di collaudo, ….programmi

• Si fa lungo tutto il processo di sviluppo, NON solo alla fine!

Page 3: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

3

Terminologia

• Verifica (verification): insieme delle attività volte a stabilire se il programma costruito soddisfa le specifiche (non solo funzionali)– did we build the program right?

• si assume che le specifiche esprimano in modo esauriente i desiderata del committente

• Testing: particolare tipo di verifica sperimentale fatta mediante esecuzione del programma, selezionando alcuni dati di ingresso e valutando risultati

Page 4: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

4

Terminologia• Debugging: localizzare errori (difetti) nel

codice (il testing ne rivela la presenza ma non li localizza)

• Programmazione difensiva: insieme di tecniche di programmazione che cercano di evitare di introdurre errori, aumentano probabilità di correttezza e facilitano verifica e debugging

• Convalida: stabilire se il programma soddisfa le “aspettative” del committente (indipendentemente dalle sue specifiche)

Attenzione: terminologia non standardizzata!

Page 5: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

5

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

• programma provato solo per quei dati

• GOAL: trovare "controesempi"• Tecnica dinamica rispetto alle verifiche

statiche fatte dal compilatore

Page 6: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

6

Testing• Testing esaustivo (esecuzione per tutti i

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 109 esecuzioni!

– per programmi banali si arriva a tempi di esecuzione pari al tempo passato dal big-bang

Page 7: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

7

Testing

• Program testing can be used to show the presence of bugs, but never to show their absence. (Dijkstra 1972)

• Obiettivo: trovare dati di test che massimizzino la probabilità di trovare errori

Page 8: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

8

Criteri di test• È cruciale la scelta di opportuni valori

(dati o casi di test) "sufficienti a convincerci" che il programma è corretto

p.es.: eseguire il programma con i valori 1, 10 e 5.

• In base a che cosa si determinano i casi di test? – in base alla specifica (test black-box o

funzionale; esiste anche un test white/glass-box, di cui qui non parliamo)

e quando?– idealmente, nel momento in cui si scrive la

specifica del modulo

• In base a quali criteri?

Page 9: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

9

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

Page 10: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

10

Test funzionale: combinazioni proposizionali

(1)ESEMPIO• Combinare i vari casi alternativi espressi da una

specificastatic boolean isPrime (int x)

//@ensures (* \result <==> x è primo*)– Scegliere dati di test primi e non primi. Es. 5 e 8

Page 11: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

11

Test funzionale: combinazioni proposizionali

(2)In generale, possiamo identificare le parti in alternativa di una specifica espressa come formula di logica proposizionale usando l’operatore ||

static float sqrt (float x, float epsilon)//@requires x >= 0 && .00001 < epsilon < .001 ;//@ensures x-epsilon <= \result * \result <= x+epsilon ;

– REQUIRES congiunzione di x >= 0 con .00001<epsilon<.001

• Parte x >= 0 equivalente a x=0 || x>0

– Combinazioni ottenibili:• x = 0 && .00001 < epsilon < .001• x > 0 && .00001 < epsilon < .001

Page 12: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

12

Il metodo seguito

• Si esamina la clausola requires e, se possibile, la clausola effects

• Si partiziona il dominio di ingresso in sottoinsiemi come specificato da essa, riducendo la formula proposizionale in forma– x1&&x2&&…. || y1&&y2&&… ym || …

• NB: metodo applicabile a clausole requires ma non sempre a clausola ensures– in questo caso non conoscendo codice

impossibile prevedere se \result*\result <x o =x o >x: come scegliere x?

Page 13: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

13

Es. applicato a effects• Es. static int maxOfThree (int x, int y, int z) {//@ensures (* restituisce il valore massimo fra x, y,

z *)• Ci sono tre alternative: il massimo è x, è y, o è z

• Es. static int maxOfThree (int x, int y, int z) {//@ ensures \result == x && x>=y && x>=z ||

\result == y && y>=x && y>=z ||\result == z && z>=x && z>=y

• Ci sono tre alternative: il massimo è x, è y, o è z• Casi di test ricavabili da ensures:

– Un caso in cui il massimo è x, p. es. (5,3,0)– Un caso in cui il massimo è y, p. es. (7,11,2)– Un caso in cui il massimo è z, p. es. (7,10,12)

Page 14: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

14

Testing funzionale (cont.)

• Altre volte possibile e necessario usare clausola ensuresstatic boolean isPrime (int x)

//@ensures \result == true iff x prime

– Scegliere dati di test primi e non primi

Page 15: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

15

Casi eccezionali• Testare non solo il comportamento normale ma

anche le eccezioni//@ensures a!=null && //@ (\exists int i; 0<=i && i<a.length; x==a[i]) && a[\result]==x ;//@ signals (NotFoundException e) //@ (\forall int i; 0<=i && i<a.length; x != a[i]);//@ signals (NullPointerException e) a == null

static int search (int [] a, int x) throws NotFoundException, NullPointerException

– Testare search con array a null, con x non in a, con x in a • ?? testare anche con input che non soddisfa clausola

requires??– NO, se metto requires è responsabile il cliente– se invece metto eccezione, devo anche testare la via cha la

genera

è bene evitare la requires e definire funzioni totali

Page 16: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

16

Testing con valori limite (boundary values)

• Se valore dell’input può stare in un intervallo, testare estremi dell’intervallo e combinare valori limite

• Esempi:– valori estremi per i numeri (max. int

ammissibile)– sqrt con radicando = 0 – stringa: vuota o di 1 carattere– array: array vuoto o di un elemento– elaborazioni con array: considerare

valori estremi degli indici

Page 17: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

17

Altri esempi

– Triangoli identificati da vertici: • tre punti allineati• due punti coincidenti• tre punti coincidenti• triangolo rettangolo• un vertice nell’origine o sugli assi • ….

Page 18: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

18

Esempio//@ensures (*\result è il massimo fra x, y, z *)static int maxOfThree (int x, int y, int z)

• Casi limite: • x = y = z: p.es. 3, 3,3• x=y !=z• ecc.

Page 19: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

19

Esempio: casi limite con alias• Due parametri si riferiscono a due oggetti

mutabili, dello stesso tipo• Considerare casi in cui coincidono, anche

se non previsto esplicitamente dalle specifiche

//@ensures(* removes all elements of v2 and appends //@them in reverse order to the end of v1 *)

static void appendVector(Vector v1, Vector v2){ while (v2.size() > 0)

{ v1.addElement(v2.lastElement());v2.removeElementAt(v2.size()-1); }

}NON è vietato che v1 e v2 siano lo stesso Vector: testando questo caso si trova un errore

Page 20: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

20

Testing di astrazioni sui dati

• Si effettua test per tutte le operazioni del tipo di dato, MA sfruttando sinergie tra metodi costruttori e modificatori e metodi osservatori

• Caso di studio: l’astrazione IntSet

Page 21: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

21

Specifica di IntSetpublic class IntSet {

/*OVERVIEW: insiemi di interi illimitati e modificabili; per es.: {1, 2, 10, -55} *///costruttori://@ensures (\forall int y;;!this.isIn(y)); public IntSet(){ }//metodi mutators://@ ensures this.isIn(x) && (\forall int y; x!=y; //@ \old(this.isIn(y)) <==> this.isIn(y)); public void insert(int x){ } //@ ensures !this.isIn(x) && (\forall int y; x!=y; //@ \old(this.isIn(y)) <==> this.isIn(y));public void remove(int x){ }//@ensures (*\result è true sse x è fra gli elementi di this*); public boolean isIn (int x){}//@ ensures (*\result è cardinalità di this *); public int size(){}

Page 22: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

22

Esempio: Test di IntSet

• Testing funzionale: – valori limite: generare IntSet con 0, 1 o 2 el.– per ognuno testare isIn (risultato false e true), size, elements

– testare size dopo insert e remove, con aggiunta o cancellazione di elemento presente o assente

– testare elements per insiemi di 0, 1, 2, elementi

Page 23: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

23

Verificare RI e specifiche• Quando si testano classi, casi di test diventano

molto numerosi. • Difficile capire se i risultati sono corretti, e nel caso

in cui siano scorretti qual’e la causa dell’errore.• Per automatizzare, allora verificare

sistematicamente RI (es. chiamando un metodo repOK() dopo ogni operazione di costruzione e modifica)

• Es. Aggiungere repOk() (verifica invariante)– quando si esce da IntSet(), remove(), insert()

• Se possibile anche verifica delle pre e postcondizioni

• Tutto questo aiuta ad automatizzare il testing e successivamente semplifica il debugging

Page 24: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

24

Esempio: semplificare post• Verifica della postcondizione di

insert è difficile perche’ richiede di verificare che tutti gli elementi già presenti nell’insieme non sono eliminati

• Piu’ facile verificare solo che la cardinalità dell’insieme sia corretta:

isIn(x) && (\old(isIn(x))==> size(x)==\old(size(x)) ||

\old(isIn(x))==>size(x)==1+\old(size(x)))

Page 25: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

25

Test delle gerarchie di tipi

• Dati di test funzionale per sottotipo devono includere quelli del supertipo; in generale sottotipo testato con – dati di test funzionali per supertipo,

con in più chiamate del costruttore del sottotipo

– dati di test funzionali aggiuntivi caratteristici del sottotipo

Page 26: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

26

Test di unità e di integrazione• Test di unità

– verifica di un singolo modulo isolatamente

• Test di integrazione– verifica di corretta interazione dei moduli

• Test di integrazione più difficile– comportamento da testare più complesso– maggiore dimensione del codice– spesso interazione poco/mal specificata, e

moduli di tipo e provenienza disomogenea

Conviene prima test di unità e poi test di integrazione (divide et impera)

Page 27: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

27

Test di unità

JUnit

Page 28: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

28

Esecuzione dei test• Quando si testa un programma è

importante definire esattamente i risultati attesi (si parla di oracolo)

• Si può automatizzare sia l'esecuzione dei test che il controllo dei risultati (Junit)

• Junit (http://junit.org/index.htm)– si basa sull'idea "first testing then coding"– "test a little, code a little, test a little, …

Page 29: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

29

Junit: esempio 1

import junit.framework.*; (1)public class SimpleTest extends TestCase { (2)

public SimpleTest(String name) { (3)super(name);

}public void testSimpleTest() { (4)

int answer = 2;assertEquals((1+1), answer); (5)

}}

Page 30: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

30

Spiegazioni• importazione delle classi definite da Junit• va ridefinita la classe TestCase• costruttore del nostro specifico test case,

che ha un nome (ne vedremo l'uso più avanti)

• definizione di uno specifico test interno al test case

• il test verifica che "1+1" produca il risultato definito dall'oracolo; è un metodo statico della classe assert

N.B Terminologia: un test case contiene uno o più test

Page 31: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

31

Classi principali• junit.framework.TestCase

– Consente l'esecuzione di più test, riportando eventuali errori

• junit.framework.Assert– Insieme di metodi assert– Se la condizione di assert è falsa il test fallisce

• junit.framework.TestSuite (vedi più avanti)– Collezione di test– Usa l'introspezione di Java per trovare tutti i

metodi che iniziano per "test" e hanno parametri void

– Il metodo run di TestSuite esegue tutti i test

Page 32: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

32

Esempio 2Test di una funzione stringStrip cheelimina tutte le "a" da una stringa

public void testStringStripFunction() {String expected = "bb"StringStripper stripper = new

StringStripper();assertEquals(expected, stripper.stringStrip("aabaaaba"));

}

Page 33: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

33

Esempio 3 (1)// Adds up a string based on the ASCII values of its// characters and then returns the binary representation sumpublic class BinString {

public BinString() {}public String convert(String s) {

return binarise(sum(s));}public int sum(String s) {

if(s=="") return 0;if(s.length()==1) return ((int)(s.charAt(0)));return ((int)(s.charAt(0)))+sum(s.substring(1));

}public String binarise(int x) {

if(x==0) return "";if(x%2==1) return "1"+binarise(x/2);return "0"+binarise(x/2);

}}

Page 34: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

34

Esempio 3 (2)import junit.framework.*;public class BinStringTest extends TestCase {

private BinString binString;public BinStringTest(String name) {

super(name);}protected void setUp() {

binString = new BinString();}public void testSumFunction() {

int expected = 0;assertEquals(expected, binString.sum(""));expected = 100;assertEquals(expected, binString.sum("d"));expected = 265;assertEquals(expected, binString.sum("Add"));

}

1

2

Page 35: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

35

Esempio 3 (3)

public void testBinariseFunction() {String expected = "101";assertEquals(expected, binString.binarise(5));expected = "11111100";assertEquals(expected, binString.binarise(252));

}public void testTotalConversion() {

String expected = "1000001";assertEquals(expected, binString.convert("A"));

}}

3

4

Page 36: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

36

Spiegazioni

1setUp (da ridefinire) viene chiamato automaticamente prima della valutazione di ogni test; esiste anche tearDown da ridefinire per riportarsi in condizioni che evitino interferenze tra test

test della funzione sum2

test della funzione binarise3

test della funzione convert 4

Page 37: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

37

Ancora JUnit

• Test definiti tramite l’uso della famiglia di ASSERTXXX()– assertTrue()– assertFalse()– assertEquals()– fail()– ...

• È possibile eseguire una Suite di test:– istanziare un oggetto di tipo TestSuite;– aggiungere i test alla suite invocando il

metodo addTest(Test) sull'oggetto istanziato

Page 38: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

38

Nuovo esempiopublic class Triangolo {

private int latoA, latoB, latoC;

public Triangolo(int a, int b, int c) {

latoA = a; latoB = b; latoC = c; }

public boolean valido() { if (latoA == 0 || latoB == 0 ||

latoC == 0) return false; if ((latoA+latoB < latoC) || (latoA+latoC < latoB) || (latoB+latoC < latoA)) return false; return true;

}

public int perimetro() { if (valido()) return latoA+latoB+latoC; else return 0; } }

Page 39: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

39

import junit.framework.*; import Triangolo;

public class TestTriangolo extends TestCase {

private Triangolo t1,t2;

public TestTriangolo(String name) {super(name); }

public void setUp() {

t1 = new Triangolo(2,4,3); t2 = new Triangolo(2,4,8); }

public void testValido() {

assertTrue(t1.valido()); assertFalse(t2.valido()); }

...

Page 40: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

40

...

public void testPerimetro() { assertEquals(9,t1.perimetro()); assertEquals(0,t2.perimetro()); }

/*public static Test suite() { TestSuite suite = new TestSuite(); suite.addTest(new TestTriangolo("testValido")); suite.addTest(new TestTriangolo("testPerimetro")); return suite;} */

public static void main(String args[]) { junit.textui.TestRunner.run(new TestTriangolo("testValido")); junit.textui.TestRunner.run(new TestTriangolo("testPerimetro"));// junit.textui.TestRunner.run(suite());

}}

textui è l’interfaccia testuale,

swingui è quella grafica

Si può eseguire un’intera suite

usa reflection: assume che il nome del test sia il nome del metodo del TestCase che va invocato

Page 41: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

41

Note/*public static Test suite() {

TestSuite suite = new TestSuite(); suite.addTest(new TestTriangolo("testValido")); suite.addTest(new TestTriangolo("testPerimetro")); return suite;} */

Il metodo suite() costruisce una TestSuite suite

Una testSuite è una classe che implementa Test. Dentro di sè tiene come

variabile privata un vettore di test

Page 42: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

42

Un altro esempio

• public class Product– public Product(String title, double price)

• costruttore specializzato per la classe Product. Crea un prodotto come coppia di nome e prezzo

– public String getTitle()• ritorna la stringa nome del prodotto

– public double getPrice()• ritorna il prezzo del prodotto in virgola mobile su 32

bit– public boolean equals(Object o)

• verifica che i prodotti siano uguali• instanceof: se è possibile eseguire cast tra object

o e Product allora ritorna true altrimenti false

Page 43: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

43

• Public class ShoppingCart– public ShoppingCart()

• costruttore della classe ShoppingCart. Crea una istanza del carrello come un array di items

– public double getBalance()• calcola il saldo prendendo tutti gli elementi

dell’array (i prodotti presenti nel carrello) ed eseguendo la somma di tutti i prezzi

– public void addItem(Product p)• aggiunge un elemento (prodotto) nell’array

(carrello)– public void removeItem(Product p)

• rimuove un elemento (prodotto) dall’array (carrello). Solleva una eccezione se il carrello è vuoto

– public int getItemCount()• ritorna il numero di elementi (prodotti) nell’array

(carrello)– public void empty()

• svuota il carrello istanziando un nuovo array– public boolean isEmpty()

• ritorna true se carrello vuoto (array di dimensione zero), false altrimenti

Page 44: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

44

• Public class ProductTest– protected void setUp()– protected void tearDown()– public ProductTest(String name)– public void testGetTitle()

• assertEquals("acer travelmate", notebook.getTitle())

– public void testGetPrice()• assertEquals(1.100, notebook.getPrice(), 0.0)

– public void testEqualsObject()• assertEquals(notebook2.getPrice(),

notebook.getPrice(), 0.0);• assertEquals(notebook2.getTitle(),

notebook.getTitle());• assertTrue(notebook.equals(notebook));• assertTrue(notebook2.equals(notebook));

– public static Test suite()

Page 45: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

45

• Public class ShoppingCartTest– public ShoppingCartTest(String name)– protected void setUp()– protected void tearDown()– public void testProductAdd()

• assertEquals(expectedBalance, _bookCart.getBalance(), 0.0)

• assertEquals(2, _bookCart.getItemCount());– public void testEmpty()

• assertTrue(_bookCart.isEmpty())– public void testProductRemove()

• assertEquals(0, _bookCart.getItemCount())• assertEquals(0.0, _bookCart.getBalance(), 0.0)

– public void testProductNotFound()• fail(“Should Raise an Exception”)

– public static Test suite()

• Public class AllTests– public static Test suite()

Page 46: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

46

Test di regressione• Scenario

– programma testato con dati di test da 1 a n senza trovare errori

– trovato errore con dato (n+1)-simo– debugging e correzione del programma– prosecuzione del test con dato (n+2)-

simo

• Probabilità non trascurabile che la correzione introduca errori che non lo fanno funzionare per qualche dato da 1 a n.

Page 47: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

47

Test di regressione (cont.)

• Consiste nel testare di nuovo il programma, dopo una modifica, con tutti i dati di test usati fino a quel momento, per verificare che non si ha una regressione

• Necessario, ma realizzabile ed economico in pratica solo se il testing è almeno in parte automatizzato

Page 48: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

48

Debugging (1)• Trovare il difetto del programma che dà

origine a comportamento erroneo rivelato dal testing

• Tecniche di debugging riconducibili a due tipi di azioni– identificare causa effettiva usando dati di test più

semplici possibili– localizzare porzione di codice difettoso osservando

stati intermedi della computazione

• NB: costo del debugging (spesso "contabilizzato" sotto la voce: testing) può essere parte preponderante del costo di sviluppo: molto importante sviluppare il software in modo sistematico per minimizzare sforzo speso in debugging

Page 49: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

49

Debugging (2)• Debugging è attivita' difficile da rendere

sistematica, efficienza dipende da persone ed è poco prevedibile, MA occorre cercare di essere sistematici– Identificare almeno uno stato corretto S1 e uno non corretto

S2– Cercare di capire quali stati intermedi tra S1 e S2 sono

corretti e quali no, fino a identificare uno stato corretto S’1 e uno non corretto S’2 consecutivi

– Il difetto è nell’istruzione che separa S’1 e S’2

• Molto utile un debugger: strumento per eseguire programmi in modo controllato: – breakpoint, – esecuzione passo-passo, – visualizzazione e modifica di variabili

Page 50: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

50

Funzionalità essenziali• Breakpoint: permettono di interrompere

l’esecuzione in un certo punto• Esecuzione passo passo: permette di avanzare

l’esecuzione di un passo per volta• Esame dello stato intermedio: permette di

visualizzare il valore delle singole variabili (qui molto utile funzione di astrazione implementata con toString())

• Modifica dello stato: permette di modificare il valore di una o più variabili prima di riprendere l’esecuzione

• Oggi si usano debugger “simbolici” che consentono di operare al livello del linguaggio di programmazione– variabile = variabile del linguaggio, non cella di memoria– passo = istruzione del linguaggio

Page 51: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

51

Programmazione difensiva (1)

• Un pizzico di paranoia può essere utile: scrivere i programmi in modo che scoprano e gestiscano ogni possibile situazione anomala:

• procedure chiamate con parametri attuali scorretti,

• file: devono essere aperti ma sono chiusi, devono aprirsi e non si aprono…

• riferimenti a oggetti null, array vuoti …

• Meccanismo delle eccezioni utile aiuto

Page 52: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

52

Programmazione difensiva (2)

• Essere scrupolosi con il test– ricordarsi che l'obiettivo è trovare gli

errori, non essere contenti di non trovarne

– testare in particolare • le clausole REQUIRES • gli invarianti di rappresentazione

– codificare metodo repOK, testarlo all’inizio di ogni operazione e prima di restituire i risultati

– può convenire dare ad altri il compito di testare i propri programmi

Page 53: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

53

REQUIRES o eccezioni?//@requires x <= y//@ensures a!=null &&//@ (\result <==> (\exists int i; x<=i && i<=y; e==a[i] ) )//@signals (NullPointerException e) a==nullstatic boolean inRange (int [] a, int x, int y, int e) throws NullPointerException

• Se chiamata di inRange scambia secondo e terzo parametro, implementazione diretta potrebbe non accorgersene e restituire false– durante il test aggiungere nel codice di inRange

controllo che x<=y e sollevare eccezione apposita

• in realtà potrebbe essere vantaggioso eliminare REQUIRES e lasciare permanentemente eccezione

Page 54: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

54

Controllare tutti i casi• Può essere molto costoso, ma va fatto

quando possibile– Esempio: ricevibili due soli comandi: "deliver" o

"examine": il codice s = Comm.receive();if (s.equals("deliver")) { // execute deliver} else if (s.equals("examine")) {//execute examine} else { // gestisci errore }

Molto meglio e poco meno efficiente di s = Comm.receive();if (s.equals("deliver")) { // execute deliver} else { //execute examine }

Page 55: 1 Testing e Debugging. 2 Perché? Che cosa? Quando? GOAL: software con zero difetti … MA impossibile da ottenere e garantire Necessaria una attenta e continua.

55

Trade-offs

• Talvolta controllo è troppo costoso: se una procedura di ricerca binaria controlla che insieme di ricerca sia ordinato perde efficienza

• Alternativa per controlli molto costosi: usarli solo in fase di test e debugging (permettono di diminuire i costi della “ricerca guasti”) e toglierli (con attenzione e cautela, trasformandoli in commenti) quando il programma va in produzione