Software Engineering a.y. 2016-2017 Convalida e verifica del software (parte 1) Prof. Luca Mainetti Università del Salento Obiettivi della lezione ■ Fare alcune riflessioni sul processo di sviluppo del software che ci portano ad introdurre l’argomento della convalida e verifica ■ Passare in rassegna alcune tecniche di convalida e verifica del software che permettono di provare il livello di qualità raggiunto dal prodotto – Un prodotto software deve essere collaudato, anche se il processo di sviluppo contiene tecniche sistematiche di codifica – Obiettivo del collaudo è la prova della rispondenza del prodotto ai requisiti – Già durante l’attività di specifica dei requisiti è bene anticipare i casi di test che compongono il collaudo – Le prove di convalida e verifica devono essere consegnate al committente assieme al prodotto – Dovete sottoporre il risultato dei vostri progetti ad una o più tecniche di convalida e verifica che qui analizziamo Convalida e verifica del software (parte 1) 2 Luca Mainetti Processo di sviluppo del software ■ Uno degli obiettivi primari dell’ingegneria del software è di provare che il processo di produzione del software può essere schematizzato come un’attività di derivazione formale dell'implementazione a partire dalle specifiche – la codifica è un mapping dal design al codice – il design è un mapping dai requisiti al progetto ■ Ancora non siamo giunti ad un approccio generale in questi termini, ma il alcune aree applicative, dove l’affidabilità del sistema software finale sia critica, l’approccio fa ben sperare – sistemi di controllo – sistemi che possono essere caratterizzati da un punto di vista operazionale Convalida e verifica del software (parte 1) 3 Luca Mainetti Processo di sviluppo del software (cont.) ■ Linguaggi formali di specifica – definizione di un’applicazione per livelli di astrazione successivi – dimostrazione formale della consistenza del passaggio tra un livello e quello successivo – il livello finale coincide con il linguaggio di programmazione scelto – perché si possa procedere, i requisiti iniziali devono essere tradotti in termini matematici: modello formale • il fatto che il modello formale esprima esattamente i requisiti iniziali è l’unica prova informale dell’approccio – in uno o più passi successivi si prova con tecniche logico/matematiche che dal modello formale si possa derivare una specifica formale di più basso livello, fino a giungere al codice finale • la prova può essere automatica oppure può richiedere l’intervento di un umano Convalida e verifica del software (parte 1) 4 Luca Mainetti Processo di sviluppo del software (cont.) ■ Il meccanismo di prova consiste di due parti – prova che il sistema specificato in modo operazionale soddisfa particolari condizioni invarianti che rappresentano i vincoli ed i requisiti critici del sistema – prova di consistenza tra un livello di specifica e quello successivo ■ Specifiche algebriche – è un insieme di notazioni e di metodi che permettono una descrizione ed implementazione formale e rigorosa dei tipi di dati astratti, che sono alla base del principio di information hiding – con una notazione algebrica è possibile definire le principali strutture dati – l’implementazione può essere descritta sempre in termini algebrici e dimostrata a partire dalla specifica del tipo di dato implementato Convalida e verifica del software (parte 1) 5 Luca Mainetti Processo di sviluppo del software (cont.) ■ Nel presente corso di Software Engineering non approfondiremo i metodi formali né le specifiche algebriche ■ Non perché non siano importanti, ma perché sono certamente più diffusi i metodi di specifica semi-formali e le tecniche di codifica che non fanno uso di derivazione matematica tra livelli di astrazione successivi ■ La sperimentazione durante lo svolgimento del progetto vi permetterà di provare ad utilizzare comunque un procedimento sistematico ■ Il ricorso a pattern di design e di codifica vi aiuterà ad utilizzare (e riusare) tecniche consolidate Convalida e verifica del software (parte 1) 6 Luca Mainetti Processo di sviluppo del software (cont.) ■ Implementazione fortemente basata sul design (“up-front design”) – benché all’interno di un ciclo iterativo, la fase di design cerca di anticipare e vincolare tutte le caratteristiche del prodotto software – si pone monta enfasi (ed effort) sulla definizione di interfacce di moduli e sull’uso preventivo di pattern per il riuso ■ Implementazione basata su tecniche di XP - Extreme Programming (“continuous design”) – il design è molto semplice e leggero – si procede ad un’implementazione molto anticipata ed il design riflette le caratteristiche dell’implementazione – i pattern vengono utilizzati come strumenti di supporto all’implementazione, meno come strumenti per il riuso ed evoluzione Convalida e verifica del software (parte 1) 7 Luca Mainetti Processo di sviluppo del software (cont.) ■ La crescente disponibilità di strumenti di “continuous integration”, refactoring, testing pone una reale problema di capire quale sia l’approccio più conveniente tra up-front design e continuous design – strumenti come ANT (Another Neat Tool, http://ant.apache.org) permettono di creare build di sistema in modo continuo – strumenti come JUnit, DBUnit, HttpUnit, ServletUnit permettono di automatizzare test di verifica del software – la valutazione di una versione concreta di un’applicazione software diviene sempre più un’attività supportata, automatizzabile, semplice, rapida ■ Probabilmente la via di mezzo tra up-front design e continuous design è quella più adatta alla maggior parte dei casi applicativi Convalida e verifica del software (parte 1) 8 Luca Mainetti Convalida e verifica ■ Le attività di convalida e verifica devono essere effettuate durante il ciclo di sviluppo del software (devono essere iterate), non solamente prima della fase di rilascio ■ Le attività di convalida e verifica si avvalgono di varie tecniche, ognuna delle quali ha delle precise specificità e meglio si adatta alla prova di fattori di qualità ■ Il punto di partenza è sempre e comunque una chiara definizione e specifica delle proprietà (qualità) che il prodotto software deve avere – la correttezza funzionale è una di queste proprietà, non la sola, né, a volte, la più importante – non sono molte le tecniche di verifica totalmente generali (come, ad esempio, la valutazione delle prestazioni) Convalida e verifica del software (parte 1) 9 Luca Mainetti Convalida e verifica (cont.) ■ I risultati della verifica possono non essere binari (OK, KO) – alcuni difetti possono essere tollerati – il concetto di correttezza è relativo, è meglio esprimere una certo livello o “misura” di correttezza • ad esempio, l’efficienza può essere misurata in modo relativo con una formula del tipo: “il tempo richiesto per eseguire una computazione è dato dalla funzione f(n) della lunghezza n dei dati di ingresso” ■ La verifica può essere oggettiva o soggettiva – oggettiva, alcuni esempi: verifica dei risultati a partire da dati di ingresso, misura delle prestazioni – soggettiva, alcuni esempi: verifica della manutenibilità, test di usabilità ■ Anche le qualità implicite (robustezza, manutenibilità, efficienza) devono essere verificate sebbene spesso non siano espresse nei requisiti Convalida e verifica del software (parte 1) 10 Luca Mainetti Convalida e verifica (cont.) ■ Approcci alla verifica – effettuare esperimenti con il prodotto funzionante (tecniche dinamiche) – analizzare il prodotto in modo da dedurre (dal suo codice, dalla sua documentazione) delle proprietà (tecniche statiche) ■ Procedimento di testing – si verifica il comportamento definendo in insieme di “casi di test” – è impossibile dedurre la correttezza del software da un insieme finito di casi di test – per quanti casi di test si possano prevedere ed eseguire, il software può comunque rimanere non corretto per qualche caso d’uso Convalida e verifica del software (parte 1) 11 Luca Mainetti Convalida e verifica (cont.) ■ Se si confronta il comportamento del software con i requisiti informali estratti dal committente, le tecniche di convalida e verifica utilizzabili sono necessariamente vaghe ■ Invece, se si confronta il comportamento del software con una specifica semi-formale (o formale) dei requisiti, le tecniche possono essere sistematiche e supportate da strumenti automatici ■ Esistono due momenti distinti – convalida: confronto del comportamento del software con i requisiti estratti dal committente – verifica: confronto del comportamento del software con la specifica dei requisiti stessi prodotta da un analista Convalida e verifica del software (parte 1) 12 Luca Mainetti Convalida e verifica (cont.) ■ Convalida e verifica sono quindi attività complementari – la verifica potrebbe provare che il software è corretto rispetto alla specifica dei requisiti, ma la specifica dei requisiti potrebbe non rappresentare correttamente i “desiderata” del committente – al contrario, la sola convalida potrebbe non renderci sufficientemente confidenti in un livello di correttezza accettabile del software ■ Definizioni – malfunzionamento (guasto, failure): comportamento errato di un programma (non è legato alla struttura logica del programma) – anomalia (difetto, fault, bug): è la causa di un malfunzionamento (riguarda la struttura statica del programma, il codice) • un programma potrebbe contenere anomalie senza manifestare malfunzionamenti • un malfunzionamento può essere dovuto a più anomalie Convalida e verifica del software (parte 1) 13 Luca Mainetti Convalida e verifica (cont.) ■ Esempio – se un programma che vuole calcolare il doppio di un numero contiene la linea di codice y=x * x, contiene evidentemente un’anomalia, che però non si manifesta come malfunzionamento se il programma viene provato con x = 2 ■ Definizioni – errore: è la causa di un’anomalia, dovuta frequentemente ad un errore umano piuttosto che ad un errore di uno strumento di produzione ■ Varie tecniche di prova della correttezza del software – prova formale: prova dell’assenza di anomalie – test: rilevamento di eventuali malfunzionamenti – debugging: localizzazione delle anomalie in base ai malfunzionam. – analisi statica: prove basate sull’esame del codice sorgente – analisi dinamica: prove basate sull’esecuzione del programma Convalida e verifica del software (parte 1) 14 Luca Mainetti Convalida e verifica (cont.) ■ Alcune tecniche di convalida e verifica fanno uso del “grafo di controllo di un programma sequenziale”: si tratta di una rappresentazione grafica delle strutture di controllo del codice ■ Il grafo di controllo può essere visualizzato a vari livelli di dettaglio “espandendo” o “contraendo” blocchi di codice n1 n1 S1 S1 S2 S S2 n2 if cond S1 else S2 Convalida e verifica del software (parte 1) n2 while cond do S 15 S1; S2 Luca Mainetti Convalida e verifica (cont.) begin read(x, y); a = x; b = y; while a != b do begin if a > b a = a - b; else b = b - a; end; …... end read(x, y); a = x; b = y; a != b a>b a=a-b; …… b=b-a; end; Esempio di grafo di controllo Convalida e verifica del software (parte 1) 16 Luca Mainetti Analisi statica ■ Viene analizzato il codice sorgente dell’applicativo software ■ Non è quindi richiesta l’esecuzione del programma ■ L’analisi statica si basa sull’esame su un insieme finito di elementi, che sono le istruzioni del codice sorgente ■ L’analisi dinamica si basa invece sull’esame dell’insieme delle esecuzioni, che benché finito, non è limitabile a priori ■ Per l’analisi statica non vi è quindi il problema di limitare il numero di casi da prendere in esame ■ Però proprio la finitezza dei casi implica un numero inferiori di anomalie che possono essere rilevate – ad esempio, non possono essere rilevate anomalie alla base di malfunzionamenti che dipendono dal valore assunto da variabili Convalida e verifica del software (parte 1) 17 Luca Mainetti Analisi statica in compilazione ■ L’analisi statica permette quindi di rilevare un numero minore di anomalie rispetto a quella dinamica, ma è meno costosa ed è più direttamente automatizzabile ■ I compilatori effettuano un’analisi statica del codice sorgente – analisi lessicale: errori nella formazioni delle parole chiave e dei nomi definiti dall’utente – analisi sintattica: errori nelle relazioni tra gli elementi ottenuti dall’analisi lessicale – controllo dei tipi: violazione delle regole del “type system” del linguaggio di programmazione ■ Molti compilatori effettuano anche l’analisi di flusso dati Convalida e verifica del software (parte 1) 18 Luca Mainetti Analisi di flusso dati ■ E’ un’analisi dell’evoluzione del valore delle variabili durante l’esecuzione di un programma ■ Tale valutazione è intrinsecamente dinamica, ma possibili anomalie possono essere rilevate anche con tecniche statiche ■ Sappiamo che durante l’uso di variabili possiamo distinguere tre momenti principali – definizione (d) • x = y + 1; //il valore della variabile x viene definito – uso (u) • x = y + 1; //il valore della variabile y viene usato – annullamento (a) • return( k ); //dopo l’istruzione, il valore della variabile k è annullato Convalida e verifica del software (parte 1) 19 Luca Mainetti Analisi di flusso dati (cont.) ■ Ad ogni comando è quindi associabile in maniera statica il tipo di operazione effettuata sulle variabili ■ In altre parole, sequenze di comandi, che corrispondono a possibili esecuzioni, possono essere mappate su sequenze di definizioni (d), usi (u) e annullamenti (a) ■ Sequenza di operazioni su x void swap(int x1, int x2) { int x; – auu ■ Sequenza di operazioni su x1 – dud x2 = x; x2 = x1; x1 = x; ■ Sequenza di operazioni su x2 – ddd } Convalida e verifica del software (parte 1) 20 Luca Mainetti Analisi di flusso dati (cont.) ■ Analizzando poi le sequenze di operazioni ottenute per ogni variabile, possono essere evidenziate delle anomalie o delle possibili anomalie – la sequenza auu permette di dedurre che il valore utilizzato non è stato precedentemente definito • si può quindi risalire all’anomalia, la cui causa è dovuto al fatto che le due variabili x2 e x nel primo assegnamento sono state erroneamente invertite – anche la sequenza ddd (sequenze di definizioni senza usi intermedi) permette di risalire all’anomalia precedentemente evidenziata ■ Regole per il rilevamento di possibili anomalie – R1: l’uso di una variabile x deve sempre essere preceduto in ogni sequenza da una definizione di x, senza annullamenti intermedi – R2: una definizione di una variabile x deve sempre essere seguita da un uso di x, prima di un’altra definizione o di un annullamento di x Convalida e verifica del software (parte 1) 21 Luca Mainetti Analisi di flusso dati (cont.) ■ La tecnica dell’analisi del flusso dati, che i compilatori fanno per noi, e che spesso i programmatori eseguono con un procedimento “mentale” o avvalendosi di tool di debugging, può essere estesa ad altri ambiti ■ Ad esempio, si possono ricondurre ad analisi statica le operazioni svolte sui file ■ Questo è il significato principale del ripercorre tecniche che sono implementate dai compilatori: avere un modello in mente che possa essere riusato in altre situazioni ■ Provate, ad esempio, ad ipotizzare un procedimento simile al precedente, per applicato all’analisi di operazioni con Web service Convalida e verifica del software (parte 1) 22 Luca Mainetti Analisi di flusso dati (cont.) ■ Se il codice sorgente contiene condizioni e/o cicli, il numero di cammini non è limitabile a priori. In questo caso, la formulazione di sequenze di operazioni può essere effettuata con uso di espressioni regolari 1 2 3 4 5 6 7 8 9 10 11 read(x, y); a = x; a = y; while a != b do begin if a > b a = a - b; else b = b - a; end; …... Convalida e verifica del software (parte 1) Si costruisce il grafo di controllo utilizzando due operazioni per gli assegnamenti 6 23 1 read(x, y); 2 a = x; 3 a = y; 4 a != b a>b 11 …… 7 r1=a-b; 9 r2=b-a; 7’ a=r1; 9’ b=r2; Luca Mainetti Analisi di flusso dati (cont.) ■ A ciascun nodo del grafo di controllo si assegnano gli insiemi delle variabili definite, usate, annullate 6 0 begin 1 read(x, y); 2 a = x; 3 a = y; 4 a != b a>b 11 write(a); 7 r1=a-b; 9 r2=b-a; 7’ a=r1; 9’ b=r2; Convalida e verifica del software (parte 1) 24 Luca Mainetti Analisi di flusso dati (cont.) ■ Percorrendo un cammino nel grafo, consultando la tabella ed annotando i tipi di operazioni, è possibile, per ogni variabile definirne la sequenza ■ Ad esempio, percorrendo il cammino – [0, 1, 2, 3, 4, 6, 7, 7’, 4, 11] per la variabile “a” si ottiene la sequenza di operazioni – adduuuuduu ■ Se vogliamo invece scrivere la sequenza di operazioni che corrisponde a più cammini, è necessario un linguaggio che permetta di esprimere alternative e cicli: possiamo utilizzare le espressioni regolari (“+” esprime l’alternativa, “*” esprime il ciclo) Convalida e verifica del software (parte 1) 25 Luca Mainetti Analisi di flusso dati (cont.) ■ Ad esempio, l’espressione regolare che descrive il cammino uscente dal nodo 4 per la variabile “a” è – (u(ud+u)u)*u ■ In modo analogo, l’espressione regolare che descrive il cammino uscente dal nodo 0 per la variabile “a” è – addu(u(ud+u)u)*u – è facile verificare che tutti gli usi sono preceduti da una definizione, ma esiste una definizione mai seguita da un uso (la prima) ■ L’esame delle espressioni regolari permette quindi di verificare se le regole R1 e R2 sono violate ■ Poiché il grafo di controllo può essere complesso ed il numero di variabili elevato, il procedimento qui presentato non viene attuato, ma si preferiscono algoritmi ottimizzati Convalida e verifica del software (parte 1) 26 Luca Mainetti Analisi dinamica ■ Le tecniche di analisi dinamica richiedono l’esecuzione del programma da convalidare e verificare ■ Poiché il numero di possibili esecuzioni è molto grande, si ha la necessità di selezionare un insieme limitato di input significativi ■ La scelta casuale di tali input è generalmente poco significativa e poco praticabile, ma conviene sfruttare la conoscenza del dominio associata alla conoscenza degli algoritmi utilizzati (ad esempio, analizziamo un ciclo “for” in prossimità degli estremi del ciclo steso) – massimizzare la probabilità di rilevare malfunzionamenti – minimizzare i costi di test, cioè il numero di dati di test – utilizzare criteri sistematici Convalida e verifica del software (parte 1) 27 Luca Mainetti Analisi dinamica (cont.) ■ Selezionati i casi di test ed eseguiti sui dati di input, si pone il problema di capire se i risultati ottenuti siano corretti ■ Se confrontiamo i risultati ottenuti con le specifiche, stiamo effettuando una verifica ■ Se confrontiamo i dati di test con i requisiti iniziali o, tipicamente, al giudizio dell’utente, stiamo effettuando una convalida ■ E’ possibile confrontare i risultati ottenuti, con risultati ottenuti da versioni precedenti del programma stesso eseguito sui medesimi input: test di regressione – l’ipotesi è che non siano stati introdotti nuovi malfunzionamenti – il test è facilmente automatizzabile anche per programmi che non producono semplici risultati atomici (analizzare la base dati) ■ Tipicamente si decide essere conclusa la fase di analisi dinamica sulla base di un semplice criterio temporale Convalida e verifica del software (parte 1) 28 Luca Mainetti Analisi dinamica (cont.) ■ Nel seguito presentiamo alcuni fondamenti della teoria del test che possono mostrare come criteri per la terminazione della fase di analisi possono essere derivati da criteri di selezione dei dati di test ■ Un programma P è considerato una funzione dal dominio dei D dei dati al codominio R dei risultati ■ Il risultato P(d) dell’esecuzione di P sul dato d∈D è corretto se soddisfa le specifiche: si indica ok(P,d) ■ Un programma P è corretto, ok(P), se ∀d ∈D, ok(P,d) ■ Un test T per un programma P con dominio D è un sottoinsieme di D: t ∈T è detto dato di test Convalida e verifica del software (parte 1) 29 Luca Mainetti Analisi dinamica (cont.) ■ L’esecuzione di un test T è l’esecuzione di un programma P per tutti i dati di test t appartenenti a T ■ Un programma P è corretto per un test T, ok(P,T), se il programma P è corretto per tutti gli elementi di T, cioè se ∀t ∈T, ok(P,t) ■ Scopo dell’attività di test è rilevare malfunzionamenti, quindi si dice che un test T ha successo, successo(P,T), se rileva uno o più malfunzionamenti di P ■ Se un test non rileva malfunzionamenti non può essere dedotta la correttezza di P – è l’atteggiamento inverso rispetto a quanto si vive nei team di sviluppo: la positività sta nel rilevare malfunzionamenti – in genere si è “soddisfatti” dal non rilevare malfunzionamenti in casi di test perché da qui si deduce (erroneamente) la correttezza di P Convalida e verifica del software (parte 1) 30 Luca Mainetti Analisi dinamica (cont.) ■ La generalizzazione vale solo nel caso ideale: un test T è detto ideale per P se e solo se ok(P,T) ⇒ ok(P) ■ Ovviamente uno degli scopi della teoria del test è la definizione dei metodi che consentono la selezione di test che approssimano quelli ideali ■ Un criterio C di selezione di test T per P è un insieme di predicati sul dominio D ■ Un test T è selezionato dal criterio C, selezionato(C,T), se ∀t ∈T ∃c ∈C tale che c(t) è vero e ∀c ∈C ∃t ∈T tale che c(t) è vero ■ Un criterio di selezione di test consente di selezionare più test per lo stesso programma Convalida e verifica del software (parte 1) 31 Luca Mainetti Analisi dinamica (cont.) ■ Consideriamo infatti il criterio di test – C = {(∃t ∈C tale che t<0), (0 ∈ C), (∃t ∈C tale che t>0)} cioè un test contiene almeno un numero negativo, 0 e almeno un numero positivo. Allora sono test selezionati – {-4, 0, 11} – {-4, -8, -42, 0, -1, 3} ■ Un criterio di test C è affidabile per un programma P, affidabile(C,P), se per ogni coppia di test T1 e T2 selezionati da C, se il test T1 ha successo allora anche T2 ha successo e viceversa, successo(P,T1)⇔successo(P,T2) – il successo di un test selezionato da un criterio affidabile permette di di dedurre il successo di qualsiasi test selezionato dallo stesso criterio Convalida e verifica del software (parte 1) 32 Luca Mainetti Analisi dinamica (cont.) ■ Il fatto che un criterio di test sia affidabile non implica che tutti i test selezionati permettano di evidenziare gli stessi malfunzionamenti ■ Un criterio C di selezione di test è valido per un programma P, valido(C,P), se qualora P non sia corretto, esiste almeno un test T selezionato da C che ha successo per P, cioè è in grado di rilevare i malfunzionamenti di P – se esiste un malfunzionamento in P, tale malfunzionamento è rilevato da uno dei test selezionati da C – per il programma raddoppia con corpo y=x * x • {0, 2} è affidabile (il programma risulta corretto per tutti i test selezionati) • {0, 1, 2, 3, 4} è valido, ma non affidabile • {3, 4, 5, 6, ...} è valido e affidabile Convalida e verifica del software (parte 1) 33 Luca Mainetti Analisi dinamica (cont.) ■ Teorema di Goodenough e Gerhart – il fallimento di un test T per un programma P selezionato da un criterio C affidabile e valido per P, permette di dedurre la correttezza di P – affidabile(C,P) ∧ valido(C,P) ∧ selezionato(C,T) ∧ ¬successo(T,P) ⇒ ok(P) ■ L’affidabilità e la validità sono quindi le proprietà che ci interessano nei criteri di test, ma l’importante è non dedurre tali proprietà dalla conoscenza a priori della correttezza di P ■ Al di là di casi banali (ad esempio il test esaustivo, cioè quello che contiene tutto il dominio D), non è possibile costruire un criterio di selezione generale valido e affidabile Convalida e verifica del software (parte 1) 34 Luca Mainetti Analisi dinamica (cont.) ■ Teorema di Howden – non esiste un algoritmo che, dato un programma arbitrario P, generi un test ideale finito, e cioè un test definito da un criterio affidabile e valido ■ Tesi di Dijkstra – il test di un programma può rilevare la presenza di malfunzionamenti, ma mai dimostrarne l’assenza • è una diretta corrispondenza al teorema di Howden ■ Esistono vari problemi di decidibilità legati alla teoria del test – un problema è detto “non decidibile” se può essere dimostrato che non esiste alcun algoritmo finito che lo possa risolvere – un problema P non è decidibile se non esiste una macchina di Turing in grado di risolverlo Convalida e verifica del software (parte 1) 35 Luca Mainetti Analisi dinamica (cont.) ■ Segue l’espressione di tre problemi non decidibili ■ (1) Teorema di equivalenza dei programmi – non è possibile stabilire se due generici programmi calcolino la stessa funzione o meno • in particolare non si può dimostrare la correttezza di P a partire dall’equivalenza di P con un P1 noto corretto a priori ■ (2) Teorema di equivalenza di cammini – non esiste un algoritmo in gradi di stabilire se due generici cammini del grafo di flusso di un programma calcolino la stessa funzione o meno • ciò è utile nell’ambito dell’esecuzione simbolica Convalida e verifica del software (parte 1) 36 Luca Mainetti Analisi dinamica (cont.) ■ (3) Teorema di Weyuker – Dato un generico programma P i seguenti problemi risultano indecidibili • esiste almeno un dato ingresso che causa l’esecuzione di un particolare comando? • esiste un particolare dato di ingresso che causa l’esecuzione di una particolare condizione (branch)? • esiste un particolare dato di ingresso che causa l’esecuzione di un particolare cammino? • è possibile trovare almeno un dato di ingresso che causi l’esecuzione di ogni condizione (branch) di P? • è possibile trovare almeno un dato di ingresso che causi l’esecuzione di ogni cammino di P? ■ Il teorema di Weyuker è importante per i metodi di test strutturale Convalida e verifica del software (parte 1) 37 Luca Mainetti