1 / 59

Il Testing

Il Testing. A. Fantechi Area di Ricerca di Trieste 19-20/4/2001. Attivita` di Verifica sul codice. Verifica che il codice soddisfi le sue specifiche

gyala
Download Presentation

Il Testing

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Il Testing A. Fantechi Area di Ricerca di Trieste 19-20/4/2001

  2. Attivita` di Verifica sul codice • Verifica che il codice soddisfi le sue specifiche • Testing = Attivita` mirante alla scoperta di eventuali malfunzionamenti del prodotto software dovuti a “guasti” (anomalie – difetti – faults – bugs - bachi) tramite l’esecuzione del codice stesso, fornendogli opportuni dati in ingresso (analisi dinamica) • Debugging: attivita` di localizzazione e rimozione dei guasti.

  3. Teoria del testing Programma P P: D --> R ok(P,d) sse P sul dato di ingresso d X D da` il risultato aspettato ok(P) sse per ogni d X D ok(P,d) (P è corretto) Test T = sottoinsieme di D. (test suite) t dato di test se tX T P è corretto per un test T sse   per ogni tX T ok(P,t)

  4. Scopo dell'attività di testing è la rilevazione di malfunzionamenti, quindi: un test T ha successo per un programma T se rileva uno o più malfunzionamenti in P, successo(T,P) = not ok(P,T) un test che non rileva malfunzionamenti manifesta non la correttezza del programma, ma la sua inadeguatezza * un test T per P e' detto ideale se l'insuccesso di T implica la correttezza di P OK(P,T) => ok(P)

  5. * Dipende da quale si considera sia lo scopo dell’attivita` di testing: questa definizione va bene se vediamo il testing come attivita` rivolta alla caccia di guasti (bug finding) Il testing puo` essere visto anche come attivita` mirata ad aumentare la confidenza nella bonta` del prodotto  assenza di guasti Testing come attivita` svolta da un “ente” indipendente da quello di sviluppo.

  6. Criteri di selezione di test (per approssimare test ideali) Un criterio di selezione C per un programma P è un insieme di predicati sul domino di ingresso D Un test T è selezionato da C se per ogni t X T esiste cX C tale che c(t) è vero e per ogni c X C esiste t X T tale che c(t) è vero Esempio: C= {(esiste t X T: t<0),(0 X T),(esiste t XT: t>0) } test selezionati da C: {-4,0,5}{-2,9,0,8,-12,6} Criterio di test: C = {( t X D => t X T)} test esaustivo

  7. Un criterio di selezione C è affidabile per P se, per ogni coppia di test T1, T2 selezionati da C, successo(T1,P) <=> successo(T2,P) Un criterio di selezione C è valido per P se, qualora P non sia corretto, esiste almeno un test T selezionato da C: successo(T,P) Teorema di Goodenough e Gerhart affidabile(C,P) and valido(C,P) and selezionato(C,T) and not successo(T,P) => ok(P)

  8. Teorema di Howden: • Non esiste un algoritmo che, dato P qualsiasi, generi un test ideale finito (test definito da un criterio affidabile e valido) • Tesi di Dijkstra • Il test di un programma può rilevare la presenza di malfunzionamenti, ma non dimostrarne l'assenza • Teorema di Weyuker • Dato P qualsiasi, i seguenti problemi sono indecidbili: • esiste almeno un dato di ingresso che causa l'esecuzione di un particolare comando? • esiste un particolare dato di ingresso che causa l'esecuzione di una particolare condizione (branch)? • è possibile trovare almeno un dato di ingresso che causa l'esecuzione di ogni comando di P? • è possibile trovare almeno un dato di ingresso che causa l'esecuzione di ogni condizione (branch) di P? • è possibile trovare almeno un dato di ingresso che causa l'esecuzione di ogni cammino di P?

  9. LIVELLI DI TEST • test di unità - mirato alla correttezza degli algoritmi. • test di integrazione - mirato alla correttezza delle interfacce. • test di sistema - affidabilità, sicurezza e prestazioni. • test di accettazione - imposto dal cliente, verifica che il programma fa quello che voleva. • test di regressione - verifica che non si siano introdotti errori in versioni successive

  10. Test di Unità • Test funzionale (black box) • Test strutturale (white box) • Test statistico Variano per il principio su cui si basa il criterio di selezione dei test.

  11. Test funzionale (black box) Il criterio di selezione si basa sulle specifiche funzionali dell’unita sotto test, ad esempio attraverso: EQUIVALENCE PARTITIONING Si divide il dominio di input del programma in classi con l'ipotesi che un caso di test per ciascuna classe sia rappresentativo di tutti i valori della classe. Per ciascuna condizione di input si associano almeno due classi di equivalenza, una valida ed una invalida. BOUNDARY VALUE ANALYSIS Si scelgono i casi di test in prossimità della frontiera delle classi.

  12. Es. Supponiamo di avere una unita che si puo` comportare differentemente per valori negativi o positivi dei dati in ingresso, ma il valore effettivo non e` particolarmente interessante. Un criterio di test basato sul partizionamento puo’ essere: C= {(esiste t X T: t<0)(esiste t XT: t>=0) } Cioe` si testa l’unita` con almeno un valore negativo e uno positivo. Se vogliamo prestare attenzione ai valori di forntiera (boundary analysis), possiamo includere lo zero: C= {(esiste t X T: t<0),(0 X T),(esiste t XT: t>0) }

  13. Altre tecniche… CAUSE-EFFECT GRAPHING Si disegna un grafo dove gli archi rappresentano operatori logici  le specifiche vanno ridotte a condizioni booleane, rappresentanti fatti di ingresso o uscita (“stanza doppia”, “alta stagione”, …). Ogni condizione booleana in ingresso (uscita) identifica un sottoinsieme dei dati in ingresso (in uscita). ERROR GUESSING Tecnica ad-hoc basata sull' intuito e sull' esperienza di chi esegue il test.

  14. Testing basato sulla specifica ·specificaformale Possono essere identificate piu` facilmente le partizioni e i boundary cases. • puo` essere automatizzato Es. Generazione di Test case da Finite state automata (UML state diagrams)

  15. Test strutturale (white box) Il criterio di selezione dei test si deriva dalla struttura stessa del programma  (in particolare, dal grafo di flusso) Si selezionano quei test che esercitano tutte le strutture del programma Occorre decidere quali sono le strutture di riferimento:  vari tipi di testing a seconda della struttura scelta Occore una misura che ci permette di decidere se sono state esercitate tutte le strutture  misura di copertura (coverage)

  16. Statement testing • I test sono selezionati in base alla loro capacita` di coprire i comandi (nodi del grafo di flusso) • Coverage = numero comandi eseguiti / numero totale comandi Un test e` selezionato se garantisce una copertura dei comandi uguale a 1 In questo modo si garantisce che I comandi sono tutti eseguiti almeno una volta. Non si garantisce di aver percorso tutte le “strade” (rami) almeno una volta: if (c) { comando1 } comando2 Un test che rende la condizione c vera esegue tutti i comandi, ma non tutti i rami

  17. Branch testing • Si richiede che in questo caso vengano percorsi dai test tutti i rami del programma almeno una volta. (ogni arco del grafo di flusso deve appartenere almeno ad un cammino di esecuzione esercitato dal test). • Coverage = numero rami percorsi / numero totale rami Un test e` selezionato se garantisce una copertura dei rami uguale a 1 La copertura dei rami implica la copertura dei cammini

  18. Condition testing if (x>1 && y==0) {comando1} else {comando2} In questo caso sia la copertura dei comandi che quella dei rami non garantiscono che si siano testate tutte le combinazioni delle due condizioni in and. Ad esempio, un test potrebbe esercitare solamente le situazioni: {x = 2, y =0} e { x=2, y=1}, garantendo la piena coperura dei rami e quindi dei comandi Cfr. con programma equivalente: if (x>1) if (y==0) {comando1} else {comando2} else {comando2} In cui lo stesso test da` una copertura rami e comandi del 60%

  19. Basic condition coverage = numero totale dei valori di verita` assunti da tutte le condizioni basiche numero totale dei valori di verita` delle condizioni basiche dove per numero totale dei valori di verita` delle condizioni basiche si intende 2 volte il numero delle condizioni basiche, considerando cioe` ogni condizione valutata sia a true che a false, ma senza considerare tute le possibili combinazioni dei due valori di verita` su tutte le condizioni basiche. Nel caso precedente, I due casi di test {x = 0, y =0} e { x=2, y=1}, peremettono di avere una copertura del 100% delle condizioni basiche. Come e` evidente in questo caso, la piena copertura delle condizioni basiche non garantisce la copertura dei rami.

  20. D’altra parte, se si considerano tutte le possibili combinazioni dei valori di verita` di tutte le condizioni basiche (compound condition coverage), le possibilita` da coprire sono in numero di 2 elevato al numero di condizioni basiche, e quindi diventano un numero eccessivo per condizioni appena complesse. • Vengono percio` utilizzati altri criteri, che considerano non solo i valori di verita` delle condizioni basiche, ma anche la decisione finale • MCDC Modified Condition / Decision Coverage MCDC implica copertura dei rami • esempio

  21. if (pos < parseArray.length && (parseArray[pos] == ‘{‘ || parseArray[pos] == ‘}‘ || parseArray[pos] == ‘|‘)) {continue;}

  22. room open if (pos < parseArray.length && (parseArray[pos] == ‘{‘ || parseArray[pos] == ‘}‘ || parseArray[pos] == ‘|‘)) {continue;} close bar

  23. Path testing • I criteri di copertura finora visti non sempre consentono di rilevare quei guasti che vengono attivati solo da particolari cammini di esecuzione nel programma. • Copertura dei cammini: Cpath = numero dei cammini eseguiti / numero totale dei cammini

  24. Sono sufficienti i due casi di test T1 e T4 per ottenere una copertura del 100% dei rami. Alternativamente, sono sufficienti i due casi di test T2 e T3. • Per una copertura del 100% dei cammini sarebbero necessari tutti i casi di test T1, T2, T3, T4. • Il caso precedente è il solo caso, in assenza di cicli, in cui la copertura dei cammini e la copertura dei rami differiscono; nel caso in cui ho due if then else annidati, infatti, sia i rami che i cammini sono 3. • Si noti che il numero dei cammini e’ esponenziale con il numero degli if.

  25. Il numero dei cammini e` pero`in generale illimitato, per la presenza di cicli. • Per questo motivo la path coverage non viene spesso nemmeno presa in considerazione in quanto tale. Semmai, quando si parla di copertura di cammini in presenza di cicli si pone in genere un limite superiore al numero di iterazioni che vengono svolte. Seguendo la terminologia introdotta da Miller, si parla di copertura Ct k, dove k è il numero di possibili diverse iterazioni che si vogliono considerare. Ad esempio, k=2 significa che si vuole eseguire il ciclo con 0, 1, 2 iterazioni. • Un modo comune di considerare la copertura dei cammini è quello di utilizzare k=1. Se si adotta quindi la copertura Ct(k=1) per ogni ciclo si considererà sia il cammino che non esegue affatto le azioni interne al ciclo sia quello che le segue (almeno) una volta. In questo modo si ottiene comunque la copertura dei rami. Anche qui occorre fare attenzione che si parla di "almeno" perchè non sempre sarà possibile individuare facilmente il caso di test che fa eseguire esattamente una volta le azioni del ciclo; inoltre, il caso del for con numero di iterazioni fissato staticamente sarà sempre eseguito esattamente quel numero di volte. • Si parla anche di criterio di N-copertura: copertura legata al numero di iterazioni del loop.

  26. Cyclomatic testing • Si noti comunque che il numero dei cammini, anche limitando il numero delle iterazioni, rimane esponenziale con il numero if indipendenti tra loro. • Sono stati definiti vari criteri di copertura basati sui cammini, tra cui il testing ciclomatico, che si basa sul numero di Mc Cabe: si conta il numero di cammini linearmente indipendenti testati, e si considera soddisfatto il criterio quando il numero dei cammini testati raggiunge il numero ciclomatico della unita` sotto test.

  27. Copertura (coverage) • Il concetto di copertura può essere utilizzato come metrica per valutare l'effettività dei test effettuati: ad esempio, i casi di test T1 e T4 forniscono il 100% di copertura dei rami e il 50% di copertura dei cammini. • Un criterio quantitativo di copertura viene spesso utilizzato come soglia, (es. 90% dei cammini) raggiunta la quale l'attività di testing viene considerata troppo costosa e viene quindi interrotta. • Si puo` usare una misura di copertura strutturale per valutare l’efficacia di una fase preliminare di testing funzionale e per capire se questa ha lasciato scoperte (non esercitandole) alcune strutture del programma

  28. Unfeasible paths • Ritornando all'esempio di cui sopra, si noti però che potrebbe accadere che le condizioni C1 e C2 siano dipendenti tra loro: si consideri ad esempio il caso più banale, in cui C1=C2. In questo caso si potranno al massimo esercitare due cammini, S1-S3 e S2-S4. Non si potrà cioè ottenere la copertura del 100% dei cammini, ma solo il 50 %. Questo se si considerano i cammini sul grafo, ma i cammini possibili del programma (feasible paths o achievable paths) sono coperti al 100%. • La possibile presenza di cammini unfeasible (o Infeasible) rende quindi più difficoltosa la misurazione della copertura di cammini; tale presenza in generale non può essere rilevata da un'analisi statica, ed anche la completa rilevazione dei cammini unfeasible attraverso un'analisi dinamica è stata dimostrata essere teoricamente impossibile

  29. Unfeasible paths • In alcuni casi, la presenza di cammini Unfeasible e` voluta: Defensive Programming: si testano condizioni normalmente vere, che possono risultare false solo in presenza di guasti hardware/software: nel caso risultino false si effettuano percio`opportune azioni di trattamento del guasto. • In altri casi, la presenza di cammini Unfeasible e` indice di disattenzione nella stesura (o nel riutilizzo)del codice. • A fronte di percentuali di copertura minori del 100%, si dovra` giustificarne il motivo (normative DO-178B): si potra` cosi` duistinguere i casi di Defensive Programming da quelli di codice non sufficientemente curato.

  30. Data flow testing • Nella più recente produzione scientifica sul testing, non si tenta di ottenere la copertura dei cammini, ma semmai qualcosa di intermedio tra la copertura dei rami e quella dei cammini. Viene infatti definita una "data-flow" coverage, in cui i casi di test sono selezionati sulla base dell'utilizzo dei dati: ad esempio un cammino dove la stessa variabile viene prima scritta e poi letta: si considerano solo i cammini da assegnamenti a variabili a usi successivi della variabili: i cammini analizzati hanno dunque una rilevanza diretta sul modo con cui i programmi trattano i dati.

  31. Ordinamento dei criteri di copertura Path testing Compound cond. testing N-Path testing Cyclomatic t. MCDC testing Branch testing Basic cond. testing Statement testing

  32. Ordinamento dei criteri di copertura TEORICI Path testing Compound cond. testing N-Path testing Cyclomatic t. MCDC testing Branch testing Basic cond. testing Statement testing

  33. Funzionale vs. strutturale Il testing funzionale e quello strutturale sono complementari: • Una specifica di una tabella lascia all’implementatore la scelta della struttura dati da utilizzare. Se la scelta e` per una tabella hash, vi saranno diverse porzioni di codice eseguite a seconda che vi siano o meno collisioni. Test derivati dalla specifica non possono garantire di coprire sia il caso di collisione che quello di non collisione, mentre il piu’ semplice criterio di copertura strutturale lo garantisce. • Viceversa, il caso dei missing paths. Questi guasti derivano dal non aver considerato alcuni aspetti dalla specifca, e possono essere rivelati solo da un testing basato sulla specifica, e non da un testing strutturale.

  34. Test statistico Mentre nei test funzionale e strutturale i dati di test sono forniti da un criterio deterministico, nel test statistico sono casuali. In realtà posso usarlo in combinazione con i precedenti ed ottenere 4 tipi di test: funzionale deterministico, funzionale statistico, * strutturale deterministico, strutturale statistico. * (* il criterio di selezione dei test e` deterministico e definisce degli intervalli; i dati di test possono essere scelti casualmente in tali intervalli)

  35. Il test di una unita` richiede la costruzione di: • Stub Modulo fittizio che presenta la stessa interfaccia di un modulo invocato dall’unita` sotto test. • Drivers Modulo che ha la funzione di invocare l’ unita` sotto test passandole I casi di test individuati • Oracolo Puo’ essere un programma, ma anche l’utente umano, e rappresenta l’entita` che decide se il test e’ passato ofallito. • Automazione del testing:strumenti di supporto alle attivita’ di costruzione di Drivers, Stubs, e Oracoli  Cantata, Adatest, Logiscope,…..

  36. Test di integrazione • In seguito al test dei singoli moduli, si esegue il test di integrazione per verificare la correttezza del programma complessivo, e l’assenza di anomalie sulle interfacce tra i moduli. Per questo si seguono due metodi: approccio non incrementale approccio incrementale L’approccio non incrementale prevede di assemblare tutti i moduli e realizzare immediatamente l’analisi globale del sistema. È detto anchebig bang test. Suppone di aver completato il test di unita` per ogni modulo.

  37. Test di integrazione • Nell’approccio incrementale si parte testando dei singoli moduli, collegandoli poi con i moduli chiamanti o chiamati, e testando il sottosistema ottenuto, e cosi’ via fino a costituire il sistema complessivo. • Non richiede di aver svolto il test di unita` di tutti i moduli • Esercita piu’ a lungo ogni singolo modulo • Permette di localizzare piu` facilmente le anomalie di interfaccia tra moduli.

  38. Test di integrazione- STRATEGIE DI TEST TopDown Bottom Up Risultati veloci inizia a sistema ultimato stub complessi (emulatori, tabelle) driver semplici output artificiale per simulare parallelismo i moduli sottostanti

  39. Test di integrazione- Criteri di copertura Criteri di copertura sono stati definiti anche per l’attivita` di test di integrazione. In particolare, il criterio di copertura delle chiamate di procedura ci dice se il testing di integrazione ha esercitato tutte le procedure. Con una granularita` piu` fine, il criterio di copertura dei punti di ingresso e dei punti di uscita dalle procedure consente di sapere se sono stati esercitati tutti i punti di ingresso e i punti di ritorno da una procedura o funzione.

  40. Test di sistema • Con il test di integrazione si è già realizzato il test delle funzionalità dell’intero sistema, ora si vogliono analizzare alcune proprietà globali che non hanno senso se viste nell’ambito del singolo modulo. Esempi: • -Test di stress ( overload ) : si vuole verificare non solo che il programma funzioni secondo le specifiche, ma anche che si comporti in modo corretto in condizioni di carico di lavoro eccezionale. Per esempio: un sistema per basi di dati normalmente viene interrogato in modo tale da produrre venti transazioni per unità di tempo. È progettato per sopportare fino a trenta transazioni. • -Test di sicurezza : il sistema può essere usato in condizioni non corrette, ad esempio si sottopone a delle violazioni, anche di tipo accidentale. • -Test di robustezza : si forniscono al sistema dei dati sbagliati, e si osserva il comportamento del sistema rispetto a tali dati. (esempio tipico: si digitano sequenze casuali di tasti sulla tastiera per controllare se l’interfaccia utente di un programma si “pianta”)

  41. Test di sistema • In alcuni casi, si usano strumenti specifici per il test di sistema; ad esempio quando il codice software viene caricato su un microprocessore dedicato a qualche funzione di controllo (sistema embedded), si ricorre all’uso di strumenti di simulazione dell’ambiente esterno al processore, o all’uso di emulatori su macchina host della macchina target su cui verra’ caricato il software, o ai cosiddetti In-circuit emulator, che permettono alla macchina host di emulare il comportamento di un microprocessore target, ricevendone - tramite un apposito connettore che si sostituisce al processore sulla scheda del sistema target - direttamente gli input reali, e producendo valori in uscita direttamente al sistema.

  42. Test di accettazione Nel test di sistema il software viene confrontato con la specifica dei requisiti (verifica). Questo test e` normalmente responsabilita` dello sviluppatore. Nel Test di accettazione il software viene confrontato con i requisiti dell’utente finale (validazione) Questo test e` normalmente svolto dal cliente. Una caratteristica del test di accettazione e` che viene usualmente svolto senza avere a disposizione il codice sorgente Per prodotti di largo consumo si utilizzano i concetto di -test e -test.

  43. Test di accettazione • -test: il software viene già usato all’interno della casa produttrice per verificarne le funzionalità, però ancora non è stato rilasciato all’esterno • -test: il software viene rilasciato a un numero selezionato di utenti che lo usano sapendo che non è una versione stabile, e che possono interagire con chi ha prodotto il software.

  44. Test di regressione • Testing di una nuova release: come si puo’ minimizzare lo sforzo usando risultatidel testing di versioni precedenti? Mantenere i drivers, gli stubs, gli oracoli e memorizzare i test cases della vecchia versione Nel corso del testing della nuova versione: Tenere traccia dei cambiamenti Valutare l’impatto dei cambiamenti  Strumenti di supporto al testing di regressione

  45. Problema dell’incrementalita` dei test: • Sarebbe auspicabile che il costo di ritestare un programma dopo una piccola modifica sia marginale, e non paragonabile al primo testing del programma • I criteri di copertura strutturale non sono incrementali: le percentuali di copertura possono venir sconvolte da una piccola modifica.

  46. Analisi mutazionale • Dopo aver esercitato P su T, si verifica P corretto rispetto a T. Si vuole fare una verifica più profonda sulla correttezza di P: introduco degli errori ( piccoli ) su P e chiamo il programma modificato P’. Questo P’ viene detto mutante. Si eseguono su P’ gli stessi test di T. Il test dovrebbe rilevare gli errori. Se il test non rileva questi errori, allora significa che il test non era valido. Questo è un metodo per valutare la capacità di un test, e vedere se è il caso di introdurre test più sofisticati.  Fault based testing  Software Fault injection

  47. Object-Oriented Testing Caratteristiche principali del paradigma object oriented: • Gli oggetti hanno uno stato, accessibile solo attraverso le loro interfacce • Ereditarieta`: nuove classi possono essere derivateper specializzazione di classi esistenti • Polimorfismoe dynamic binding: le invocazionidei metodi possono essere legate dinamicamente a codice diverso • Genericita`

  48. Problemi per il testing • Information hiding Gli oggetti, avendo uno stato, violanole ipotesi di un comportamento funzionale • Shadow invocations I metodipossono essere invocati implicitamente(problemi relativi al conteggio delle percentuali di copertura) • Polimorfismoe dynamic binding: I metodiinvocati non possono essere identificati staticamente • Ereditarieta`: I metodi sono riutilizzati in classi diverse • Genericita`: Le classi generichedevono essere instanziate per essere testate

  49. Object Oriented : ereditarieta` ProgrammazioneProcedurale: Il codice e` strutturato in subroutines e moduli I moduli sono composti in modo bottom-up o top-down Quando una subroutine e` stata testata, non lo deve essere piu` ProgrammazioneObject oriented: Il codice e` strutturato in classi. L’ ereditarieta`e` la relazione fondamentale tra classi L’ ereditarieta`favorisce il riuso e lo sviluppo incrementale: alcune operazioninon sono modificate nelle sotto-classi, altre sono ridefinite o cancellate Problemi: Come fare testincrementale? Quali operazioni ereditate devono essere ri-testate?

More Related