Defect testing n Lobiettivo scoprire difetti in un
Defect testing n L’obiettivo: scoprire difetti in un programma n Un test ha successo se forza il programma a comportarsi in modo anomalo n I test provano la presenza (non l’assenza) di errori: solo un testing esaustivo proverebbe l’assenza di difetti. 1
Priorità nel testing n I test devono sondare le caratteristiche globali del sistema nel suo insieme più che le singole componenti n Se il sistema è una nuova versionedi un sistema esistente, è più importante testare le vecchie caratteristiche testare le nuove caratteristiche n Testare le situazioni tipiche è più importante che testare i valori alla frontiera 2
Dati di test e casi di test n Dati di test L’insieme di input che devono essere costruiti per testare il sistema n Casi di test L’insieme di input per testare il sistema e gli output previsti in corrispondenza di questi input se il sistema soddisfa la sua specifica 3
Terminologia n Per definire i Casi di Test devo adottare un criterio: n Criterio C affidabile n tutti i test selezionati da C hanno successo o nessuno lo ha n Criterio C valido n qualora P non sia corretto, $ un T selezionato C che ha successo 4
Esempio program RADDOPPIA. . . . read (x); y = x*x; write (y); . . . n Se C seleziona solo {0, 2} n è affidabile, non valido n Se C seleziona tutti i sottoinsiemi di {0, 1, 2, 3, 4} n è valido, non affidabile n Se C seleziona insiemi che contengono tutti almeno un elemento < 3 n è valido e affidabile 5
Elementi di teoria dei test Teorema di Goodenough e Gerhart Se Esiste un C affidabile e valido per P e T è selezionato da C e T non ha successo su P allora P è corretto 6
Elementi di teoria dei test Teorema di Howden Non si può costruire meccanicamente (mediante un programma) un test finito che soddisfi un criterio affidabile e valido 7
Il processo di defect testing 8
Approcci al defect testing 9
Black-box testing n Approccio al testing in cui il sistema è visto come una “scatola nera” n I casi di test sono basati sulla specifica del sistema n La pianificazione può iniziare molto presto nel processo software 10
Black-box testing 11
Equivalence partitioning 12
Equivalence partitioning n Partiziona gli input e gli output del sistema in “insiemi equivalenti” n Se l’input è un intero di 5 digits tra 10, 000 e 99, 999, le classi di equivalenza sono: n n n < 10. 000 da 10. 000 a 99. 999 (compresi) >= 100. 000 n Scegli i casi di test ai confini di questi insiemi n 0, 9. 999, 10000, 99. 999, 100. 000, 150. 000 13
Partizioni 14
Specifica di una routine di ricerca procedure Search (Key : ELEM ; T: ELEM_ARRAY; Found : in out BOOLEAN; L: in out ELEM_INDEX) ; Pre-condition -- the array has at least one element T’FIRST <= T’LAST Post-condition -- the element is found and is referenced by L ( Found and T (L) = Key) or -- the element is not in the array ( not Found and not (exists i, T’FIRST >= i <= T’LAST, T (i) = Key )) 15
Partizioni di input n Input che soddisfano le precondizioni n Input dove una precondizione non vale n Input dove l’elemento chiave è un membro dell’array n Input dove l’elemento chiave non è un membro dell’array 16
Linee guida sul testing (arrays) n Testare il programma con array che hanno solo un singolo elemento n Usa array di dimensioni diverse nei diversi test n Costruisci i test in modo che gli elementi primo, mediano e ultimo dell’array vengano visitati n Testare il programma con array di lunghezza zero (se consentito dal linguaggio di programmazione) 17
Routine di ricerca: partizioni di input 18
Routine di ricerca: casi di test Input array (T) 17 17 17, 29, 21, 23 41, 18, 9, 31, 30, 16, 45 17, 18, 21, 23, 29, 41, 38 21, 23, 29, 33, 38 Key (Key ) 17 0 17 45 23 25 Output (Found, L ) true, 1 false, ? ? true, 1 true, 7 true, 4 false, ? ? 19
Testing strutturale n Chiamato talvolta white-box testing n I casi di test sono ottenuti a partire dalla struttura del programma. La conoscenza del programma viene utilzzata per identificare altri ulteriori casi di test n Obiettivo: vagliare tutti i comandi del programma (non tutti i cammini di computazione) 20
Criteri White-box n Sono criteri di selezione dei casi di test basati su concetti di “copertura” della struttura interna del programma n Congettura: se un programma è stato poco sollecitato dai dati di test, potenzialmente contiene anomalie n Definito il livello desiderato di “copertura” è possibile valutare quanto progressivamente ci si avvicina all’obiettivo 21
White-box testing 22
Copertura 1. Copertura delle istruzioni n Obiettivo: esercitare almeno una volta ogni istruzione durante il test n Motivazione: se no, ci possono essere computazioni scorrette o computazioni mai osservate 23
Esempio 1 Program statement (input, output); 5 2 var 3 x, y : real; 6 4 begin not(x>0) 5 read(x); 6 read(y); 8 7 if x > 0 then x: =x+10; 8 y: =y/x; 9 write(x); 9 10 write(y); 11 end. S = {(x = 20, y = 30)} soddisfa il criterio 10 read(x) read(y) x>0 x: =x+10 7 y: =y/x write(x) write(y) 24
Copertura 2. Copertura delle decisioni n Ogni arco del flusso di controllo deve venire percorso S = {(x = 20, y = 30), (x = -3, y = 100} soddisfa il criterio Ma continua a non scoprire il malfunzionamento! 25
Arricchimento del criterio n Utilizzare valori “ai limiti” dei campi di variabilità delle decisioni, oltre a valori “all’interno” n Esempio se deve essere x >= 0, provare con x = 0, oltre che con x > 0 n Attitudine n “fare l’avvocato del diavolo” 26
Esempio 1 2 3 4 5 6 7 8 read (x, y); if x = 10 then x : = x - 10 else x : = |x| +1; if y <= 0 then y : = (y+1)/x else y : = x/y; . . . T = {(10, 5), (0, -3)} copre tutte le decisioni Così facendo si coprono i cammini “then. . . else” e “else. . . then”, non il cammino “then. . . then” che genera un malfunzionamento. 27
Copertura 3. Copertura dei cammini n Test strutturale esaustivo: tutti i cammini… ma il numero di cammini è infinito! n Occorre limitare il numero: quali? n Criteri empirici per limitare il numero delle iterazioni n Il numero dei dati di test tende comunque a crescere in maniera non controllabile. . . 28
Ricerca binaria (Ada) 29
Ricerca binaria: partizioni di input n Chiave nell’array n Chiave non nell’array n Array di input con un solo elemento n Array di input con numero pari di elementi n Array di input con numero dispari di elementi 30
Ricerca binaria: partizioni di input 31
Ricerca binaria: casi di test 32
Grafi di flusso del programma n Descrivono il flusso di controllo nel programma usati per calcolare la complessità ciclomatica n Complessità = Numero di archi - Numero di nodi +2 33
Rappresentazione di un grafo di flusso di un programma 34
35
Cammini indipendenti n 1, 2, 3, 4, 12, 13 n 1, 2, 3, 5, 6, 11, 2, 13 n 1, 2, 3, 5, 7, 8, 10, 11, 2, 12, 13 n 1, 2, 3, 5, 7, 9, 10, 11, 2, 3, 4, 12, 13 n Bisogna costruire dei casi di test in modo che tutti questi cammini siano percorsi n Si può utilizzare un analizzatore dinamico per verificare che i cammini siano stati eseguiti 36
Complessità ciclomatica n Il numero di test per controllare tutti i comandi di controllo è uguale alla complessità ciclomatica n La complessità ciclomatica è uguale al numero di condizioni booleane nel programma n E’ utile se usata con attenzione. Non è sempre adeguata come test e non può essere usata per programmi data-driven 37
Controllo e programmi data-driven case A is when “One” => i : = 1 ; when “Two” => i : = 2 ; when “Three” => i : = 3 ; when “Four” => i : = 4 ; when “Five” => i : = 5 ; end case ; Strings: array (1. . 4) of STRING : = (“One”, “Two”, “Three”, “Four”, “Five”); i : = 1 ; loop exit when Strings (i) = A ; i : = i + 1 ; end loop ; 38
Testare le interfacce n Questo tipo di testing va fatto quando vengono integrati moduli o sottosistemi per creare sistemi più grandi n L’obiettivo in questo caso è trovare errori dovuti alle interfacce o ad assunzioni sulle interfacce che non sono valide n È particolarmente importante nello sviluppo object-oriented, in quanto gli oggetti sono definiti a partire dalle loro interfacce 39
Tipi di interfacce n Interfacce realizzate con parametri n I dati sono trasmessi da una procedura all’altra n Interfacce a memoria condivisa n Due o più procedure condividono la stessa memoria n Interfacce procedurali n Sottosistemi incapsulano un insieme di procedure che devono essere chiamate da altri sottosistemi n Interfacce a passaggio di messaggi n I sottosistemi richiedono servizi da altri sottosistemi 40
Testare le interfacce 41
Errori nelle interfacce n Cattivo uso delle interfacce n Una componente chiama un’altra componente e commette un errore nell’uso dell’interfaccia di quest’ultima, ad esempio chiamando i parametri nell’ordine sbagliato n Incomprensione di interfacce n Una componente chiamante fa delle assunzioni sul comportamento della componente chiamata che non sono valide n Errori di temporizzazione n La componente chiamante e la componente 42
Linee guida per testare interfacce n Progetta i test in modo che i parametri attuali n n delle procedure siano agli estremi del loro rango Testa sempre parametri di tipo riferimento con valore NIL Progetta test che causano il fallimento della componente Usa uno stress testing nel sistema di scambio di messaggi Nei sistemi a memoria condivisa, cambia l’ordine in cui le componenti sono attivate 43
- Slides: 43