vuoi
o PayPal
tutte le volte che vuoi
ALWAYS FALSE COVERAGE
Prendiamo in considerazione tutte le triplette in cui la condizione è sempre FALSE;
ALWAYS/POSSIBLE FALSE COVERAGE
Prendiamo in considerazione tutte le triplette in cui la condizione è sempre FALSE o può esserlo a seconda della condizione, si considera una sola disgiunzione della condizione;
ALWAYS/POSSIBLE FALSE COVERAGE PLUS
Si usa la stessa regola di prima andando però a considerare tutte le disgiunzioni della condizione.
Infine, facciamo riferimento all'ultimo criterio che ingloba tutti i precedenti.
Il testing costa, quindi, quando considero le triplette faccio in modo da coprire quante più triple possibili con un unico caso di test e cercando di ridurre il numero di invocazioni di metodi. Per realizzare questo posso usare degli accorgimenti che prevedono di individuare le sequenze in questo modo: considero (m1, m2, T) quindi poi considero (m2, m3, T) poi (m3, m4, T) e così via.
Se le pre e post condizioni
Sono scritte in linguaggio formale posso utilizzare degli algoritmi che mi permettono di generare casi di test sulla base dei vincoli (triplette). Questo approccio permette di testare la compatibilità tra metodi, ma non è risolutivo in termini di test di integrazione poiché determinati bug emergono quando vengono invocate sequenze di metodi più lunghe. Inoltre, in sistemi non critici, potrebbero non essere presenti pre e post condizioni.
Il metodo basato sulla macchina a stati. In questo caso la classe e il suo stato viene rappresentata mediante una macchina a stati UML. I concetti a cui bisogna fare riferimento in questo caso sono:
- OSSERVABILITÀ: Saper definire in un determinato istante lo stato in cui si trova la macchina;
- CONTROLLABILITÀ: Saper portare la macchina in un determinato stato;
Nel caso in cui si voglia testare la transizione tra uno stato iniziale (i) ed uno stato finale (j) si considera:
PREAMBOLO: Condizioni che hanno portato la
macchina nello stato iniziale i;
EVENTO Condizioni che determinano la transizione tra lo stato i e lo stato j;
SEQUENZA CARATTERISTICA Determinare lo stato in cui dopo la transizione si trova la macchina e verificare che l'output sia corretto.
Le tipologie di fault che possono essere individuati tramite questo testing sono:
- OUTPUT MANCATO O INCORRETTO Tramite una transizione corretta viene generato un output scorretto;
- FAILURE DOVUTA AD INPUT SCORRETTO Il sistema accetta un input che determinano il verificarsi di una failure;
- EXTRA TRANSITION Il sistema accetta un input illegale che determina il verificarsi di una transizione non specificata;
- STATO CORROTTO Il sistema sulla base di un input si reca in uno stato corrotto;
- MISSING OR INCORRECT TRANSITION TO A VALID STATE Tramite un input corretto ho una transizione non specificata.
I criteri di copertura in questo caso sono:
- TRANSITION COVERAGE Copro tutte le transizioni;
- ALL PREDICATE Copro tutti i predicati.
STATI A partire dal nodo sorgente seguo la prima transizione che può verificarsi quindi mi trovo nel nuovo stato e a sua volta seguo la prima transizione che può verificarsi, continuando così. Questo approccio mi fa costruire un decision tree con pochi rami ma molto profondi, di conseguenza avrò pochi casi di test ma molto corposi;
VISITA IN AMPIEZZA DELLA MACCHINA A STATI A partire dallo stato iniziale seguo tutte le transizioni che si possono verificare a partire da questo e così via. Si crea un decision tree con più rami ma meno profondo, di conseguenza avrò più casi di test ma più semplici (meno corposi).
Quindi, dopo aver costruito il decision tree ho a disposizione le sequenze di invocazioni da testare, però va detto che questo metodo presenta delle limitazioni. Infatti, il criterio round trip non ci assicura che tutte le transizioni siano coperte. Alla fine, bisogna effettuare una verifica manuale.
applicare questo approccio è necessario che: Ogni stato della macchina non sia definito in modo ambiguo, gli stati devono essere mutuamente esclusivi e lo si realizza usando invarianti di stato (condizioni booleane che devono essere vere in uno stato e non possono esserle in un altro. Le condizioni di guardia devono essere ben definite; Si deve poter accedere allo stato di una classe tramite il criterio di osservabilità; Testare il sistema in modo indipendente dall'interfaccia che verrà testata creando un navigation path (albero del menu); Isolare il sistema dal (non deterministico) mediante l'uso di stub (componente chiamato realizzato solo per poter testare). Class integration testing in Object Oriented Il test di integrazioni nei sistemi Object Oriented è volto a testare le interazioni tra componenti diverse, come ad esempio tra classi. È più complesso rispetto all'approccio usato nel mondo procedurale poichésono corrette e se i risultati ottenuti sono quelli attesi. Per fare ciò, è possibile utilizzare il testing di integrazione, che consiste nell'eseguire sequenze di invocazioni tra le classi coinvolte nel sistema. Nello scenario descritto, abbiamo una classe client (A) e una classe server (B). Nel test di integrazione possiamo considerare sia le sequenze di invocazioni interprocedurali all'interno della stessa classe, sia le sequenze di invocazioni che coinvolgono un metodo della classe client che invoca un metodo della classe server. È importante notare che queste invocazioni possono essere effettuate su istanze diverse della classe server. Attraverso il testing di integrazione possiamo individuare diverse tipologie di fault, come ad esempio l'invio di un messaggio ad un oggetto sbagliato a causa del polimorfismo, l'utilizzo dell'istanza sbagliata di un metodo a causa del binding, o ancora il client che invia una chiamata al server violando le precondizioni. L'obiettivo del testing di integrazione è stabilire se le chiamate tra le classi coinvolte sono corrette e se i risultati ottenuti sono quelli attesi.effettuate dal lato client vanno a finire sull'istanza del lato server desiderata, per analizzare questo (binding) valuto lo scope dell'interazione. Lo scope dell'interazione può essere:
- Livello di metodo: l'interazione avviene tramite una reference ad un'istanza della classe server che è locale al metodo della classe client considerato;
- Livello di classe: l'interazione avviene tramite una variabile di istanza, ciò nel metodo della classe client considerato invoco un metodo della classe server su un oggetto della classe server che è definito come variabile di istanza nella classe client.
Il modello che si prende in considerazione è un CFG annotato: un CFG in cui per ogni nodo (rappresentante un metodo della classe client) viene specificata una coppia (id_oggetto - nome_metodo). Tali annotazioni possono essere effettuate tramite operazioni di reverse engineering statica o dinamica:
- Reverse engineering statica:
tramite source code analysis effettuo le annotazioni, il grafo che si ottiene è approssimato in quanto è difficile considerare tutte le istanze della classe server su cui le invocazioni possono essere lanciate;
Reverse engineering dinamica: consente di ottenere un grafo più preciso.
Quindi, dopo aver ottenuto il modello (CFG annotato) bisogna prestare attenzione a due fattori:
- La presenza di cicli: considero il ciclo una sola volta oppure non lo considero proprio;
- La presenza di invisible path: ci potrebbero essere cammini che non vado ad eseguire.
Nel considerare le sequenze di invocazioni si potrebbero escludere:
- Le sequenze che prevedono invocazioni intraproceduali nell'ambito della classe client;
- Sequenze ridondanti, ovvero quelle sequenze di invocazioni che si sovrappongono, che si overloppano oppure identiche.
Nel considerare queste sequenze ridondati, relativamente alla loro gestione posso far riferimento a tre criteri:
Criterio 1 (Server method)...
dell'integrazione del sistema.del test di integrazione. Relativamente al coupling che si realizza tra due classi si possono definire diverse tipologie di coupling. Ricordiamo che il punto in cui avviene l'invocazione tra client e server prende il nome di call-site. Queste tipologie di coupling sono:
- Parameter coupling: il metodo della classe client scambia informazioni con il metodo della classe server tramite l'invio di parametri, inoltre, il metodo della classe server ha almeno un parametro di ritorno. Il parameter coupling path prevede per ciascun parametro scambiato un cammino che inizi con una last_def_bef_call e che termini con un first_use_in_callee;
- Shared variable coupling: il metodo della classe client comunica con il metodo della classe server tramite variabili condivise;