Luciano Baresi - Politecnico di Milano
Matteo Miraz - Politecnico di Milano

TestFul

Generazione Automatica di Test per Classi Java

La fase di testing dovrebbe essere una delle attività chiave di ogni processo di sviluppo software. Tuttavia, il testing può richiedere fino alla metà dello sforzo complessivo necessario allo sviluppo del sistema. Uno dei principali problemi è la generazione di test “intelligenti” in grado di esercitare a fondo il sistema, operazione difficile e dispendiosa. Per questo motivo, la comunità di ricerca ha proposto diversi metodi per automatizzare la generazione di questi test; tra questi le tecniche che sfruttano euristiche di ricerca (es. algoritmi genetici) hanno recentemente ottenuto risultati significativi. Queste tecniche sono state applicate con successo a sistemi composti da funzioni e procedure, ma la loro applicabilità ai sistemi object-oriented è ancora limitata.

TestFul si inserisce in questo contesto, e permette di generare test per sistemi con stato mediante algoritmi evolutivi. TestFul è rilasciato come progetto open-source ed è disponibile all’indirizzo http://code.google.com/p/testful. Le principali innovazioni rispetto allo stato dell’arte sono la possibilità di usare diversi criteri di copertura e l’adozione di un approccio olistico.

I lavori precedenti si concentrano quasi esclusivamente sulla copertura del flusso di controllo, generando test in grado di eseguire ogni riga di codice o tutte le varie condizioni. In sistemi orientati agli oggetti converrebbe invece utilizzare altre coperture, come quelle sul flusso dei dati che sono in grado di evidenziare dipendenze mediate dallo stato degli oggetti. Per questo motivo, TestFul è stato strutturato con un’architettura modulare, permettendo di introdurre facilmente altri meccanismi di copertura. Allo stato attuale, TestFul si avvale di criteri di copertura sia white-box (statement coverage, branch coverage, def-use pairs coverage) sia black-box (behavioral coverage) al fine di considerare il sistema da diverse prospettive e garantire un'elevata capacità dei test generati di trovare i potenziali errori.

Inoltre, TestFul adotta un approccio olistico che supera (e si contrappone) alla strategia “divide et impera” utilizzata nelle proposte precedenti. Queste, prima di effettuare la fase di ricerca, analizzano il programma da testare e ne evidenziano i diversi elementi da raggiungere (es. le diverse condizioni). Ognuno di questi elementi viene gestito in maniera indipendente dagli altri, e mediante un algoritmo di ricerca si cerca di generare un test. Tuttavia, è raro che diversi elementi siano completamente indipendenti tra loro, specie in un sistema complesso con stato interno. Al contrario, spesso la possibilità di eseguire una funzionalità del sistema spesso dipende dall’aver esercitato un’altra parte del sistema stesso. Per esempio, si pensi ad una classe che rappresenta un account bancario: per poter effettuare un prelievo è richiesto un saldo opportuno, possibile mediante un precedente deposito (o altra analoga operazione). L’approccio olistico alla base di TestFul permette di generare test capaci di massimizzare i diversi criteri di copertura scelti, e quindi di esercitare le diverse funzionalità del sistema.

Il processo di ricerca di TestFul è completato con una ricerca locale. Questa seconda fase permette di completare la ricerca olistica, recuperando l’efficacia del paradigma “divide et impera”. In dettaglio, la ricerca locale rileva la funzionalità non ancora esercitata, e si focalizza direttamente su quelle.

L'efficacia delle proposte fatte è stata studiata mediante un'ampia e sistematica validazione empirica. A tal proposito, è stato proposto un benchmark composto da progetti considerati da altri studi empirici e da librerie pubbliche. Come confronto, consideriamo sia i lavori che utilizzano tecniche di ricerca, sia quelli che adottano l'esecuzione simbolica, sia gli studi che analizzano test generati da esseri umani. I risultati ottenuti sono incoraggianti, e confermano la capacità di TestFul di gestire in maniera efficiente anche le classi più complesse, superando le prestazioni degli altri approcci. Le proposte introdotte con TestFul aprono nuove interessanti direzioni di ricerca. Da un lato, si può continuare a perfezionare il processo di ricerca, esaminando tecniche di ricerca più avanzate e sfruttando criteri di copertura più completi. D'altra parte, si può cercare di far scalare l'approccio sia considerando diversi livelli di granularità, concentrandosi sui test di integrazione, sia esaminando altre tipologie di sistemi di con stato (ad esempio, componenti o servizi).

Torna alla conferenza