Elaborato Angelino Pasquale N46000090

Transcript

Elaborato Angelino Pasquale N46000090
Facoltà di Ingegneria
Corso di Studi in Ingegneria Informatica
Elaborato finale in Ingegneria del Software
Stato dell'arte e valutazione di strumenti
open source per il testing black box
Anno Accademico 2012/2013
Candidato:
Angelino Pasquale
matr. N46/000090
Ai miei genitori ,
a mia sorella ,
ai miei angeli...
Indice
Introduzione
4
Capitolo 1. Principi e automazione del testing black-box
6
1.1
1.2
1.3
1.4
1.5
1.5.1
1.5.1.1
1.5.1.2
1.5.2
1.6
Obiettivi del testing di un prodotto software
Fondamenti di progettazione di test case
Valutazione del testing
Principali attività di testing
Testing black box
Metodo delle classi di equivalenza (o delle partizioni)
Suddivisione in classi di equivalenza
Copertura delle classi di equivalenza: testing combinatoriale
User Interface Testing
Testing Automation
Capitolo 2. Valutazione di strumenti open source per testing black box
2.1
2.1.1
2.1.2
2.2
2.2.1
2.2.1.1
2.2.2
2.2.3
2.2.4
2.3
2.4
Conclusioni
Bibliografia
JUnit
Caratteristiche principali di JUnit
JUnit 4
Selenium
Selenium IDE
Utilizzo di Selenium IDE
Selenium RC
Selenium WebDriver
Selenium Grid
Tobias
Korat
6
7
7
8
9
11
11
12
13
14
15
15
16
18
21
21
22
24
26
26
27
29
31
32
III
Stato dell'arte e valutazione di strumenti open source per il testing black box
Introduzione
Spesso si è portati a sottovalutare l'importanza del testing di un software per la sua natura di attività
tipicamente "non costruttiva", anzi, in un certo senso distruttiva del lavoro effettuato in precedenza
da chi ha sviluppato il sistema. In realtà, senza questa attività, un'applicazione di una qualunque
azienda risulterebbe nella stragrande maggioranza dei casi inutile e/o non utilizzabile.
E' attraverso il testing che vengono scoperti i difetti del prodotto e se ne mostrano i
malfunzionamenti, ed è grazie ad esso che avviene la sua reale convalida.
Con queste parole non si vuole di certo sminuire le fasi di progetto e realizzazione, senza le quali il
software non esisterebbe affatto, ma si intende far comprendere il motivo per il quale, nella stima
dei costi di un generico prodotto, il testing da solo occupi ben il 40% di essi.
E questo non solo perché molte volte ha una durata ben più lunga di quanto ci si potesse
immaginare, ma anche perché dovrebbe sempre iniziare dalle prime fasi di costruzione del sistema,
con gli stessi sviluppatori che provano i componenti da loro creati, superando il conflitto di
interessi e il senso di colpevolezza che sorge nel momento in cui ci trovano degli errori e
comprendendo che è anche tramite il testing che un software può realmente divenire un prodotto di
qualità.
Questa trattazione interesserà in particolare una delle strategie di testing più significative, quella
funzionale, che prova il sistema senza interessarsi di come questo è stato realizzato e tocca
principalmente le fasi finali del processo di test, sebbene venga attualmente utilizzata spesso anche
per i singoli componenti realizzati.
Ci si immedesima pienamente nel cliente dell'applicazione, che infatti è molte volte coinvolto in
modo anche attivo in questa procedura, proprio per mostrargli la validità del software e metterlo in
condizioni di accettarlo, visto che alla fine sarà lui a doverlo utilizzare, e quindi testarlo con dati
che non siano i suoi può aiutare solo relativamente a verificarne la correttezza.
4
Stato dell'arte e valutazione di strumenti open source per il testing black box
Risulta chiaro, però, come attualmente l'effettuare questa attività in modo manuale sia alquanto
gravoso e, inoltre, può farne salire ancora i già considerevoli costi. Ecco il motivo per il quale si
cerca di automatizzarla il più possibile mediante l'ausilio di strumenti che consentano non solo di
ridurre le fatiche e i tempi del processo, ma anche di eseguirlo in maniera ottimale, cosa che non
sarebbe possibile nella maggioranza dei casi con il solo intervento umano.
In particolare, al giorno d'oggi l'attenzione generale è parecchio orientata ai benefici offerti, non
solo in questo campo, da una specifica classe di strumenti, e cioè quelli open source, letteralmente
"a sorgente aperto", che, se per un normale utente richiamano solo il fatto di essere gratuiti, per i
programmatori e sviluppatori della rete rappresentano un prodotto in evoluzione continua, a cui
loro stessi possono far riferimento e contribuire, collaborando tra loro anche se lontani.
Verrà quindi illustrato, nel corso della trattazione, il funzionamento di alcuni validissimi strumenti
open source per eseguire testing black box, che non avranno quelle grandi potenzialità che forse
possiedono gli equivalenti commerciali allo stesso scopo, ma sicuramente con la loro semplicità
d'uso e con le funzionalità essenziali offerte, non lasciano che questo pesi troppo su chi li utilizza,
motivo che ne ha decretato nel corso degli anni la rapida diffusione e l'innegabile successo.
5
Stato dell'arte e valutazione di strumenti open source per il testing black box
Capitolo 1
Principi e automazione del testing black-box
In questa prima parte verranno richiamati i concetti e le definizioni principali di software testing,
focalizzando l'attenzione sulla strategia black box e sul come essa viene, in generale, attuata
nell'ambito del collaudo del software; il discorso verrà, poi, esteso brevemente al caso di testing
combinatoriale e di testing di sistemi interattivi (in particolare di interfacce utente, UI).
Infine, si cercherà di approfondire la problematica dell'automazione delle attività di testing
funzionale, evidenziandone le caratteristiche peculiari, che saranno, quindi, alla base dell'utilizzo
degli strumenti open source valutati in seguito.
1.1 Obiettivi del testing di un prodotto software
Qualsiasi processo aziendale con l'obiettivo di realizzare un sistema software prevede diverse
attività produttive nelle quali, per interpretazione inesatta dei requisiti del prodotto o anche per
errato utilizzo degli strumenti a disposizione, si tende, sin dai primi stadi di sviluppo, a commettere
errori, che si manifesteranno nel prodotto finale come veri e propri difetti dello stesso, e che non gli
consentiranno di agire, in esecuzione, secondo le aspettative (provocando un malfunzionamento).
E' a causa di questa incapacità umana di operare e comunicare
in modo perfetto che la
realizzazione di un qualunque sistema software è affiancata da un'attività di garanzia di qualità del
prodotto, che viene provato in un certo numero di situazioni rappresentative, accertando, prima del
rilascio al cliente, che si comporti come previsto (test di convalida) e che sia quanto più possibile
privo di difetti (test dei difetti).
Il testing risulta essere dunque un'attività sperimentale di verifica del software, poichè gli errori
dello stesso vengono ricercati osservandone il comportamento e confrontandolo con quello stabilito
in fase di specifica, a differenza di quanto viene fatto, invece, con l'attività analitica di ispezione
del codice e della documentazione di progetto ad esso relativa, basata sul semplice studio di
modelli statici del sistema.
6
Stato dell'arte e valutazione di strumenti open source per il testing black box
Può anche darsi che un difetto nel codice dell'applicazione produca un malfunzionamento solo se
viene utilizzato un particolare compilatore o interprete, oppure solo su una determinata piattaforma
di esecuzione. Pertanto, potrebbe essere necessario collaudare il software su varie piattaforme e
ambienti di sviluppo.
1.2 Fondamenti di progettazione di test case
Per poter testare il software per scoprire (e quindi poi correggere) quanti più difetti possibili prima
di fornirlo al cliente, è necessario progettare una serie di casi di test, ossia particolari scenari di
esecuzione con specifiche combinazioni dei valori d'ingresso al sistema, che abbiano un'elevata
probabilità di far esibire malfunzionamenti. Questa attività va però eseguita in maniera disciplinata
e sistematica e utilizzando tecniche ben precise, per evitare che il testing del prodotto diventi
troppo lungo o gravoso. Il tempo e le risorse a disposizione di chi collauda il software sono infatti
limitati, perciò è necessario che ogni test case distinto sia né troppo semplice né troppo complesso,
e che abbia uno scopo, seppur in modo sottile, diverso da quello degli altri appartenenti alla stessa
test suite (insieme dei casi di prova progettati).
Per verificare che il comportamento osservato del prodotto sia quello previsto (dove la conoscenza
di quest'ultimo risulta essere la prima condizione che deve essere soddisfatta prima di poter
effettuare un qualsiasi test), il software deve dunque essere provato in un certo numero di situazioni
rappresentative che ne garantiscano un operato accettabile anche nei contesti di funzionamento non
presi sotto esame, data l'impossibilità di generare tutte le diverse possibili configurazioni dei dati di
ingresso e, quindi, di testarlo in tutte le sue condizioni operative.
Difatti, il successo di un test dei difetti deriva dalla sua capacità di evidenziare gli errori commessi
nello sviluppo del sistema software, ma nulla di quanto viene fatto durante quest'attività assicura
che lo stesso sistema sia privo dei difetti suddetti, proprio a causa della già menzionata non
attuabilità, in tempi ragionevoli, di un testing realmente esaustivo.
1.3 Valutazione dell'attività di testing
Durante le fasi di progettazione e sviluppo di un prodotto, l'ingegnere del software deve sempre
7
Stato dell'arte e valutazione di strumenti open source per il testing black box
tenere in grande considerazione il fatto che questo sistema dovrà poi essere "collaudato" da chi di
dovere, e per questo è necessario che il suo lavoro sia mirato anche a facilitare le future prove di
esecuzione che verranno effettuate. Allo stesso modo, chi progetta i test case deve fare in modo che
questi abbiano in sé le caratteristiche necessarie ad individuare il maggior numero di errori del
sistema, ma col minimo sforzo.
E' per questo che il test dovrebbe essere sempre adeguato, con casi di test significativi invece che
numerosi; questo aiuterà anche a far sì che i suoi risultati siano il più possibile affidabili e precisi,
riuscendo a isolare gli errori che verranno poi corretti in una successiva fase di debugging. Questa
precisione dipende in gran parte, però, anche dalla stessa accuratezza e accessibilità con cui sono
state formulate le specifiche del sistema, visto che la progettazione dei casi di prova è in gran parte
basata proprio sui risultati dell'ingegneria dei requisiti.
In definitiva, si deve, quindi, cercare di raggiungere un giusto compresso tra numero di difetti
scoperti e numero di test case condotti, per evitare di eseguire un test troppo costoso o, peggio,
inutile, soprattutto quando non si hanno a disposizione degli strumenti automatici a supportare le
attività.
1.4 Principali attività di testing
Come si è già avuto modo di precisare, il testing dovrebbe essere un'attività tutt'altro che
disorganizzata. In particolare due sono le fasi fondamentali che dovrebbero esistere in un qualsiasi
processo di verifica software: il test delle unità e il test del sistema. E' facile rendersi conto di come
questi due processi siano inevitabilmente collegati tra di loro: i difetti dei componenti volutamente
ignorati o sfortunamente non evidenziati durante i primi test, saranno, a volte anche "brutalmente",
scoperti durante il test del prodotto completo.
Il test delle unità è il processo con cui vengono testati i singoli componenti (dotati di
funzionamento autonomo) di un sistema. E' un test dei difetti, che mette in luce gli errori commessi
nelle fasi di sviluppo delle varie parti del software. Nella maggior parte dei casi sono gli stessi
sviluppatori a testarle, iniziando il progetto del testing già nella fase di sviluppo. Se da un lato il
collaudo risulta semplificato, poiché chi ha creato il componente ne conosce vincoli e struttura, e
8
Stato dell'arte e valutazione di strumenti open source per il testing black box
quindi può più facilmente verificare che questi soddisfino i loro requisiti iniziali, dall'altro lo
sviluppatore è evidentemente di parte, e tende a giustificare gli errori che lui stesso ha commesso,
evidenziando meno i difetti del software.
I vari moduli prodotti verranno poi integrati, costruendo il sistema complessivo, ed un team
indipendente di testing sarà responsabile dell'attuazione di un vero e proprio test del sistema, con
obiettivo la verifica della correttezza dell'intero software.
Questa fase prevede innanzitutto la costruzione del sistema a partire dai vari moduli; si verifica che
vengano richiamati correttamente, che trasferiscano i dati nei tempi giusti e che, quindi, lavorino
effettivamente assieme. Viene detta "test di integrazione" e in pratica viene effettuata per cercare
errori nel sistema visto come insieme delle sue parti, ossia nell'organizzazione dei componenti e
nella loro cooperazione.
Successivamente avviene il test della release, che ha come obiettivo la convalida di una versione
del sistema di prossima consegna agli utenti (se questi ultimi sono coinvolti attivamente nella
verifica si parla proprio di test di accettazione della release), mostrando che questa soddisfi i suoi
requisiti e sia affidabile. Se il sistema presenta problemi, questi verranno comunicati poi agli
sviluppatori, che avranno premura di effettuare il dovuto debugging dell'applicazione. Questo test è
solitamente derivato dalle specifiche del software, che viene trattato come una "scatola nera" il cui
comportamento è descritto solamente dall'applicazione di dati di ingresso e dall'esame delle uscite
prodotte. Per questo motivo viene detto test black box, o funzionale, in quanto, a differenza del test
strutturale (detto infatti white box), l'attenzione viene rivolta alle funzionalità che il singolo
componente o il sistema dovrebbe offrire, senza curarsi di come queste siano state effettivamente
realizzate.
1.5 Testing black box
Testare un software o una sua parte identificandolo come una scatola nera significa verificare che
svolga effettivamente le funzioni che dovrebbe e che lo faccia in modo corretto. Non ci si
9
Stato dell'arte e valutazione di strumenti open source per il testing black box
preoccupa della sua struttura interna, dell'implementazione e di come abbiano lavorato i
programmatori. Si accede al software solo tramite l'interfaccia utente oppure tramite altre interfacce
di comunicazione tra processi.
Anche in questo caso, infatti, il lavoro dei testers (che spesso appartengono a un'organizzazione
diversa da quella che ha sviluppato il software) non può non dipendere da un altro tipo di lavoro, e
cioè quello eseguito da chi si è occupato della specifica dell'applicazione. Il testing black box si
concentra sui requisiti funzionali del software: più preciso è stato il modo in cui questi sono stati
formulati, più precisi potranno essere i casi di test derivati da essi e la valutazione dei loro risultati.
Inoltre, nel caso in cui il codice sorgente o la documentazione di progetto siano da mantenere come
"segreti aziendali", il fatto di poter far effettuare questo collaudo anche a persone esterne
all'azienda, risulta essere un indiscutibile vantaggio, così come la possibilità di affidarsi anche a
programmatori che non conoscano gli aspetti interni del software o che non siano così esperti, e che
quindi sono più facili da trovare (e anche meno costosi).
Chi effettua questi test invia al componente o al sistema degli input riconosciuti, dopo una
sistematica attività di selezione, come ad alta probabilità di successo, ossia di scoperta di difetti nel
software, basandosi magari sull'esperienza o semplicemente sul giudizio. Una volta stimolato il
sistema, vengono esaminati gli output forniti e se questi non concordano con quanto previsto nella
progettazione del test case, allora è stata rilevata la presenza di difetti nel software.
10
Stato dell'arte e valutazione di strumenti open source per il testing black box
Si dovrebbe anche cercare di testare per primi i moduli del sistema che si prevede verranno
maggiormente utilizzati, così da concentrare su di essi gli sforzi maggiori, lasciando alla fine il
testing di quelle parti dell'applicazione, la cui esecuzione interesserà solo scenari di utilizzo
eccezionali, anche se, ovviamente, nulla assicura che non siano proprio quelle le funzionalità ad
essere affette da errori.
1.5.1 Metodo delle classi di equivalenza (o delle partizioni)
Uno degli approcci più utilizzati per la progettazione di test case nel testing black box è
sicuramente quello delle partizioni o classi di equivalenza, basato sulla diffusa tendenza dei sistemi
software a comportarsi, in molti scenari d'esecuzione, nello stesso modo, a fronte di ingressi che
presentano una qualche correlazione o caratteristica comune.
C'è da precisare subito, però, come questa attitudine, di forte valenza in molti altri settori
costruttivi, nel campo dell'ingegneria del software debba essere trattata con cautela, poiché spesso
piccolissime differenze, nei dati di input o nelle condizioni dell'ambiente operativo, possono
provocare comportamenti imprevedibili e fortemente diversi tra loro, non mostrando quindi quella
continuità che semplificherebbe notevolmente l'attività di testing e lo studio del sistema.
1.5.1.1 Suddivisione in classi di equivalenza
Con questo approccio, quindi, il dominio dei dati d'ingresso viene suddiviso in classi dalle quali
verranno derivati i casi di prova da sviluppare, riducendo notevolmente il numero di questi ultimi
necessario a dedurre il generico errore del sistema. I test case vengono, difatti, selezionati in modo
da provare simultaneamente il maggior numero di attributi di una classe, basandosi in gran parte
sulle specifiche del sistema, ma anche sull'esperienza.
Tramite questi test è possibile constatare se il software si comporta come dovrebbe e se gestisce in
modo corretto anche gli input non validi. Una possibile partizione di equivalenza è, infatti, proprio
quella in ingressi validi e non validi per il sistema. C'è una cosa però da tener presente:
l'appartenenza ad una classe piuttosto che ad un'altra dipende fortemente anche dallo stato interno
11
Stato dell'arte e valutazione di strumenti open source per il testing black box
dell'applicazione, che spesso non è facile determinare in modo ideale.
In generale, una condizione d'ingresso sulla quale possono essere definite la classe di equivalenza
di valori validi e quelle di valori non validi, può essere uno specifico valore numerico, un intervallo
di valori, un insieme discreto di valori correlati tra loro oppure una condizione booleana. Un
approccio più sistematico potrebbe prevedere anche la distinzione della stessa classe valida in più
classi che dettagliano diverse casistiche di esecuzione, o ancora considerando quei valori atipici o
di confine che di solito vengono ignorati da chi testa il software, ma che spesso sono anche la causa
principale dei fallimenti del sistema, durante la loro elaborazione.
1.5.1.2 Copertura delle classi di equivalenza: testing combinatoriale
Una volta definite le suddette classi, c'è da decidere quale debba essere la test suite che consenta di
coprirle tutte. Anche in questo caso, l'ideale sarebbe trovare il giusto compromesso tra numero di
casi di test e quantità di scenari testati (che consentano di rilevare malfunzionamenti). In generale
comunque si può decidere di minimizzare lo sforzo di esecuzione del testing, con pochi test case,
ma nei quali compaia almeno una volta ogni classe di equivalenza, oppure cercare di generare tutte
le possibili combinazioni delle classi in cui è stato suddiviso il dominio d'ingresso.
Si parla in questo caso di testing combinatoriale, che produce, a partire da tutte le classi di
equivalenza, quindi valide e non valide, tutti i possibili casi di test ottenuti combinando le suddette,
anche se alcuni, per come è stata progettata e realizzata l'applicazione e la sua interfaccia utente,
12
Stato dell'arte e valutazione di strumenti open source per il testing black box
risulteranno non esercitabili, ad esempio se l'assegnazione di un certo valore di una particolare
classe ne impedisce l'inserimento di un altro.
Con questa tecnica si stima vengano riscontrati più del doppio dei difetti della normale copertura
delle classi, e quindi una maggiore affidabilità e qualità del test, che contribuiscono, come si può
immaginare, ad aumentare il livello di conformità dell'implementazione del prodotto alle sue
specifiche. Di contro però l'efficienza del test è sensibilmente ridotta e difficilmente questa tecnica
risulterebbe concretizzabile senza un valido supporto. Esperimenti industriali hanno però
dimostrato che i test cases appartenenti a una test suite molto grande spesso presentavano un livello
molto alto di similarità, ed alcuni di essi in pratica corrispondevano alla stessa sequenza di
esecuzione di metodi, semplicemente con parametri differenti o operazioni tra loro simili. Produrre
questi test case in maniera manuale sarebbe quindi stata un'attività assolutamente ripetitiva. Ecco il
motivo per il quale la tecnica combinatoriale è risultata molto più utile se attuata in condizioni di
test automatizzato, attraverso tool di collaudo come gli strumenti open source Tobias oppure Korat
(per strutture più complesse) che verranno illustrati brevemente nel seguito della trattazione.
1.5.2 User Interface Testing
Se un software è composto da diverse unità, queste interagiscono tra loro mediante delle interfacce,
il cui collaudo risulta fondamentale, poiché l'esistenza di errori nella collaborazione tra gli elementi
influenza il corretto funzionamento dell'intero sistema. Anche questo test delle interfacce è
tipicamente eseguito in maniera black box, e in particolare quello di interfacce utente (UI), che
viene effettuato provando i diversi possibili scenari di interazione utente-applicazione.
Potrebbe essere necessario avere a disposizione un modello che descriva queste interazioni, e il più
comunemente utilizzato è di sicuro quello come macchina a stati, con ingressi, rappresentati da
eventi sull'interfaccia, che scatenano le diverse transizioni associate alle sollecitazioni-utente degli
elementi caratteristici delle user interfaces, ovvero finestre e relativi widget.
Esistono degli strumenti però che consentono di progettare test suite per le UI anche a prescindere
da un modello formale, come quello descritto, delle stesse; uno di questi è il framework Selenium
per le applicazioni web, che verrà ripreso e analizzato anch'esso in seguito, e che rappresenta un
esempio di, come già accennato più volte, sia possibile utilizzare tools automatici a supporto della
13
Stato dell'arte e valutazione di strumenti open source per il testing black box
progettazione ed esecuzione di test suite per il software.
1.6 Testing Automation
E' facile comprendere come anche nel campo del software testing, così come accaduto in
moltissimi altri settori industriali e sociali, l'automazione, con la sua capacità di ridurre
all'essenziale la necessità dell'intervento umano, abbia quindi portato innumerevoli benefici.
Non solo consente di ottimizzare tempi e costi riguardanti l'esecuzione di quelle attività presenti
molto spesso nel processo di realizzazione e quindi ripetitive, ma semplifica anche quelle troppo
ardue e faticose. Gli strumenti tecnologici addetti a queste operazioni offrono poi, senza dubbio,
maggiore sicurezza riguardo la corretta concretizzazione delle stesse, rispetto ovviamente
all'operato umano, che, anche in questo caso, ancor più delicato proprio perché finalizzato alla
ricerca dei difetti del software, non è infallibile e non può quindi fornire quella certezza di essere
stato portato a termine (sembra un paradosso) senza errori.
In pratica, un testing compiuto sulla base del solo giudizio dell'uomo, può non riuscire a scovare i
difetti del sistema, il che di sicuro non ne migliora la qualità, ed è per questo che gli strumenti
automatici consentono di controllare il funzionamento del software offrendo maggiori garanzie
circa la sua correttezza, e permettono inoltre di farlo in modo molto più veloce. Inoltre lo stesso
test, a seguito di modifiche, può essere riutilizzato molto più facilmente, e questo è un vantaggio
che, visti i già citati ed elevati costi dell'attività di testing, non deve essere affatto trascurato.
14
Stato dell'arte e valutazione di strumenti open source per il testing black box
Capitolo 2
Valutazione di strumenti open source per testing black box
In questa seconda sezione, come annunciato, vengono presentati alcuni dei molti tools open source
disponibili per effettuare test, come detto, "a scatola nera". Si parte con il colosso nel campo dello
unit testing JUnit, il cui impatto sull'automazione di testing funzionale è stato tale da influenzare la
maggior parte degli strumenti sviluppati negli anni successivi. Come si vedrà lo stesso Selenium,
utilizzato per il collaudo di applicazioni web e anch'esso illustrato nel seguito, prevede, infatti, la
possibilità di integrare i risultati ottenuti con il suddetto framework. Infine, vengono presentati
brevemente due ulteriori strumenti nel caso si voglia adoperare un approccio combinatoriale:
Tobias e Korat, quest'ultimo basato sul testing di strutture dati anche complesse.
2.1 JUnit
Nell'ambito del testing di unità tramite un approccio black box, lo strumento che ad oggi risulta
essere quello cui la maggior parte degli ingegneri del software fanno riferimento è senz'altro il
framework JUnit. Questo appartiene alla famiglia di frameworks per lo unit testing xUnit, che ebbe
origine dal framework SUnit, sviluppato da Kent Beck per il linguaggio di programmazione
SmallTalk e di cui rappresenta praticamente l'evoluzione. Junit risale ormai al 1997 ed è frutto del
lavoro dello stesso Beck insieme a Erich Gamma, ed è uno strumento Java-oriented, ma, visti i
risultati positivi ottenuti, ne sono state scritte diverse alternative per molti altri linguaggi di
programmazione come C++ (CPPUnit), JavaScript (JSUnit) e così via...
L'ultima release temporale di JUnit è JUnit 4 (in particolare la versione 4.11 del 14 novembre
2012), contenuta nel package org.junit, che ha introdotto alcune interessanti novità rispetto alle
precedenti, residenti invece nel package junit.framework, cercando di essere sempre più in linea
con le esigenze dei testers e di soddisfarle nel modo migliore possibile.
La raccolta .jar di classi Java che costituiscono JUnit può essere controllata esplicitamente
scaricandola dal sito ufficiale e aggiungendola al progetto Java realizzato, ma diversi ambienti di
15
Stato dell'arte e valutazione di strumenti open source per il testing black box
sviluppo, come Eclipse o NetBeans, permettono di usare una versione di JUnit integrata nello
stesso IDE come plug-in, senza bisogno di ulteriori installazioni, rendendo il già semplice utilizzo
del framework ancora più immediato.
2.1.1 Caratteristiche principali di JUnit
Come già si è avuto modo di far intendere, la forza di JUnit sta nella sua enorme semplicità,
caratteristica che nel tempo ha fatto sì che un gran numero di frameworks sviluppati si poggiassero
su di esso e sulla sua struttura., il cui elemento di base è sicuramente il già approfondito concetto di
caso di test, qui rappresentato da una vera e propria classe Java, una per ogni classe da testare, che
estende quella fondamentale di libreria chiamata TestCase. Avere delle classi di test separate dal
software reale costituisce un primo indiscutibile vantaggio dell'utilizzo di JUnit, poichè in questo
modo il programma non viene ulteriormente appesantito da questo codice, che potrebbe non solo
creare conflitti di vario genere, ma che per giunta una volta terminato il testing dovrebbe anche
essere rimosso, con conseguente ulteriore spreco di tempo e risorse.
Ad ogni modo, ogni classe di test JUnit contiene metodi che identificano le diverse situazioni da
provare e il cui nome, per convenzione, deve iniziare con il prefisso test per fare in modo che siano
riconosciuti come tali.
Ad esempio: public void testOperation( ) {...}
JUnit assume, inoltre, che tra tutti i metodi di test non debba esserci alcun tipo di dipendenza, per
non falsare o corrompere i risultati degli stessi. Questo aspetto di JUnit è purtroppo riscontrabile
anche nello stesso concetto di comunicazione fra classi diverse. Infatti, il framework non risulta
essere un utile supporto quando i malfunzionamenti di una unità sono dovuti alla sua integrazione
con altri componenti del progetto.
Oltre a questi metodi, le classi di test ne contengono altri due di uso condiviso setUp e tearDown,
che vengono chiamati rispettivamente prima e dopo ogni metodo di test della classe, e sono
utilizzati per predisporre e concludere l'esecuzione di ogni test, istanziando oggetti, aprendo o
chiudendo la connessione a un database e così via...
16
Stato dell'arte e valutazione di strumenti open source per il testing black box
Ma come fare per valutare i risultati di un test? JUnit mette a disposizione, a questo proposito,
ulteriori metodi chiamati asserzioni, anche questi identificati da un prefisso speciale, assert, che
verificano il comportamento (o lo stato) dell'unità sotto test e permettono di specificare tra l'altro
anche il risultato atteso e un messaggio di errore da visualizzare nel caso questo non rispecchiasse
quello attuale; in questo caso l'asserzione risulta falsa e il test case è fallito (è stato trovato un
malfunzionamento). Utilizzare molte e diverse asserzioni può anche aiutare il tester ad avere
indicazioni da mettere in pratica nella futura operazione di debugging.
Le asserzioni più utilizzate sono riassunte nella seguente tabella:
Statement
Description
fail(String)
Let the method fail. Might be used to check that a certain part of the code is not
reached. Or to have failing test before the test code is implemented.
assertTrue(true) / assertTrue(false)
Will always be true / false. Can be used to predefine a test result, if the test is
not yet implemented.
assertTrue([message], boolean
condition)
Checks that the boolean condition is true.
assertsEquals([String message],
expected, actual)
Tests that two values are the same. Note: for arrays the reference is checked
not the content of the arrays.
assertsEquals([String message],
expected, actual, tolerance)
Test that float or double values match. The tolerance is the number of decimals
which must be the same.
assertNull([message], object)
Checks that the object is null.
assertNotNull([message], object)
Checks that the object is not null.
assertSame([String], expected, actual) Checks that both variables refer to the same object.
assertNotSame([String], expected,
actual)
Checks that both variables refer to different objects.
Figura 2.1 – Asserzioni di JUnit
Le classi di test JUnit rappresentano, quindi, uno strumento sistematico per il test delle varie unità
del software. Spesso i progetti ne includono però un numero così grande che potrebbe non solo
rendere il codice piuttosto disordinato, ma anche singolarmente sottrarre tempo prezioso per la loro
esecuzione. Ecco perchè JUnit fornisce la concretizzazione del meccanismo proprio dell'ingegneria
del software di raggruppare più casi di test in un'unica test suite, la cui esecuzione implica quella
automatica, in ordine arbitrario, di tutti i test in essa contenuti. Qui riportato un piccolo esempio di
codice per una generica TestSuite:
public class AllTests extends TestSuite {
public static TestSuite suite( ) {
17
Stato dell'arte e valutazione di strumenti open source per il testing black box
TestSuite suite = new TestSuite("All!");
suite.addTestSuite(MyTestCase.class);
suite.addTestSuite(AnotherTestCase.class);
return suite;}
}
2.1.2 JUnit 4
Tutti gli elementi sopra accennati con le loro convenzioni costituiscono lo scheletro di base di un
test JUnit. Con l'avvento di una nuova release del framework, si è cercato però di rendere ancor più
immediata la scrittura delle classi di test, in particolare tramite un meccanismo che consentisse di
identificare in modo evidente la natura dei diversi metodi.
Sono state introdotte quindi le annotazioni (divenute disponibili con il Java Development Kit
versione 1.5), con le quali ad esempio non è più necessario che i metodi di collaudo abbiano il
nome che cominci con "test", ma il framework eseguirà ogni metodo annotato come @Test (anche
se devono comunque restare void e senza parametri). Anche i metodi setUp e tearDown sono
sostituibili con metodi annotati rispettivamente come @Before e @After, e inoltre non è più
necessario che le classi di test ereditino dalla classe TestCase, anche se è possibile che vengano
eseguite correttamente anche classi scritte per una versione precedente del framework. A questo
punto però può giustamente sorgere il dubbio sul come vengano invocate le asserzioni se le classi
di test non estendono più TestCase. La risposta è presto data: grazie agli import statici di Java 5, il
problema non si pone e tutto può restare come è stato definito con una precedente versione, senza
bisogno di modificare il codice dell'asserzione:
import static org.junit.Assert.* .
Altre annotazioni possono essere utilizzate per:

quei metodi che devono essere eseguiti prima o dopo tutti i test contenuti in una classe,
marcati rispettivamente con @BeforeClass ed @AfterClass (devono essere statici);

per indicare metodi che il framework deve, almeno per il momento, ignorare nell'esecuzione
(che nelle precedenti versioni sarebbero stati quelli che non iniziavano per "test"),
18
Stato dell'arte e valutazione di strumenti open source per il testing black box
marcandoli semplicemente con @Ignore e facendo così in modo che questi possano in
seguito essere re-inclusi nel test senza grosse difficoltà;

per realizzare una test suite in modo ancor più rappresentativo, con @SuiteClasses({classi
di test}), di cui predisporre l'esecuzione, ad esempio con @RunWith(Suite.class), dove Suite
è uno dei possibili test-runners, incluso in JUnit.
Di seguito sono riportati, a confronto, due semplici frammenti di codice (di esempio) che mettono
in evidenza alcune delle suddette differenze tra le due versioni del framework:
import
import
import
import
static org.junit.Assert.*;
org.junit.After;
org.junit.Before;
org.junit.Test;
import junit.framework.TestCase;
public class TestBlackBox extends TestCase {
public class TestBlackBox {
protected void setUp()
throws Exception{}
@Before
public void initialize() throws Exception{}
protected void tearDown()
throws Exception{}
@After
public void finalize() throws Exception{}
@Test
public void blackboxMethod() {
fail("Not yet implemented");
}
public void testBlackBoxMethod() {
fail("Not yet implemented");
}
}
}
Figura 2.2 – Codice JUnit 4 (a sinistra) e JUnit 3.8 a confronto
2.1.3 Esecuzione dei test con JUnit
Due sono le possibili strade che possono essere percorse per poter eseguire un test tramite il
framework JUnit.
La prima è quella di utilizzare del codice Java standard. In particolare la classe
org.junit.runner.JUnitCore fornisce il metodo runClasses( ) che consente di eseguire una o più
classi di test. Come parametro di ritorno otterremo un oggetto del tipo org.junit.runner.Result che
può essere utilizzato per recuperare informazioni sull'esito dei test. Le classi apposite di cui JUnit
poi dispone sono junit.textui.TestRunner (su console) oppure junit.swingui.TestRunner (grafico).
Basta aprire il command prompt, posizionarsi sulla cartella ed eseguire $java -cp junit.jar.
Per far questo però, come si è già avuto modo di far notare, la libreria JUnit deve essere aggiunta al
classpath del nostro progetto Java.
19
Stato dell'arte e valutazione di strumenti open source per il testing black box
La seconda è invece più semplicemente utilizzare ambienti integrati come Eclipse, che fornisce
anche supporto alla creazione dei test e, soprattutto, alla valutazione dell'esito degli stessi,
verificando se il test ha avuto successo (ossia non sono stati trovati difetti, cosa che come è stato
precisato più volte, però, è l'esito negativo del testing), se sono stati rilevati malfunzionamenti
(viene lanciata una junit.framework.AssertionFailedError e bisogna rivedere il codice dell'oggetto
del test) oppure se ci sono stati degli errori (può darsi che debba essere rivisto anche il test stesso).
La barra che compare nella finestra di Eclipse rende ancor più evidente l'esito del test, poichè
risulterà verde solo se tutti i test hanno successo. E' presente, infine, come si può vedere in figura,
anche una Failure Trace, che fornisce informazioni sul tipo di errore o malfunzionamento
verificatosi.
Figura 2.3 – Esito con successo di un test JUnit in ambiente Eclipse
Figura 2.4 – Esito con fallimento di un test JUnit in ambiente Eclipse
Figura 2.5 – Esito con errori di un test JUnit in ambiente Eclipse
20
Stato dell'arte e valutazione di strumenti open source per il testing black box
Tutto questo rende, quindi, JUnit ancora più rapido e semplice da adoperare, con un'interfaccia
assolutamente user friendly, tanto da divenire ad oggi uno dei principali e più utilizzati strumenti di
unit testing esistenti.
2.2 Selenium
Selenium è un framework di software testing consistente in una suite di tools utilizzati per
automatizzare il collaudo black box di web applications (in particolare per test di accettazione), su
svariate piattaforme. Sono, infatti, supportati i più moderni e conosciuti browsers web e può essere
eseguito su molti sistemi operativi come Windows, Linux e Mac OS. L'ultima release stabile di
Selenium, la versione 2.25, è stata rilasciata a Luglio 2012. Originariamente sviluppato nel 2004 da
Jason Huggins, nel corso del tempo Selenium è diventato sempre più popolare e viene oggi
utilizzato da utenti e organizzazioni per testare in modo automatico sia la GUI (interfaccia utente
grafica) che le funzionalità di un'applicazione, con l'indiscutibile vantaggio di mantenere l'integrità
di quest'ultima sia durante che dopo lo sviluppo, ma consente anche di eseguire test di compatibilità
del browser.
E' possibile creare test tramite Selenium in due modalità: la prima è quella di generarli in
automatico tramite uno dei tools forniti, ossia l'ambiente Selenium IDE. La seconda è quella,
invece, di progettarli manualmente, utilizzando le client API messe a disposizione per molti
linguaggi di programmazione.
2.2.1 Selenium IDE
Selenium IDE è implementato come un'estensione del browser Mozilla Firefox, per cui è di facile
installazione e permette di testare le applicazioni con l'approccio record & playback, basato sul
memorizzare la sequenza di azioni effettuate da un tester per poterle poi eseguire nuovamente in
modo autonomo, senza bisogno però di conoscere alcun linguaggio di scripting. Questo metodo
rende il tool adatto ad effettuare anche eventuali test di regressione, a seguito della modifica di
alcune funzionalità del sistema, con il solo svantaggio di dover riscrivere i test se questi
risulteranno a un certo punto non più validi.
I test possono essere salvati in diversi formati per il loro riuso con altri frameworks, ma
21
Stato dell'arte e valutazione di strumenti open source per il testing black box
normalmente sono registrati in Selenese, il linguaggio di scripting speciale di Selenium, che
fornisce i comandi in formato HTML per eseguire diversi tipi di azioni in un browser e per
recuperare dati dalla pagina web.
La forza di Selenium IDE risiede sicuramente nella sua estrema facilità di cattura e di successivo
replay dei test, mettendo a disposizione dei collaudatori l'autocompletamento dei comandi più
comuni (così da risparmiare tempo) oltre che la possibilità di editare a mano i propri test. Viene
fornito, inoltre, anche un primo supporto al debugging, compreso l'inserimento di breakpoints.
L'intera test suite può, quindi, essere prodotta in maniera quasi completamente automatica,
garantendo in ogni caso il controllo completo sull'esecuzione dei vari test case, e con la possibilità
aggiuntiva di ottenere un report completo su quelli terminati con successo e su quelli falliti,
corredato da informazioni utili sui warnings e sugli errori rilevati.
2.2.1.1 Utilizzo di Selenium IDE
Dopo averlo scaricato dal sito ufficiale della suite e installato in modo semplice come una qualsiasi
altra estensione, Selenium IDE risulta automaticamente integrato in Firefox e subito a disposizione
dell'utente nel menu del browser, tra gli Strumenti di sviluppo web. L'ultima versione attualmente
rilasciata è quella 1.10.0 del 20 dicembre 2012.
Il tool si mostra presto di utilizzo intuitivo ed immediato anche per i non programmatori,
presentando un'interfaccia molto semplice per creare intere test suite, composta tra l'altro da una
finestra nella quale, man mano che l'azione di record prosegue, vengono memorizzati in una tabella
tutti i comandi inviati (vista Table) e generato il codice corrispondente in Selenese (vista Source).
La registrazione dei comandi comincia subito, una volta che il tool viene lanciato, memorizzando le
interazioni dell'utente con il browser e riportandole nella suddetta tabella, dove ogni riga
corrisponde a un comando del test case e contiene nei suoi campi il nome dello stesso (command) e
altri due parametri rappresentanti l'elemento target del comando e il suo valore (value).
I comandi più comuni sono quelli di open, click e type, generati in automatico dal sistema (il cui
fallimento decreta l'interruzione del test, e vengono anche chiamati azioni poichè manipolano lo
stato dell'applicazione), mentre richiedono l'intervento del tester quelli di store (che invece lo
22
Stato dell'arte e valutazione di strumenti open source per il testing black box
esaminano e lo memorizzano in variabili) e quelli di verify/assert. Questi ultimi sono in pratica le
asserzioni (già viste in JUnit) che vengono utilizzate per verificare che lo stato dell'applicazione sia
conforme a quanto ci si aspetta, con la sostanziale differenza che, se un assert fallisce il test è
abortito, se è un verify a fallire, invece, il test continua la sua esecuzione, segnalando
semplicemente l'errore verificatosi. Esiste un ulteriore tipo di asserzione, il waitFor, che in pratica
attende che una determinata condizione diventi vera, ma se ciò non avviene in un pre-settato lasso
di tempo (Timeout), il test viene inevitabilmente anche in questo caso arrestato. Una volta terminata
la registrazione, il test case o l'intera test suite possono essere riprodotti sempre adoperando il tool,
che riesegue i comandi inviati nel loro ordine, annotando nel log sottostante la tabella gli eventuali
warnings o malfunzionamenti.
Di seguito viene riportato un semplice esempio di utilizzo, ottenuto fotografando lo stato dello
strumento alla fine della riproduzione di un test case sull'applicazione di ateneo, Campus,
consistente nell'individuare l'orario di ricevimento del professor Tramontana Porfirio per il corso di
"Ingegneria del Software II". Notiamo, inoltre, come i comandi definiti a mano dall'utente siano
evidenziati in verde rispetto a quelli inseriti invece in automatico, e come sia stato generato il
codice corrispondente in Selenese del test case.
Figura 2.6 – Esempio di utilizzo di Selenium IDE – Vista Table
23
Stato dell'arte e valutazione di strumenti open source per il testing black box
Figura 2.7 – Esempio di utilizzo di Selenium IDE – Vista Source
Selenium IDE non è, però, caratterizzato solo da questa enorme semplicità d'impiego. Presenta
anche un'altra caratteristica, citata già in precedenza, che risulta ad oggi essere fondamentale nella
maggior parte dei suoi contesti d'utilizzo: viene, infatti, offerta l'ulteriore possibilità di esportare il
test case generato in molti formati diversi, ed è innegabile che ciò abbia sicuramente favorito in
questi anni la rapida diffusione e il successo dell'intera Selenium suite.
2.2.2 Selenium RC
Con Selenium è, quindi, possibile generare ed eseguire test in un qualsiasi linguaggio di
programmazione supportato dal tool: per farlo, prima dell'introduzione della versione 2.0, era
necessario l'utilizzo esclusivo di un altro strumento della suite, ossia Selenium RC (Remote
Control). Scritto in Java, questo componente è costituito da:

una serie di librerie client (API) che rappresentano l'interfaccia tra i linguaggi di
programmazione supportati (Java, C#, Ruby, PHP, etc.) e il server, consentendo la scrittura
24
Stato dell'arte e valutazione di strumenti open source per il testing black box
di test in modo assolutamente flessibile;

un server a linea di comando che permette di avviare un browser, cui vengono trasferiti i
comandi utilizzando un altro componente della suite Selenium, ossia Selenium Core, basato
su JavaScript. Questo significa che può essere efficacemente utilizzato sulla maggior parte
dei browsers, dove vengono eseguiti, infine, i comandi specificati nel test case d'interesse.
Questa straordinaria versatilità di Selenium semplifica, come è facile intuire, anche una sua
eventuale integrazione con altri frameworks esistenti di unit testing, come ad esempio lo stesso
JUnit di cui si è discusso in precedenza.
Infatti, è sufficiente ad esempio esportare nel formato JUnit 4 il codice del test case generato da
Selenium IDE ed inserirlo, con le opportune leggere modifiche e configurazioni, in un progetto
creato ad esempio con Eclipse, a cui si dovrà aggiungere però, oltre alla libreria JUnit, la libreria
Selenium client relativa agli script in codice Java. Il test diviene così un vero e proprio JUnit test,
con la sola differenza che verrà eseguito, una volta avviato il server RC, tramite il browser così
come in Selenium IDE, ma alla fine l'esito positivo o meno del test sarà comunque visualizzabile
nell'ambiente Eclipse.
25
Stato dell'arte e valutazione di strumenti open source per il testing black box
2.2.3 Selenium WebDriver
Dalla versione 2.0 di Selenium, è stato introdotto invece l'utilizzo di un altro strumento, Selenium
WebDriver.
Sviluppato per supportare al meglio la crescente dinamicità delle pagine web, WebDriver è basato
su un meccanismo leggermente diverso da quello di Selenium RC, tramite "chiamate dirette" al
browser. Le WebDriver API mantengono la flessibilità del framework, consentendo agli
sviluppatori di creare i loro test in qualunque linguaggio supportato, ma i comandi (in Selenese
oppure in uno dei suddetti linguaggi) sono stavolta inviati al browser tramite un browser-driver,
una sorta di supporto nativo dello specifico browser all'automazione. Questo dimostra come
WebDriver a differenza di Selenium RC, il cui funzionamento in fin dei conti non varia molto da
caso a caso, risulta come realizzato "su misura" per ogni browser supportato, come Firefox, Internet
Explorer, Opera e Chrome. E' questo browser-driver che invia i comandi al browser e ottiene da
esso i risultati. In ogni caso, Selenium RC continua ad essere molto utilizzato, soprattutto nelle
attività di manutenzione delle applicazioni.
WebDriver inizia direttamente un'istanza del browser e la controlla. Non ha bisogno del server di
Selenium per far partire i test, ma l'utilizzo di quest'ultimo potrebbe risultare necessario in alcuni
casi, specialmente quando si cerca di eseguire i suddetti test su più macchine in remoto. Nelle
ultime versioni di Selenium è stata, infatti, inclusa l'utilissima possibilità di supporto a WebDriver
per i test di Selenium distribuiti, realizzati tramite l'ultimo importante componente della Selenium
suite, e cioè Grid.
2.2.4 Selenium Grid
Selenium Grid è un sistema automatico per la distribuzione trasparente di test su più server. E'
basato sul coordinare l'operato di più server Selenium RC, così da permettere l'esecuzione in
parallelo di tests su più piattaforme. Un server fa da hub centrale e controlla sulle macchine remote
le varie istanze dei browsers, che possono anche essere di versioni o configurazioni differenti,
senza che possano sorgere problemi di compatibilità. L'hub regola gli accessi alle suddette istanze,
mantenendo una lista dei server che li forniscono e ricevendo tutte le richieste di tests che poi
26
Stato dell'arte e valutazione di strumenti open source per il testing black box
distribuisce ai nodi giusti, fornendo feedback molto veloci da usare per migliorare l'applicazione.
Figura 2.9 – Il funzionamento di Selenium Grid
Si potrebbe anche pensare di utilizzare codice di test esistente e "distribuirlo"; purtroppo, però, non
è fornita alcuna strategia di esecuzione parallela, perciò è consigliabile scrivere già i propri test in
questa modalità. In ogni caso, l'indiscutibile vantaggio di questo approccio resta l'apprezzabile
risparmio di tempo nel testing di una qualsiasi applicazione e inoltre la possibilità di avviare test
sicuramente più ampi ed accurati rispetto all'utilizzo individuale.
2.3 Tobias
Tobias è un tool per il testing combinatoriale che genera, a partire da un modello, un alto numero di
test cases, così da migliorare il più possibile il livello di confidenza nel software che viene testato.
Sviluppato dall'Università Joseph Fourier di Grenoble, il suo aspetto principale è sicuramente,
come nei tools visti in precedenza, la sorprendente semplicità d'uso, resa ancora maggiore dal non
necessitare di alcuna installazione, poichè lo si utilizza direttamente online, sul sito ufficiale [6].
27
Stato dell'arte e valutazione di strumenti open source per il testing black box
Figura 2.10 – Pagina iniziale del tool on-line Tobias
L'originalità di Tobias risiede nel basarsi sulla sequenza di chiamate dei metodi del test case,
anzichè semplicemente sulla combinazione dei valori dei loro parametri, e ciò permette di
progettare test cases in termini del comportamento che si vuole che essi esercitino nel sistema
piuttosto che sullo stato dello stesso, generando test molto più sistematici e che riescono a coprire
anche situazioni che magari sarebbero state trascurate utilizzando un approccio manuale. In questo
modo di sicuro aumentano considerevolmente le possibilità di rilevare gli errori del prodotto.
Per poter usufruire dei benefici offerti da questo tool, basta caricare, tramite l'interfaccia piuttosto
essenziale presentata sul sito e qui riportata, il file di testo contenente il modello su cui si vuole
venga costruita l'intera test suite richiesta.
Figura 2.11 – Schermata di upload di Tobias
Questo file deve contenere come detto un modello che viene chiamato "test schema", ossia la
definizione di vari set di operazioni "simili" e di valori rilevanti per ogni parametro, chiamati in
Tobias "gruppi", e la cui sintassi di base è riportata di seguito:
28
Stato dell'arte e valutazione di strumenti open source per il testing black box
group GroupName [ GroupQualifier = value , ...] {
Sequence of instructions
OR Set of instructions
OR Set of values
}
Il file ha il limite di avere dimensione massima di 150 kB, ma questa non risulta essere una grossa
preoccupazione, vista la forte compattezza presentata dai modelli di Tobias.
Il test schema viene poi espanso in un set di sequenze dalle quali vengono computate tutte le
combinazioni dei parametri di input per tutte le operazioni del pattern, producendo un gran numero
di test cases che di sicuro porteranno alla rilevazione di un numero maggiore di errori rispetto al
caso manuale. Ma la maggiore forza di Tobias risulta anche essere la sua debolezza. La dimensione
della test suite può divenire un vero problema, a partire dalla dimensione massima del file di output
(che viene inviato in un link via e-mail) di 4 MB che spesso tronca i risultati, ma anche in termini
di risorse da utilizzare per generare ed eseguire il test. Per limitare questa "esplosione
combinatoriale" è sempre meglio progettare il proprio modello di test con cura, evitando chiamate
inutili e mantenendo al minimo il numero dei possibili valori dei parametri.
In ogni caso la robustezza anche dell'output fornito rende più semplice la stessa manutenzione della
test suite, garantendo nella maggior parte dei casi che le correzioni da effettuare siano minime.
Tra i formati del file di output, poi, come si può notare, è disponibile quello di JUnit, garantendo
quindi anche in questo caso la possibilità di un'integrazione semplificata con i propri test projects,
facendo in modo che il collaudatore possa concentrarsi maggiormente sugli aspetti più rilevanti del
testing.
2.4 Korat
Korat è un ulteriore tool che può essere utilizzato per effettuare unit testing black box in modo
combinatoriale, specialmente di implementazioni di strutture dati complesse, come ad esempio
alberi binari, heap etc. . Scaricabile dal sito ufficiale insieme alle varie librerie addizionali che
utilizza, la generazione di test automatica che Korat effettua è basata su forti vincoli strutturali
(specificati da dei predicati Java, costruiti a partire dalle precondizioni del metodo da testare e che,
29
Stato dell'arte e valutazione di strumenti open source per il testing black box
come delle asserzioni, devono essere soddisfatti dai casi di test) e su ulteriori limiti riguardanti le
dimensioni degli input. Il metodo viene, quindi, eseguito su ogni caso di test e ne viene usato anche
uno ulteriore di post-condizione che rappresenta un vero e proprio oracolo di test per verificare la
correttezza dell'output. Grazie alla verifica del predicato, Korat genera i test cases in maniera
efficace e rapida: vengono creati, infatti, in poco tempo, molti test cases, ma a struttura tutti
differente tra loro (vengono detti non-isomorfici), e viene offerta anche la possibilità di visualizzare
graficamente le strutture generate, come si può vedere dallo screenshot presentato di seguito in
figura.
Figura 2.12 – Utilizzo del tool Korat
La sostanziale differenza che è possibile rilevare tra il funzionamento di Tobias e quello di Korat è
che quest'ultimo (oltre al fatto di poter essere utilizzato efficacemente, come già detto, anche per
strutture complesse) genera i diversi casi di test comprendendo in ognuno, oltre alla verifica delle
precondizioni, la chiamata al singolo metodo della classe da testare, e utilizza un generatore che
riesce a coprire un range considerevole di possibili input al sistema. Tobias, di contro, aggiunge
invece la possibilità di esprimere un'intera sequenza di chiamate a metodi nel test schema di cui si è
discusso, permettendo di raggiungere stati del sistema cui non sarebbe possibile arrivare così
semplicemente in altro modo e di esprimere, inoltre, anche test sulla base del suo comportamento.
30
Stato dell'arte e valutazione di strumenti open source per il testing black box
Conclusioni
E' evidente che il provare la validità e la correttezza di un qualunque software non banale risulta
essere sempre più articolato e faticoso di quanto ci si potesse immaginare, e si è ben compreso,
quindi, il motivo che ha portato all'introduzione dei vari strumenti automatici attualmente
disponibili, tramite i quali il collaudatore riesce sicuramente a ridurre molto lo sforzo e i costi di
esecuzione del testing del prodotto.
I tools esaminati (per i quali, per maggiori informazioni si rimanda alle documentazioni sui siti
ufficiali, presenti alla fine della trattazione) si sono dimostrati, nel corso degli anni, dei validi
supporti all'approccio black box del testing, con la loro semplicità di installazione e utilizzo, con le
loro funzionalità essenziali e con le loro potenzialità, tutte caratteristiche che ne hanno favorito la
rapida diffusione e il grande successo, e che probabilmente non hanno nulla da invidiare ai loro
equivalenti commerciali, tanto che un loro miglioramento può essere pensato solo da un punto di
vista che alla fine, in parte, qualcuno di essi è già riuscito a raggiungere: l'autogenerazione dei test
cases più rilevanti e la riduzione del loro numero sulla base di informazioni contenute in specifiche
anche formali, così da eliminare ad esempio casi di test inconcludenti o equivalenti tra loro, per
generare test suites più efficienti e pertinenti a ciò che è il reale utilizzo del prodotto.
Informazioni queste, che potrebbero essere prese ad esempio anche da pre- e post- condizioni,
ipotesi sul valore assunto dai parametri o, addirittura, da diagrammi realizzati nelle fasi di
progettazione dello stesso software.
Si potrebbe anche pensare di affinare la selezione degli stessi valori di input da utilizzare, cosa che
magari un ingegnere non riesce mai a fare manualmente senza tralasciare qualche caso utile o
ridondarne qualcuno che magari tanto utile non è.
Questi, come molti altri possibili miglioramenti, al di là della loro realizzabilità o meno, puntano
tutti allo stesso obiettivo: semplificare e rafforzare un'attività che forse a volte non viene eseguita
come si dovrebbe, ma dalla quale dipende l'intero ciclo di vita del prodotto e la soddisfazione di chi
in futuro potrà e vorrà utilizzarlo.
31
Stato dell'arte e valutazione di strumenti open source per il testing black box
Bibliografia
[1]
[I. Sommerville] [2007] “[Ingegneria del Software, 8a edizione]”
[2]
[R. Pressman] [2008] “[Principi di Ingegneria del Software, 5a edizione]”
[3]
[C. Ghezzi, M. Jazayeri, D. Mandrioli] [2004] “[Ingegneria del Software –
Fondamenti e Principi, 2a edizione]”
[4]
[Documentazione JUnit] [http://junit.sourceforge.net/]
[5]
[Documentazione Selenium] [http://docs.seleniumhq.org/]
[6]
[Sito ufficiale Tobias] [http://tobias.liglab.fr]
[7]
[Documentazione Korat] [http://korat.sourceforge.net]
[8]
[Sito Campus] [http://www.campus.unina.it]
32