Specification-based Testing

Il testing si può fare in tanti modi diversi, per esempio a partire dalle specifiche, e i principali vantaggi sono la possibilità di automatizzarlo, generando i casi di test per esempio dalle specifiche algebrice, automi a stati finiti, grammatica... generando tutte le possibili frasi o combinazioni di dati.

Quando abbiamo specifiche meno formali (semi formali) per esempio basate su diagrammi il cui significato va immaginato da chi legge, potremmo avere problemi di automatizzazione o incomprensioni.

Structural Coverage Testing

Si basa sulla copertura strutturale, che è un criterio di adeguatezza: quando si raggiunge il 100% abbiamo finito.

Copertura delle istruzioni (statement coverage)

Prevede che ogni istruzione eseguibile venga testata almeno una volta. Lo svantaggio è che se c'è un errore il testing lo può rilevare soltato una volta che arrivo a testare quella determinata istruzione con quel determinato caso di test.

Realisticamente è un ottimo risultato arrivare a circa l'85% di coverage.

Per facilitare il lavoro si utilizza il grafo di flusso del controllo (control flow graph) che prende un programma e lo trasforma in un grafo. Con questo strumento possiamo vedere graficamente i percorsi ancora da testare.

Esempio:

Untitled

Basic Block Coverage: Una buona cosa da fare è massimizzare la percentuale di blocchi "base", ovvero blocchi di codice di istruzioni sequenziali, che quindi verranno eseguite una dopo l'altra (→ evitare diramazioni inutili).

Copertura delle diramazioni (branch (decision) coverage)

L'idea è che non ci basta coprire tutte le istruzioni, ma dobbiamo coprire anche tutte le diramazioni (nell'esempio non abbiamo coperto le diramazioni nere, e per coprirle bisognerebbe testare un secondo caso di test).

Verosimilmente avremo un insieme di casi di test, detto test suite. Oppure a volte può bastare un solo input di test che copre tutte le diramazioni, tuttavia questa ipotesi è poco probabile.

Esempio (continua l'esempio precedente):

Untitled

Tuttavia anche in questo caso, resta scoperto il test sulla seconda parte del primo if (a[i]<x). Per avere una copertura completa servirebbero quindi 3 test di input.