tecniche di testing

42

description

tecniche di testing

Transcript of tecniche di testing

Indice

1

Capitolo 1

Applicazione Android

1.1 Abstract

I Beni Culturali in Italia rappresentano una risorsa di inestimabile valore a livello mondiale, che at-trae milioni di visitatori ogni anno attraverso monumenti, siti archeologici e musei. Nasce l'esigenzadi ra�orzare la �liera beni culturali sviluppando le potenzialità del mercato legate all'applicazionedelle tecnologie alla valorizzazione dei beni culturali, ovvero un segmento di produttività che nonè stato ancora oggetto di codi�ca e/o organizzazione. Questa situazione, determinata principal-mente dalla presenza di un mercato �imperfetto� dove a fronte di grandi opportunità si registranodebolezze e ostacoli, rende spesso episodico e non strutturale l'incontro tra la domanda e l'o�erta.Il progetto, partendo dalla rilevazione di questi �colli di bottiglia� ed opportunità, intende de�nirela fattibilità dei modelli organizzativi, di mercato e dei conseguenti fabbisogni formativi e profes-sionali capaci di attivare il mercato secondo procedure e strumenti che permettano lo sviluppo siadella domanda che dell'o�erta. Dopo la riforma del titolo V della Costituzione le Regioni e gli EntiLocali si sono trovati a dover valorizzare un patrimonio culturale sul quale precedentemente nonavevano competenze, nè professionalità dedicate. Contestualmente il forte sviluppo e il di�ondersidell'Information Technology ha spalancato le porte a nuove modalità di fruizione, valorizzazione ecomunicazione del patrimonio culturale condivise da tutti i livelli della popolazione. Mille progetti,soluzioni ed idee sono stati sviluppati e non pochi committenti hanno scommesso sull'applicazionedelle tecnologie alla valorizzazione dei beni culturali. Tuttavia questo processo è avvenuto sino adoggi prevalentemente in maniera episodica, avulso da piani strategici di sviluppo nazionali, localio regionali. In sintesi, le cause di ciò a�eriscono a due principali fattori: da un lato la non sempreadeguata competenza della committenza nella materia e l'assenza di punti di riferimento e/o lineedi sviluppo �date� cui conformarsi, dall'altro un'o�erta di prodotti e servizi estremamente etero-genei, scaturiti da necessità occasionali e che raramente �dialogano� tra di loro, dando vita ad uninutile �sovrapproduzione tecnologica�. Uno dei problemi di ricerca più stimolanti e interessantiè sicuramente quello relativo alla valorizzazione del patrimonio dei beni culturali dove . Anzi,dovrebbe essere importante fornire un ambiente culturale attraverso servizi per rappresentare larelativa conoscenza derivata dalle attuali sorgenti digitali che descrivono il patrimonio culturale,come ad esempio descrizioni testuali, immagini , video ed audio, al �ne di consentire ad un turistache visita un sito di godere di storie multimediali in tempo reale, in modo da arricchire il suo /la sua esperienza culturale. DATABENC, Distretto ad Alta TecnologiA dei BENi Culturali, sipone l'obiettivo di realizzare uno sviluppo socio-economico orientato verso un'analisi �nalizzatadel patrimonio culturale, un nuovo uso delle risorse, in cui il driver tecnologico, rappresentato so-

1

CAPITOLO 1. APPLICAZIONE ANDROID

prattutto dalle ICT, deve giocare un ruolo importante sviluppando e adattando i contenuti di benie servizi diversi per fruitori eterogenei. In un sistema non più caratterizzato dalla specializzazionemono-�liera, ma piuttosto dall'integrazione di molte di esse a�erenti al cultural heritage materialee immateriale. È indubbio quanto oggi i nuovi �media� siano i protagonisti di uno �spostamento�verso rinnovati modelli di comunicazione della conoscenza che mirano ad una estensione, sotto mol-teplici aspetti e secondo forme sempre più rapide e immediate, dell'o�erta culturale. Si tratta diun linguaggio che tende ad enfatizzare gli aspetti percettivi del nostro comprendere de�nendo azio-ni comunicative attuate attraverso immagini che mirano ad agevolare la comprensione, a chiarireaspetti di complessità, a presentare concetti in modo più chiaro e coinciso, a rendere più esplicitee fruibili le informazioni. In breve una comunicazione (visiva) realizzata con una attenzione versogli obiettivi degli utenti, portatrice di una certa capacità di persuasione e, conseguentemente, ingrado di stabilire ulteriori modalità per informare e educare. La digitalizzazione di contenuti è ilfondamento posto alla base di tali nuove pratiche. Per mezzo di tale primaria operazione è possibilepoi restituire, attraverso varie forme di simulazione, �prodotti� adatti a molteplici usi miranti adobiettivi di combinazioni diversi�cate di contenuti complessi resi facilmente accessibili grazie adapplicazioni e ad applicativi caratterizzati da �uidità e contaminazione. Se si guarda,

Progetto Di Ingegneria del Software 2

Capitolo 2

Software Testing

2.1 Testing dell'Applicazione S-Quiz

Per l'esercizio di software testing, fra le varie opzioni di programmi java è stato scelto S-Quiz.L'obiettivo è quello di rilevare la presenza di errori ed eventualmente correggerli.

S-Quiz è un gioco a quiz sviluppato in Java, dove l'utente deve rispondere a diverse domande,selezionando una fra le quattro risposte disponibili, di cui solo una è vera. In totale ci sono 15livelli di gioco. All'aumentare del livello di gioco aumenta anche la di�coltà delle domande chesono scelte casualmente da �le di testo precedentemente compilati. Esiste anche una classi�ca deiprimi 10 giocatori col miglior punteggio: più si è veloci a rispondere più si accumulano punti.

Non avendo a disposizione ne speci�che ne documentazione come azione preventiva è sta-to lanciato il programma S-Quiz per avere un'idea dell'interfaccia utente che viene mostrata.L'interfaccia è mostrata in �gura:

2.1.1 Testing di interfaccia preventivo

Dall'interfaccia si può notare come inizio esecuzione l'esclusiva presenza di menu, senza altri campio bottoni. Si è deciso dunque di e�ettuare un test dell'interfaccia sui suoi menù per veri�carne icomportamenti. A tale scopo è stata utilizzata UISpec4J ossia una libreria a supporto del testingfunzionale e di unità di applicazioni Java con interfaccia utente basata su Swing, che fa uso diJunit. E' stato programmato un caso di test per ogni menù presente nell'interfaccia. Di seguitoviene mostrato il codice relativo al �le TestBlackBox.java:

1 package com.IS2.esercizio;2

3 import org.junit.BeforeClass;4 import org.junit.Test;5 import org.uispec4j.Button;6 import org.uispec4j.MenuItem;7 import org.uispec4j.Panel;8 import org.uispec4j.Trigger;9 import org.uispec4j.UISpec4J;

10 import org.uispec4j.UISpecTestCase;11 import org.uispec4j.Window;12 import org.uispec4j.interception.BasicHandler;

3

CAPITOLO 2. SOFTWARE TESTING

13 import org.uispec4j.interception.MainClassAdapter;14 import org.uispec4j.interception.WindowHandler;15 import org.uispec4j.interception.WindowInterceptor;16

17

18

19 public class TestBlackBox extends UISpecTestCase{20

21 private Panel main;22 private Window menuprova;23

24 @BeforeClass25 public void setUp() {26 //Inizializzazione per tutte le classi di un Adattatore che ha il cui

ruolo di realizzare l’adattamento tra la suite di test e l’applicazione

27 UISpec4J.init();28 setAdapter(new MainClassAdapter(Starter.class, new String[0]));29 main = getMainWindow();30 menuprova=getMainWindow();31 }32

33

34 @Test //Testa la funzionalità del menù help/statistiche35 public void testMenuStatistiche() {36

37 MenuItem menu=menuprova.getMenuBar().getMenu("Help");38 menu.click();39 MenuItem menu2=menu.getSubMenu("Statistiche");40 //WindowsInterceptor richiama la finestra Statistiche e41 WindowInterceptor.init(menu2.triggerClick())42 //controlla se essa viene correttamente visualizzata43 .process(new WindowHandler() {44 public Trigger process(Window w){45 assertTrue(w.containsLabel("In totale ci sono 44 domande"));46 return w.getButton("OK").triggerClick();47 }48 }).run();49

50 }51

52 @Test //Testa la funzionalità del menù help/statistiche53 public void testMenuAbout() {54

55 MenuItem menu=menuprova.getMenuBar().getMenu("Help");56 menu.click();57 MenuItem menu2=menu.getSubMenu("About"); //WindowsInterceptor

richiama la finestra About e58 WindowInterceptor.init(menu2.triggerClick()) //controlla se essa

Progetto Di Ingegneria del Software 4

CAPITOLO 2. SOFTWARE TESTING

viene correttamente visualizzata59 .process(new WindowHandler() {60 public Trigger process(Window w){61 assertTrue(w.containsLabel("S-Quiz"));62 return w.getButton("OK").triggerClick();63 }64 }).run();65

66 }67

68

69 @Test //Testa la funzionalità del menù help/statistiche70 public void testMenuClassifica() {71

72 MenuItem menu=menuprova.getMenuBar().getMenu("Classifica");73 menu.click();74 MenuItem menu2=menu.getSubMenu("Classifica");75 //WindowsInterceptor richiama la finestra Classifica e76 //controlla se essa viene correttamente visualizzata77 WindowInterceptor.init(menu2.triggerClick())78 .process(new WindowHandler() {79 public Trigger process(Window w){80 assertTrue(w.containsLabel("1 - PC: 10"));81 return w.getButton("OK").triggerClick();82 }83 }).run();84

85 }86

87 @Test //Testa la funzionalità del menù Impostazioni88 public void testMenuImpostazioni() {89

90 MenuItem menu=menuprova.getMenuBar().getMenu("Impostazioni");91 menu.click();92 MenuItem menu2=menu.getSubMenu("Gioco Veloce"); //Controlla se vengono

correttamente visualizzate le due93 assertTrue(menu2.isVisible()); //opzioni di gioco.94 MenuItem menu3=menu.getSubMenu("Gioco Normale");95 assertTrue(menu3.isVisible());96 }97

98 @Test //Testa la funzionalità del menù File/Nuova Partita99 public void testMenuNuovaPartita() {

100

101 MenuItem menu=menuprova.getMenuBar().getMenu("File");102 menu.click();103 MenuItem menu2=menu.getSubMenu("Nuova Partita");104 //WindowsInterceptor richiama la finestra NuovaPartita e105 //controlla se essa viene correttamente visualizzata

Progetto Di Ingegneria del Software 5

CAPITOLO 2. SOFTWARE TESTING

106 WindowInterceptor.init(menu2.triggerClick())107 .process(new WindowHandler() {108 public Trigger process(Window w){109 assertTrue(w.containsLabel("Inserisci"));110 w.getInputTextBox().appendText("pippo");111 return w.getButton("OK").triggerClick();112 }113 }).run();114 }115

116

117

118 }

Dall'esecuzione del codice tramite JUnit il risultato ottenuto è mostrato nella �gura:Il testing risulta bloccato sul metodo di test �testMenuNuovaPartita�. Il problema risiede nel

testing del menu File che causa un blocco di JUnit. Si sceglie dunque di procedere manualmentee veri�care il comportamento del software al click del menù File e poi Nuova Partita. Cliccandosul menù nuova partita viene visualizzata una �nestra in cui inserire il nome del giocatore.

Cliccando su ok si nota un blocco del gioco e l'impossibilità di eseguire alcuna operazione.Cliccando sulla x per chiudere il gioco non si ha alcun e�etto. In questo frangente sembra cheil processore faccia fatica a eseguire altre applicazioni come il Broswer o Eclipse. Viene dunquecontrollato lo stato del Software tramite gestione attività di Windows.

L'applicazione impegna il processore per il 28% del suo utilizzo, questo fa capire che c'è qualcheistruzione che viene eseguita senza restituire nessun risultato in cambio. Intuitivamente si potrebbepensare a un loop in�nito e per veri�care tale condizione si è pensato di controllare, tramite letturadel codice, quale funzione viene chiamata al click del pulsante nuova partita.

Nella classe S-Quiz è stato ricercato con CTRL+F �Nuova Partita�, ossia l'etichetta del pulsantedel menu. Di conseguenza si è evidenziata questa porzione di codice:

1 JMenuItem fileNewMenuItem = new JMenuItem("Nuova Partita", KeyEvent.VK_N);2 fileNewMenuItem.addActionListener(new ActionListener() {3 public void actionPerformed(ActionEvent ae) {4 newGame();5 }6 });

2.1.2 Inserimento di sonde per rilevare il problema (Forza Bruta)

Il metodo chiamato al click del menu è newGame(). L'intuizione avuta è relativa alla possibilepresenza di un loop in�nito. A questo punto si inseriscono delle sonde all'interno del programma,in questo caso delle semplici stampe a video per veri�care in quale parte del codice si veri�ca ilblocco:

1 public void newGame() {2 player = new Player("Unidentified-Error");3 try {4 String tempName;

Progetto Di Ingegneria del Software 6

CAPITOLO 2. SOFTWARE TESTING

5 tempName = JOptionPane.showInputDialog("Inserisci il tuo nome:");6 player.setName(tempName);7 System.out.println("Il player è stato settato"); }8 catch (HeadlessException he) { }9 finally {

10 questions = new Questions(player);11 System.out.println("Le domande sono state istanziate");12 GameStart();13 System.out.println("Il gioco è stato lanciato");14 } }

Come si nota dal codice sono state inserite 3 sonde, costituite da un semplice �System.out.prin-tln�. Come visto precedentemente il metodo chiamato da Crea Nuova Partita è newGame, percui si è intuito che il problema risiedesse in tale metodo. Il primo print se visualizzato mostreràche la classe player funziona correttamente, il secondo che la classe Questions viene correttamenteistanziata e il terzo che il metodo GameStart funziona correttamente. Lanciando il programma laconsolle mostra:

La consolle mostra a video la stampa dei soli 2 metodi print. Questo singni�ca che il metodoGameStart() non conclude la sua esecuzione. Si passa dunque all'esaminare tale metodo:

1 public void GameStart() {2 questions.MakeQandA(questions);3 System.out.println("La funzione MakeQandA funziona correttamente");4 MakeGUI((int) questions.getCasualNumber()); }

Un'ulteriore sonda è stata inserita all'interno del codice per veri�care che il metodo MakeQandAriesca a portare a termine la propria esecuzione. Si nota dalla console che è proprio questo metodoche causa il blocco del programma per cui si decide di esaminarlo. Vengono inserite dunque altre 2sonde. Poichè l'ipotesi è quella del ciclo in�nito inseriamo una sonda prima del ciclo while presentee una dopo il ciclo così da essere sicuri che l'esecuzione funzioni prima e dopo il ciclo.

1 System.out.println("Esecuzione prima del ciclo while terminata");2 while (st.hasMoreTokens() && st.countTokens() > 1) {3 switch (numST) { case 0:4 q.questions[file - 1][qu++] = st.nextToken();5 numST--;6 break;7 case 1:8 case 2:9 case 3:

10 q.answer[file - 1][an++] = st.nextToken();11 numST++;12 break;13 case 4:14 case 5:15 q.exactly[file - 1][ex++] = st.nextToken();16 numST = 0;17 break;18 }19 }

Progetto Di Ingegneria del Software 7

CAPITOLO 2. SOFTWARE TESTING

20 try {21 db.close();22 } catch (IOException ioe) {}23 file++; }24 System.out.println("Esecuzione del ciclo while conclusa.");25 }

L'esecuzione del codice porta al seguente risultato:La riga �System.out.println("Esecuzione del ciclo while conclusa.");� non viene eseguita. Il

problema è nel ciclo while che non termina la sua esecuzione. Tramite tecnica di ispezione si cercadi rilevare e correggere il problema.

2.1.3 Debugging

Il ciclo while esaminato per il debugging, ha il compito di riempire le seguenti strutture dati:

1. questions: è una matrice di stringhe che contiene le domande relative ai �le database.txt. Laposizione questions[i][j] si riferisce alla j-esima domanda del �le database[i].txt

2. answer: è una matrice di stringhe che contiene le risposte alle domande relative ai �ledatabase.txt. La posizione answer[i][j] si riferisce alla j-esima risposta del �le database[i].txt

3. exactly: è una matrice di stringhe che contiene le risposte esatte relative ai �le database.txt.La posizione questions[i][j] si riferisce alla j-esima risposta del �le database[i].txt

Ogni �le �database.txt� è strutturato con una serie di domande e 5 risposte. Il ciclo while esaminauna domanda alla volta e la inserisce in question, poi per 4 volte inserisce le 4 risposte errate inquestions e alla quinta iterazione inserisce la risposta esatta in exactly. Di seguito è visualizzato ilcodice errato:

1 System.out.println("Esecuzione prima del ciclo while terminata");2 while (st.hasMoreTokens() && st.countTokens() > 1) {3 switch (numST) {4 case 0:5 q.questions[file - 1][qu++] = st.nextToken();6 numST--;7 break;8 case 1:9 case 2:

10 case 3:11 q.answer[file - 1][an++] = st.nextToken();12 numST++;13 break;14 case 4:15 case 5:16 q.exactly[file - 1][ex++] = st.nextToken();17 numST = 0;18 break;19 }20 }

Progetto Di Ingegneria del Software 8

CAPITOLO 2. SOFTWARE TESTING

21 try {22 db.close();23 } catch (IOException ioe) {}24 file++; }25 System.out.println("Esecuzione del ciclo while conclusa.");26 }

Il costrutto switch viene ripetuto dal ciclo while �no a quando il �le database contiene testoal suo interno. Il case 0 corrisponde all'inserimento della domanda nella matrice. Dopo di che lavariabile numST de�nisce la prossima azione da seguire. Si nota come alla prima iterazione delciclo numST=0, si esegue il case 0 e numST viene decrementata al valore numST=-1. Questoprovoca il blocco della successiva iterazione in quanto -1 non è un valore valido per lo switch.

Oltre a questo difetto si nota un'altra particolarità: esistono 4 risposte errate per il quiz mal'operazione di inserimento di tali risposte è inserita nel case 3: in questo modo il case 4 e ilcase 5 si riferiscono all'inserimento delle risposte in exactly, cosa errata in quanto l'inserimento inexactly deve avvenire una sola volta per l'unica risposta esatta. Da queste premesse viene correttoil codice:

1 System.out.println("Esecuzione prima del ciclo while terminata");2 while (st.hasMoreTokens() && st.countTokens() > 1) {3 switch (numST) {4 case 0:5 q.questions[file - 1][qu++] = st.nextToken();6 numST++;7 break;8 case 1:9 case 2:

10 case 3:11

12 case 4:13 q.answer[file - 1][an++] = st.nextToken();14 numST++;15 break;16 case 5:17 q.exactly[file - 1][ex++] = st.nextToken();18 numST = 0;19 break;20 }21 }22 try {23 db.close();24 } catch (IOException ioe) {}25 file++; }26 System.out.println("Esecuzione del ciclo while conclusa.");27 }

A questo punto viene ripetuto il caso di test in JUNIT con il codice corretto:Il test sul menu Nuova Partita ha avuto esito negativo, così come gli altri test. A questo punto

non sono stati riscontrati errori sui test e�ettuati.

Progetto Di Ingegneria del Software 9

CAPITOLO 2. SOFTWARE TESTING

Per veri�care la copertura del codice relativo a questi casi di test è stato usato EclEmma.EclEmma e' uno strumento di copertura del codice Java per Eclipse. Molto similmente a CodeCover, pemette l'analisi della copertura del codice direttamente nel workbench Eclipse. Il suoutilizzo è molto semplice: tramite il bottone che appare sulla barra di Eclipse, si seleziona il �leJUnit di cui si vuole conoscere la copertura.

E' possibile installare EclEmma inserendo �http://update.eclemma.org/� in Help/Install NewSoftware di Eclipse. Una volta installato apparirà un pulsante verde con una barra, da qui possibilelanciare il �le JUnit visualizzando nella View Coverage la copertura del software. Nell'immagineseguente è visibile il bottone verde da cui è possibile eseguire i �le JUnit per la copertura, e inoltresi può notare come oltre alla visuale coverage vi è anche l'evidenziazione del codice: analogamentea Code Cover, il rosso indica che la riga di codice non e' stata coperta, il giallo indica che e' unariga predicato, quindi coperta in una sola delle sue decisioni e il verde indica che la riga e' statacoperta completamente.

L'immagine seguente mostra la copertura per il �le JUnit di testing dell'interfaccia:

2.2 Testing Black Box

Il Debugging ha permesso di visualizzare il comportamento del gioco S-Quiz, poichè con la pre-senza dell'errore rilevato era impossibile osservare le sue funzionalità. Da questo comportamentoè stato possibile disegnare l'automa relativo all'interfaccia gra�ca, FSM ricostruito per ReverseEngineering a partire dalla UI e�ettivamente implementata. Inoltre dalla visualizzazione dellacopertura di EclEmma, si nota che la percentuale di copertura è ancora troppo bassa, per cui siprocede con l'esecuzione di altri test in modalità Black Box.

2.2.1 User Interface Testing

Dall'analisi del grafo dell'Interfaccia utente è stata progettata una serie di casi di test con l'obiettivodi coprire tutti gli archi del grafo. A tale scopo vengono sintetizzati i casi di test de�nendo perognuno di essi quali archi sono stati coperti.

Test Case Stato Iniziale Sequenza di Eventi Stati Intermedi Stato FinaletestMenuStatistiche() Finestra -Click Menu Help -Menu Help Finestra

Principale -Click su Statistiche -Dialog Statistiche PrincipaletestMenuAbout() Finestra -Click Menu Help -Menu Help Finestra

Principale -Click su About -Dialog About Principale-Click su Ok

testMenuClassi�ca() Finestra -Click Menu Classi�ca -Menu Classi�ca FinestraPrincipale -Click Classi�ca -Dialog Classi�ca Principale

-Click OktestMenuImpostazioni() Finestra -Click su Impostazioni -Menu Impostazioni Finestra

Principale -Click Gioco Veloce -Radio Button 1 Principale-Click Gioco Normale -Radio Button 2

testMenuNuovaPartita() Finestra -Click su Menu File -Menu File FinestraPrincipale -Click Nuova Partita -Dialog Nome Domande

-Inserisci Nome

Progetto Di Ingegneria del Software 10

CAPITOLO 2. SOFTWARE TESTING

-Click su OktestMenuNoNome() Finestra -Click su Menu File -Menu File Dialog

Principale -Click Nuova Partita -Dialog Nome Nome-Click su Ok

testDialogAnnulla() Finestra -Click su Menu File -Menu File FinestraPrincipale -Click Nuova Partita -Dialog Nome Principale

-Click AnnullatestVittoria() Finestra -Click su Menu File -Menu File Finestra

Principale -Click Nuova Partita -Dialog Nome Principale-Inserisci Nome -Finestra Domanda

-Click Ok -Risposta Esattafor(i=0;i<14;i++) -Dialog Vittoria-Risposta Esatta -Classi�ca-Click Rispondi

testVittoriaVeloce() Finestra -Click su Menu File -Menu File FinestraPrincipale -Click Nuova Partita -Dialog Nome Principale

-Inserisci Nome -Finestra Domanda-Click Ok -Risposta Esatta

for(i=0;i<14;i++) -Dialog Vittoria-Risposta Esatta -Classi�ca

testRispostaErrata() Finestra -Click su Menu File -Menu File FinestraPrincipale -Click Nuova Partita -Dialog Nome Domanda

-Inserisci Nome -Finestra Domanda-Click Ok -Risposta Errata

-Risposta Errata -Dialog Errore!testNonSelezionato() Finestra -Click su Menu File -Menu File Finestra

Principale -Click Nuova Partita -Dialog Nome Domanda-Inserisci Nome -Finestra Domanda

-Click Ok -Dialog Risposta-Click Rispondi! non selezionata

testEsci() Finestra -Click su Menu File -Menu File GiocoPrincipale || -Click su Esci -Dialog Arrivederci! TerminatoFinestra -Click su OkDomande

• testMenuStatistiche(): archi coperti -> 5,6,7.

• testMenuAbout(): archi coperti -> 5,8,9.

• testMenuClassi�ca(): archi coperti ->1,3,4

• testMenuImpostazioni(): archi coperti -> 10,11,12,13,14.

• testMenuNuovaPartita(): archi coperti -> 15,18,19. (Questo test è incluso con unasserzione nel testRispostaErrata().

Progetto Di Ingegneria del Software 11

CAPITOLO 2. SOFTWARE TESTING

• testMenuNoNome(): archi coperti -> 15,18,20.c

• testDialogAnnulla(): archi coperti -> 15,18,16.

• testVittoria(): archi coperti-> 15,18,19,22,23,27,4. (Da considerare che alcuni archi sonoin modalità duale sia in partita veloce sia in partita normale).

• testVittoriaVeloce(): archi coperti-> 15,18,19,22,23,27,4.

• testRispostaErrata(): archi coperti ->15,18,19,24,28.

• testNonSelezionata(): archi coperti ->15,18,19,26,25.

I testVittoriaVeloce(), testVittoria(),testRispostaErrata() per essere eseguiti è stato necessariocompilare un �le di testo contentente le risposte esatte e un altro contenente le risposte errate.Questo perchè i RadioButton vengono visualizzati dinamicamente e i loro label dipendono dallerisposte. Per poter dunque catturare ad esempio il RadioButton della risposta esatta è stata fattauna ricerca nel �le delle risposte per controllare di volta in volta fra i 4 RadioButton quale fossequello con la risposta esatta. L'azione duale è per la risposta errata.

L'arco 2 e quelli etichettati con ** sono stati coperti con un semplice click del mouse fattomanualmente.

Con questi casi di test sono stati coperti tutti gli archi e tutti i nodi.La copertura degli archi 17 e 21, e stata e�ettuata tramite controllo manuale data l'impossibilità

di eseguire il test in automatico. Nel seguito mostriamo il codice provato per il test che però haun blocco.

1 @Test2 public void testEsci() {3

4 MenuItem menu=menuprova.getMenuBar().getMenu("File");5 menu.click();6 final MenuItem menu2=menu.getSubMenu("Esci");7

8 WindowInterceptor.init(menu2.triggerClick())9 .process(new WindowHandler() {

10 public Trigger process(Window w)11 assertTrue(window.containsLabel("Arrivederci!"));12 return w.getButton("OK").triggerClick();13 } }).run();14

15 }

2.2.2 Codice JUnit di testing

Di seguito viene proposto il codice dei test e�ettuati. Da notare che alcuni casi di test come test-MenuStatistiche() contiente un controllo in più, questo perchè la stesura del grafo dell'interfacciautente ha messo in luce alcuni aspetti prima non noti, come per esempio il ritorno alla �nestraprincipale o a quella di domanda.

Progetto Di Ingegneria del Software 12

CAPITOLO 2. SOFTWARE TESTING

**NOTA: I test come accennato sono stati realizzati utilizzando la libreria uispec4j. Per l'ese-cuzione corretta dei test è stato necessario installare la jdk 1.6, in quanto con la versione recentenon era possibile un funzionamento dei test, inoltre con questa libreria si evitano i problemi di�WindowsInterception� o �No Windows shown� **.

1 package com.IS2.esercizio;2

3 import java.io.BufferedReader;4 import java.io.FileReader;5 import java.io.IOException;6

7 import org.junit.BeforeClass;8 import org.junit.Test;9 import org.uispec4j.Button;

10 import org.uispec4j.MenuItem;11 import org.uispec4j.Panel;12 import org.uispec4j.RadioButton;13 import org.uispec4j.Trigger;14 import org.uispec4j.UISpec4J;15 import org.uispec4j.UISpecTestCase;16 import org.uispec4j.Window;17 import org.uispec4j.interception.BasicHandler;18 import org.uispec4j.interception.MainClassAdapter;19 import org.uispec4j.interception.WindowHandler;20 import org.uispec4j.interception.WindowInterceptor;21

22

23

24 public class TestBlackBox extends UISpecTestCase{25

26 private Panel main;27 private Window menuprova;28 private String descrizione;29

30 @BeforeClass31 public void setUp() {32 //Inizializzazione per tutte le classi di un Adattatore che ha il cui

ruolo di realizzare l’adattamento tra la suite di test e l’applicazione

33 UISpec4J.init();34 setAdapter(new MainClassAdapter(Starter.class, new String[0]));35 main = getMainWindow();36 menuprova=getMainWindow();37 descrizione=menuprova.getDescription();38 }39

40

41 @Test //Testa la funzionalità del menù help/statistiche42 public void testMenuStatistiche() {

Progetto Di Ingegneria del Software 13

CAPITOLO 2. SOFTWARE TESTING

43 //Test per il menu Statistiche, clicca su Help poi su statistiche econtrolla

44 //che sia visualizzato il dialog45

46 MenuItem menu=menuprova.getMenuBar().getMenu("Help");47 menu.click();48 MenuItem menu2=menu.getSubMenu("Statistiche"); //WindowsInterceptor

richiama la finestra Statistiche e49 WindowInterceptor.init(menu2.triggerClick()) //controlla se essa viene

correttamente visualizzata50 .process(new WindowHandler() {51 public Trigger process(Window w){52 assertTrue(w.containsLabel("In totale ci sono 44 domande"));53 return w.getButton("OK").triggerClick();54 }55 }).run();56

57 assertEquals(descrizione,menuprova.getDescription());//controlla che lafinestra restituita sia quella di

58 //partenza59

60 }61

62 @Test //Testa la funzionalità del menù help/statistiche63 public void testMenuAbout() {64 UISpec4J.init();65 MenuItem menu=menuprova.getMenuBar().getMenu("Help");66 menu.click();67 MenuItem menu2=menu.getSubMenu("About"); //WindowsInterceptor

richiama la finestra About e68 WindowInterceptor.init(menu2.triggerClick()) //controlla se essa

viene correttamente visualizzata69 .process(new WindowHandler() {70 public Trigger process(Window w){71 assertTrue(w.containsLabel("S-Quiz"));72 return w.getButton("OK").triggerClick();73 }74 }).run();75

76 assertEquals(descrizione,menuprova.getDescription());77

78 }79

80

81 @Test //Testa la funzionalità del menù help/statistiche82 public void testMenuClassifica() {83

84 MenuItem menu=menuprova.getMenuBar().getMenu("Classifica");85 menu.click();

Progetto Di Ingegneria del Software 14

CAPITOLO 2. SOFTWARE TESTING

86 MenuItem menu2=menu.getSubMenu("Classifica"); //WindowsInterceptorrichiama la finestra Classifica e

87 WindowInterceptor.init(menu2.triggerClick()) //controlla se essaviene correttamente visualizzata

88 .process(new WindowHandler() {89 public Trigger process(Window w){90 assertTrue(w.containsLabel("pipp"));91 return w.getButton("OK").triggerClick();92 }93 }).run();94

95 assertEquals(descrizione,menuprova.getDescription());96

97 }98

99

100

101

102 @Test //Testa la funzionalità del menù Impostazioni103 public void testMenuImpostazioni() {104 //pest per verificare il funzionamento dei tasti opzione di gioco105 UISpec4J.init();106 MenuItem menu=menuprova.getMenuBar().getMenu("Impostazioni");107 menu.click();108 MenuItem menu2=menu.getSubMenu("Gioco Veloce"); //Controlla se vengono

correttamente visualizzate le due109 assertTrue(menu2.isVisible()); //opzioni di gioco.110 MenuItem menu3=menu.getSubMenu("Gioco Normale");111 assertTrue(menu3.isVisible());112 assertEquals(descrizione,menuprova.getDescription());113

114 }115

116

117

118

119 @Test //Testa la funzionalità del menù help/statistiche120 public void testNonSelezionato() {121 //test che crea una nuova partita e clicca su rispondi senza

selezionare la domanda122 //controlla che si visualizzi il dialog di errore123 UISpec4J.init();124 MenuItem menu=menuprova.getMenuBar().getMenu("File");125 menu.click();126 MenuItem menu2=menu.getSubMenu("Nuova Partita"); //WindowsInterceptor

richiama la finestra NuovaPartita e127 WindowInterceptor.init(menu2.triggerClick()) //controlla se essa

viene correttamente visualizzata128 .process(new WindowHandler() {

Progetto Di Ingegneria del Software 15

CAPITOLO 2. SOFTWARE TESTING

129 public Trigger process(Window w){130 assertTrue(w.containsLabel("Inserisci"));131 w.getInputTextBox().appendText("pippo"); //inserisco il nome del

giocatore132 return w.getButton("OK").triggerClick();133 }134 }).run();135

136 String domanda=menuprova.getDescription();137

138 Button rispondi=menuprova.getButton("Rispondi!");139 WindowInterceptor.init(rispondi.triggerClick()) //controlla se essa

viene correttamente visualizzata140 .process(new WindowHandler() {141 public Trigger process(Window w){142 assertTrue(w.containsLabel("Devi"));143 //inserisco il nome del giocatore144 return w.getButton("OK").triggerClick();145 }146 }).run();147

148

149 assertNotSame(domanda,menuprova.getDescription());150

151 }152

153

154

155 @Test //Testa la funzionalità del menù help/statistiche156 public void testMenuNoNome() {157 UISpec4J.init();158 //Crea una nuova partita senza inserire il nome e controlla che non sia

creata la159 //nuova partita160 MenuItem menu=menuprova.getMenuBar().getMenu("File");161 menu.click();162 MenuItem menu2=menu.getSubMenu("Nuova Partita"); //WindowsInterceptor

richiama la finestra NuovaPartita e163 WindowInterceptor.init(menu2.triggerClick()) //controlla se essa

viene correttamente visualizzata164 .process(new WindowHandler() {165 public Trigger process(Window w){166 assertTrue(w.containsLabel("Inserisci"));167 return w.getButton("OK").triggerClick();168 }169 }).run();170

171 assertEquals(descrizione,menuprova.getDescription());//descrizione siriferisce a finestra principale

Progetto Di Ingegneria del Software 16

CAPITOLO 2. SOFTWARE TESTING

172 //getDescription dovrebbe restituire la finestra principale173

174 }175

176 @Test177 public void testDialogAnnulla() {178 UISpec4J.init();179 //controlla che al click su annulla del dialog per l’inserimento nome180 //la partita non sia creata181 MenuItem menu=menuprova.getMenuBar().getMenu("File");182 menu.click();183 MenuItem menu2=menu.getSubMenu("Nuova Partita"); //WindowsInterceptor

richiama la finestra NuovaPartita e184 WindowInterceptor.init(menu2.triggerClick()) //controlla se essa

viene correttamente visualizzata185 .process(new WindowHandler() {186 public Trigger process(Window w){187 assertTrue(w.containsLabel("Inserisci"));188 return w.getButton("Annulla").triggerClick();189 }190 }).run();191

192 assertEquals(descrizione,menuprova.getDescription());//descrizione siriferisce a finestra principale

193 //getDescription restituire la descrizione della finestrarestituita al click di Annulla

194

195 }196

197

198

199 @Test //controlla che una volta risposto a 15 domande correttamentevisualizza la schermata di vittoria

200 public void testVittoria() throws IOException, InterruptedException{201 UISpec4J.init();202 //Crea una partita e ad ogni risposta seleziona quella corretta.203 //Serve a verificare che dopo 15 risposte esatte venga mostrato il

dialog di vittoria.204 MenuItem menu=menuprova.getMenuBar().getMenu("File");205 menu.click();206 MenuItem menu2=menu.getSubMenu("Nuova Partita"); //WindowsInterceptor

richiama la finestra NuovaPartita e207 WindowInterceptor.init(menu2.triggerClick()) //controlla se essa

viene correttamente visualizzata208 .process(new WindowHandler() {209 public Trigger process(Window w){210 w.getInputTextBox().appendText("pipp"); //inserisco il nome del

giocatore211 return w.getButton("OK").triggerClick();

Progetto Di Ingegneria del Software 17

CAPITOLO 2. SOFTWARE TESTING

212 }213 }).run();214

215 BufferedReader reader = new BufferedReader(new FileReader(".\\Databases\\risposteEsatte.txt"));

216 String line=" ";217 String risposte[]=new String[44];218 int i=0;219 while(line!=null) {220 line=reader.readLine();221 if(line!=null)222 risposte[i]=line;223 i++;224 }225

226 for(int j=0;j<15;j++){227 System.err.println("Indice "+j);228

229 RadioButton bottone = new RadioButton(null);230 Boolean trovato=false;231 int x=0;232

233 while(!trovato && x<44){234

235 try{236 bottone = menuprova.getRadioButton(risposte[x]);237 System.out.println(bottone.getLabel());238 trovato=true;239

240 }catch(Exception e){241 x++;242 }243

244

245 }246

247 bottone.click(); //Seleziona la risposta esatta248 Button risposta=menuprova.getButton("Rispondi!"); //clicca su

rispondi249 final int p=j;250 try{251 if(p<14){252 WindowInterceptor.init(risposta.triggerClick())253 .process(new WindowHandler() {254 public Trigger process(Window w){255 assertTrue(w.containsLabel("Risposta"));256 return w.getButton("OK").triggerClick();257 }258 }).run();

Progetto Di Ingegneria del Software 18

CAPITOLO 2. SOFTWARE TESTING

259 Thread.sleep(1000);260 }261

262 else if(p==14){263 WindowInterceptor.init(risposta.triggerClick())264 .process(new WindowHandler() {265 public Trigger process(Window w){266 assertTrue(w.containsLabel("Hai Vinto"));267 return w.getButton("OK").triggerClick(); }268 }).process(new WindowHandler("Classifica") {269 public Trigger process(Window window) {270 // ... perform some operations on the second window

...271 assertTrue(window.containsLabel("pipp"));272 // return a trigger that will close it273 return window.getButton("OK").triggerClick();274 }275 })276 .run();277

278

279 }280

281

282 }catch(Exception e){283 System.out.println("Si è verificato un errore di interception");284 }285

286

287 }288 }289

290

291

292 @Test //controlla che una volta risposto a 15 domande correttamentevisualizza la schermata di vittoria

293 public void testVittoriaVeloce() throws IOException, InterruptedException{

294 //Come test Vittoria ma in modalità veloce295 MenuItem imp=menuprova.getMenuBar().getMenu("Impostazioni");296 imp.click();297 MenuItem veloce=imp.getSubMenu("Gioco Veloce");298 veloce.click();299

300

301 MenuItem menu=menuprova.getMenuBar().getMenu("File");302 menu.click();303 MenuItem menu2=menu.getSubMenu("Nuova Partita"); //WindowsInterceptor

richiama la finestra NuovaPartita e

Progetto Di Ingegneria del Software 19

CAPITOLO 2. SOFTWARE TESTING

304 WindowInterceptor.init(menu2.triggerClick()) //controlla se essaviene correttamente visualizzata

305 .process(new WindowHandler() {306 public Trigger process(Window w){307 w.getInputTextBox().appendText("pipp"); //inserisco il nome del

giocatore308 return w.getButton("OK").triggerClick();309 }310 }).run();311

312 BufferedReader reader = new BufferedReader(new FileReader(".\\Databases\\risposteEsatte.txt"));

313 String line=" ";314 String risposte[]=new String[44];315 int i=0;316 while(line!=null) {317 line=reader.readLine();318 if(line!=null)319 risposte[i]=line;320 i++;321 }322

323 for(int j=0;j<15;j++){324 System.err.println("Indice "+j);325

326 RadioButton bottone = new RadioButton(null);327 Boolean trovato=false;328 int x=0;329

330 while(!trovato && x<44){331

332 try{333 bottone = menuprova.getRadioButton(risposte[x]);334 System.out.println(bottone.getLabel());335 trovato=true;336

337 }catch(Exception e){338 x++;339 }340

341

342 }343

344

345

346 final int p=j;347 try{348 if(p<14){349 WindowInterceptor.init(bottone.triggerClick())

Progetto Di Ingegneria del Software 20

CAPITOLO 2. SOFTWARE TESTING

350 .process(new WindowHandler() {351 public Trigger process(Window w){352 assertTrue(w.containsLabel("Risposta"));353 return w.getButton("OK").triggerClick();354 }355 }).run();356 Thread.sleep(1000);357 }358

359 else if(p==14){360 WindowInterceptor.init(bottone.triggerClick())361 .process(new WindowHandler() {362 public Trigger process(Window w){363 assertTrue(w.containsLabel("Hai Vinto"));364 return w.getButton("OK").triggerClick(); }365 }).process(new WindowHandler("Classifica") {366 public Trigger process(Window window) {367 // ... perform some operations on the second window

...368 assertTrue(window.containsLabel("pipp"));369 // return a trigger that will close it370 return window.getButton("OK").triggerClick();371 }372 })373 .run();374

375

376 }377

378

379 }catch(Exception e){380 System.out.println("Si è verificato un errore di interception");381 }382

383

384 }385 }386

387

388

389 @Test //controlla che una volta risposto a 15 domande correttamentevisualizza la schermata di vittoria

390 public void testRispostaErrata() throws IOException, InterruptedException{

391 UISpec4J.init();392 //Controlla che al click di una risposta errata sia visualizzato il

dialog di risposta errata393 //e poi la classifica394 MenuItem menu=menuprova.getMenuBar().getMenu("File");

Progetto Di Ingegneria del Software 21

CAPITOLO 2. SOFTWARE TESTING

395 menu.click();396 MenuItem menu2=menu.getSubMenu("Nuova Partita"); //WindowsInterceptor

richiama la finestra NuovaPartita e397 WindowInterceptor.init(menu2.triggerClick()) //controlla se essa

viene correttamente visualizzata398 .process(new WindowHandler() {399 public Trigger process(Window w){400 w.getInputTextBox().appendText("pipp"); //inserisco il nome del

giocatore401 return w.getButton("OK").triggerClick();402 }403 }).run();404

405 //Corrisponde a testNuovaPartita406 assertNotSame(descrizione,menuprova.getDescription());//descrizione

si riferisce a finestra principale407 //getDescription dovrebbe restituire la finestra con domande.408

409 BufferedReader reader = new BufferedReader(new FileReader(".\\Databases\\risposteErrate.txt"));

410 String line=" ";411 String risposte[]=new String[44];412 int i=0;413 while(line!=null) {414 line=reader.readLine();415 if(line!=null)416 risposte[i]=line;417 i++;418 }419

420

421 RadioButton bottone = new RadioButton(null);422 Boolean trovato=false;423 int x=0;424

425 while(!trovato && x<44){426

427 try{428 bottone = menuprova.getRadioButton(risposte[x]);429 System.out.println(bottone.getLabel());430 trovato=true;431

432 }catch(Exception e){433 x++;434 }435

436

437 }438

Progetto Di Ingegneria del Software 22

CAPITOLO 2. SOFTWARE TESTING

439 bottone.click(); //Seleziona la risposta esatta440 Button risposta=menuprova.getButton("Rispondi!"); //clicca su

rispondi441

442 try{443

444 WindowInterceptor.init(risposta.triggerClick())445 .process(new WindowHandler() {446 public Trigger process(Window w){447 assertTrue(w.containsLabel("sbagliata"));448 return w.getButton("OK").triggerClick();449 }450 }).process(new WindowHandler("Classifica") {451 public Trigger process(Window window) {452 // ... perform some operations on the second window ...453 assertTrue(window.containsLabel("pipp"));454 // return a trigger that will close it455 return window.getButton("OK").triggerClick();456 }457 })458 .run();459 Thread.sleep(1000);460

461 }catch(Exception e){462 System.out.println("Si è verificato un errore di interception");463 }464

465

466

467 }468

469

470

471

472

473 }

2.2.3 Esito Testing e Copertura

Il �le sopra mostrato è stato lanciato tramite l'utilizzo di JUnit e di UiSpec4j. Inoltre per l'ese-cuzione è stato utilizzato il plugin ECLEmma per visualizzare la percentuale di codice coperto.Viene mostrato dunque l'esito:

Dalla �gura si evince che la copertura totale del Software è del 83,7%: è da considerare cheil test sul Menù Esci è stato eseguito manualmente, quindi la percentuale reale di copertura è dipoco superiore a quella trovata qui.

In particolare si nota come due casi di test abbiano avuto esito positivo, il restante risultaessere negativo.

Progetto Di Ingegneria del Software 23

CAPITOLO 2. SOFTWARE TESTING

Errori Rilevati:

1. testDialogAnnulla(): si è notato che premendo annulla sul Dialog di inserimento nome non siritorna alla schermata principale ma si avvia comunque il gioco. Ci si aspettava che il gioconon partisse.

2. testMenuNoNome(): si è notato che cliccando su OK senza inserire un nome su Dialog diinserimento il gioco parte ugualmente con un giocatore senza nome.

**NOTA: Si è riscontrato che nell'eseguire i casi di test, a volte si veri�cano dei blocchi conconseguente necessità di riavviare il testing. Questo fenomeno è stato riscontrato anche in rete indiversi forum che invitavano a rieseguire i test qualora si veri�casse un blocco. **

2.3 Test White Box

Il testing White Box ha avuto come inizializzazione una fase di ispezione del codice, dovuta alcontrollo della copertura ottenuta con EclEmma. Sono state quindi prese in considerazione quelleporzioni di codice che non risultavano completamente coperte. Si è deciso dunque di eseguire untest white box di unità su queste sezioni per controllare l'e�ettivo funzionamento.

L'immagine mostra che il codice di NewGame() non è completamente coperto, si nota chequesto codice è relativo alla �nestra di dialogo di inserimento nome.

Il test Black Box testDialogAnnulla() ha avuto esito positivo, si suppone dunque che il problemariesieda proprio in questa sezione di codice. Si rimanda al paragrafo di debugging per la correzionedell'errore.

Dall'immagine riportata si può notare una copertura molto bassa di questa porzione di codice.Si decide di progettare un caso di test per cercare di coprire il codice al 100%.

Il test progettato per il metodo è testNumberCompare(). Per eseguire il test è stato necessariode�nire un driver per il metodo poichè esso risulta un metodo privato. Il driver viene presentatoin basso:

1 public int driverNumberCompare(String primo,String secondo){2 return this.numberCompare(primo, secondo); }

L'esecuzione del test ha portato alla copertura completa del metodo con esito negativo del test:Il metodo InitLadder non presenta una copertura soddisfacente.Per questo motivo è stato

realizzato un driver per e�ettuare il testing di tale metodo:

1 public String driverInitLadder() throws IOException{2 initLadder();3

4 String classifica=5 topTen[0] + ": " + topTenPoints[0] + "\n" +6 topTen[1] + ": " + topTenPoints[1] + "\n" +7 topTen[2] + ": " + topTenPoints[2] + "\n" +8 topTen[3] + ": " + topTenPoints[3] + "\n" +9 topTen[4] + ": " + topTenPoints[4] + "\n" +

10 topTen[5] + ": " + topTenPoints[5] + "\n" +11 topTen[6] + ": " + topTenPoints[6] + "\n" +12 topTen[7] + ": " + topTenPoints[7] + "\n" +

Progetto Di Ingegneria del Software 24

CAPITOLO 2. SOFTWARE TESTING

13 topTen[8] + ": " + topTenPoints[8] + "\n" +14 topTen[9] + ": " + topTenPoints[9];15

16 return classifica;17 }

Driver esegue il metodo initLadder() così da aggiornare i valori di topTen e topTenPoint perpoi restituire la classi�ca calcolata.

Vengono dunque progettati diversi casi di test White Box per il metodo initLadder:

TC Precond Input O Attesi O Riscontrato PostCond EsitotestInitLadder1() Il �le dbLadder deve - classi�ca negativo

contere i seguenti valori: correttaPC PC PC100 100 100PC PC PC90 90 90PC PC PC80 80 80PC PC PC70 70 70PC PC PC60 60 60PC PC PC50 50 50PC PC PC40 40 40PC PC PC30 30 30PC PC PC20 20 20PC PC PC10 10 10

testInitLadder2() Il �le dbLadder deve Classi�ca positivocontere i seguenti valori: corretta

PC PC PC200 200 200PC PC PC100 100 100PC PC PC90 90 90PC PC PC80 80 80PC PC PC70 70 70PC PC PC

Progetto Di Ingegneria del Software 25

CAPITOLO 2. SOFTWARE TESTING

60 60 60PC PC PC50 50 50PC PC PC40 40 40PC PC PC30 30 30PC PC PC20 20 10PC10

testInitLadder3() Il �le dbLadder deve pippo Classi�ca positivocontere i seguenti valori: 20001 corretta

PC PC PC100 100 100PC PC PC90 90 90PC PC PC80 80 80PC PC PC70 70 70PC PC PC60 60 60PC PC PC50 50 50PC PC PC45 45 45PC PC PC40 40 40PC PC PC30 30 30PC PC PC20 20 10PC10

testInitLadder4() Il �le dbLadder deve Classi�ca positivocontere i seguenti valori: corretta

PC PC PC100 100 100PC PC PC90 90 90PC PC PC80 80 80PC PC PC70 70 70PC PC PC

Progetto Di Ingegneria del Software 26

CAPITOLO 2. SOFTWARE TESTING

60 60 60PC PC PC50 50 50PC PC PC45 45 45PC PC PC40 40 40PC PC PC30 30 30PC PC PC20 20 20PC PC PC10 10 5PC5

Sempre dall'ispezione del codice si è notata una scarsa copertura anche del codiceupdateLadder():

Per questo metodo sono stati progettati i seguenti casi di test utilizzando il driver nella �guraseguente. I casi di test vengono speci�cati nella tabella successiva:

1 public String[] driverUpdateLadder(String nome,String punteggio) throwsIOException{

2 player=new Player(nome);3 player.addPoints(Integer.parseInt(punteggio));4

5 initLadder();6 updateLadder();7

8 BufferedReader reader = new BufferedReader(new FileReader(".\\Databases\\dbLadder.txt"));

9 String line=" ";10 String ladder[]=new String[50];11 int i=0;12 while(line!=null) {13 line=reader.readLine();14 if(line!=null)15 ladder[i]=line;16 i++;17 }18

19 return ladder;20

21

22 }

Progetto Di Ingegneria del Software 27

CAPITOLO 2. SOFTWARE TESTING

Il driver come prima operazione crea un nuovo giocatore, esegue poi il metodo updateLadder()e restituisce il contenuto di dbLadder() così è possibile veri�care se l'operazione di aggiornamentoè andata a buon �ne.

TC Precond Input O Attesi O Riscontrato PostCond EsitotestUpdateLadder1() Il �le dbLadder Il dbLadder negativo

deve contere i viene aggiornatoseguenti valori: correttamente

PC pippo PC PC100000 100000 100000 100000PC pippo pippo

90000 100000 100000PC PC PC

80000 90000 90000PC PC PC

70000 80000 80000PC PC PC

60000 70000 70000PC PC PC

50000 60000 60000PC PC PC

40000 50000 50000PC PC PC

30000 40000 40000PC PC PC

20000 30000 30000PC PC PC

10001 20000 20000PC PC

10001 10001testUpdateLadder2() Il �le dbLadder Il dbLadder negativo

deve contere i viene aggiornatoseguenti valori: correttamente

PC pippo PC PC100000 10002 100000 100000PC PC PC

90000 90000 90000PC PC PC

80000 80000 80000PC PC PC

70000 70000 70000PC PC PC

60000 60000 60000PC PC PC

50000 50000 50000PC PC PC

Progetto Di Ingegneria del Software 28

CAPITOLO 2. SOFTWARE TESTING

40000 40000 40000PC PC PC

30000 30000 30000PC PC PC

20000 20000 20000PC pippo pippo

10001 10002 10002PC PC

10001 10001testUpdateLadder3() Il �le dbLadder Il dbLadder negativo

deve contere i viene aggiornatoseguenti valori: correttamente

PC pippo PC PC100000 20001 100000 100000PC PC PC

90000 90000 90000PC PC PC

80000 80000 80000PC PC PC

70000 70000 70000PC PC PC

60000 60000 60000PC PC PC

50000 50000 50000PC PC PC

40000 40000 40000PC PC PC

30000 30000 30000PC pippo pippo

20000 20001 20001PC PC PC

10001 20000 20000PC PC

10001 10001testUpdateLadder4() Il �le dbLadder pippo Il dbLadder negativo

deve contere i 10000 viene aggiornatoseguenti valori: correttamente

PC PC PC100000 100000 100000PC PC PC

90000 90000 90000PC PC PC

80000 80000 80000PC PC PC

70000 70000 70000PC PC PC

Progetto Di Ingegneria del Software 29

CAPITOLO 2. SOFTWARE TESTING

60000 60000 60000PC PC PC

50000 50000 50000PC PC PC

40000 40000 40000PC PC PC

30000 30000 30000PC PC PC

20000 20000 20000PC PC PC

10001 10001 10001null nullnull null

Si mostra nell'immagine seguente l'esito dell'esecuzione dei test utilizzando JUnit:Per i test testInitLadder2(),testInitLadder3(),testInitLadder4() si è riscontrato un esito posi-

tivo. E' dunque indice di presenza di un difetto. In particolar modo dall'analisi della classi�carestituita, si è notato come ogni volta restituisse sempre i primi nove valori più grandi corretta-mente, per il decimo valore più grande invece restituisce sempre il valore più piccolo dell'intero�le.

2.3.1 Debugging

2.3.1.1 TestDialogAnnulla

Questo caso di test si riferisce al comportamento errato relativo al click del pulsante annulla deldialog di inserimento nome. Quando si clicca su annulla il gioco parte comunque mentre ci siaspetta che si rimanga nella schermata principale. Si è e�ettuato quindi un ispezione del codicedel metodo newGame() che è il responsabile della visualizzazione del dialog:

1 public void newGame() {2 player = new Player("Unidentified-Error");3 try {4 String tempName;5 tempName = JOptionPane.showInputDialog("Inserisci il tuo nome:")

;6 player.setName(tempName);7 System.out.println("Il player è stato settato");8 } catch (HeadlessException he) {9 } finally {

10 questions = new Questions(player);11 System.out.println("Le domande sono state istanziate");12 GameStart();13 System.out.println("Il gioco è stato lanciato");14

15 }

Progetto Di Ingegneria del Software 30

CAPITOLO 2. SOFTWARE TESTING

16 }

Dall'analisi del codice risulta che l'errore consiste nella presenza del blocco �nally. Quando siclicca su annulla viene sollevata un eccezione poichè tempName risulta null. L'eccezione viene cat-turata adeguatamente ma la presenza del blocco �nally esegue comunque le sue istruzioni, quandoin realtà queste istruzioni non dovrebbero essere eseguite. Si mostra nel seguito la correzione delcodice:

1 public void newGame() {2 player = new Player("Unidentified-Error");3 try {4 String tempName;5 tempName = JOptionPane.showInputDialog("Inserisci il tuo nome:")

;6 player.setName(tempName);7 System.out.println("Il player è stato settato");8

9 if(tempName != null && !tempName.isEmpty() )10 {11 questions = new Questions(player);12 System.out.println("Le domande sono state istanziate");13 GameStart();14 System.out.println("Il gioco è stato lanciato");15 }16 } catch (HeadlessException he) {17 }

Con questa correzione cliccando su annulla o su ok senza inserire il nome non si avvia un nuovogioco.

2.3.1.2 Debug InitLadder()

Si mostra il codice errato di InitLadder():

1 private void initLadder() {2 int i = 0, a = 0;3 int pnt = 0;4 String Str = "";5 StringTokenizer seq;6 try {7 ladder = new FileInputStream(".\\Databases\\dbLadder.txt");8 //Read the file and copy it into Str String variable.9 do {

10 try {11 i = ladder.read();12 if (i != -1) Str += (char) i;13 } catch (IOException ioe) {}14 } while (i != -1);15 seq = new StringTokenizer(Str, "\r\n", false);16 String instr;

Progetto Di Ingegneria del Software 31

CAPITOLO 2. SOFTWARE TESTING

17 while (seq.hasMoreTokens() ) {18 switch (pnt) {19 case 0:20 topTen[a] = seq.nextToken();21 pnt = 1;22 break;23 case 1:24 topTenPoints[a] = seq.nextToken();25 pnt = 0;26 if (a < 9) a++;27 else break;28 break;29 }

Il problema nel codice consiste nell'istruzione if(a<9) e nell'assenza di controlli nel ciclo while.Il valore di a viene incrementato �no al valore massimo 8 così i primi 9 valori vengono letticorrettamente. Quando a==8, il ciclo non si ferma perchè la condizione del while continua �no aquando ci sono token nel �le. Quello che succede in pratica è che il valore di topTen[9] viene divolta in volta aggiornato al valore del next token. E' dunque necessario inserire un controllo nelciclo while ed eliminare l'if. Si mostra nel seguito il codice corretto:

1 private void initLadder() {2 int i = 0, a = 0;3 int pnt = 0;4 String Str = "";5 StringTokenizer seq;6 try {7 ladder = new FileInputStream(".\\Databases\\dbLadder.txt");8 //Read the file and copy it into Str String variable.9 do {

10 try {11 i = ladder.read();12 if (i != -1) Str += (char) i;13 } catch (IOException ioe) {}14 } while (i != -1);15 seq = new StringTokenizer(Str, "\r\n", false);16 String instr;17 while (seq.hasMoreTokens() && a<10 ) {18 switch (pnt) {19 case 0:20 topTen[a] = seq.nextToken();21 pnt = 1;22 break;23 case 1:24 topTenPoints[a] = seq.nextToken();25 pnt = 0;26 a++;27 break;28 }

Progetto Di Ingegneria del Software 32

CAPITOLO 2. SOFTWARE TESTING

Dopo aver corretto i diversi errori si procede con l'esecuzione dei test per veri�care la correttezzadei risultati:

Dall'esecuzione dei test si evince che tutti i casi di test precedentemente progettati hanno esitonegativo. Gli errori sono stati corretti. La copertura però non risulta soddisfacente poichè ha unvalore del 89.8%. Da ispezione del codice si è notato come il codice ancora non coperto risiedesse nelmetodo break() della classe SQuiz. In particolar modo tutto il blocco �nally risulta parzialmentecoperto. Visitando il sito u�ciale di EclEmma si è notato che questo è un comportamento normalerelativo ai blocchi �nally. Come riportato dal sito:

�The reason lies in how �nally blocks are implemented by the compiler. The compilermust ensure that the cleanup code in lines 16-25 is always executed, whether or not thereis an exception thrown in the try block. There are thus two possible paths leading intothe �nally block: with and without an exception pending. Execute this example with aninvalid �lename input to simulate the failure situation and you will see a di�erence.However, it has to be said that it is not clear why javac assigns that implicit branch codeto line 16 and not, say, 14 (the exact behavior here is compiler-speci�c as well).�**Lerighe 16-25 si riferiscono a un blocco �nally di un esempio.

Da queste informazioni si è deciso di fare una prova eliminando il blocco �nally:

Adesso si è ottenuta una copertura del 96,6%, ritenendola un risultato soddisfacente. Simostrano i dettagli della copertura nella prossima �gura:

Figura 2.19: Dettaglio Copertura

Progetto Di Ingegneria del Software 33

CAPITOLO 2. SOFTWARE TESTING

Figura 2.1: Interfaccia Utente S-Quiz

Figura 2.2: Test JUnit

Figura 2.3: Crea nuova partita

Progetto Di Ingegneria del Software 34

CAPITOLO 2. SOFTWARE TESTING

Figura 2.4: Gestione Attività

Figura 2.5: Consolle Eclipse

Figura 2.6: Esecuzione con sonde

Progetto Di Ingegneria del Software 35

CAPITOLO 2. SOFTWARE TESTING

Figura 2.7: JUnit

Figura 2.8: EclEmma

Figura 2.9: Copertura EclEmma

Progetto Di Ingegneria del Software 36

CAPITOLO 2. SOFTWARE TESTING

Figura 2.10: Grafo dell Interfaccia Utente

Progetto Di Ingegneria del Software 37

CAPITOLO 2. SOFTWARE TESTING

Figura 2.11: Copertura e Esito

Figura 2.12: New Game

Progetto Di Ingegneria del Software 38

CAPITOLO 2. SOFTWARE TESTING

Figura 2.13: Number Compare

TC Precond Input O Attesi O Riscontrato PostCond EsitotestNumberCompare() - �10000� 1 1 - negativo

�01000�testNumberCompare() - �00000� -1 -1 - negativo

�10000�testNumberCompare() - �02000� 1 1 - negativo

�01000�testNumberCompare() - �00000� -1 -1 - negativo

�01000�testNumberCompare() - �00100� 1 1 - negativo

"00000"testNumberCompare() - "00000" -1 -1 - negativo

"00100";testNumberCompare() - "00010" 1 1 - negativo

"00000"testNumberCompare() - "00000" -1 -1 - negativo

"00010"testNumberCompare() - "00001" 1 1 - negativo

"00000"testNumberCompare() - "00000" -1 -1 - negativo

"00003"

Tabella 2.2: testNumberCompare

Progetto Di Ingegneria del Software 39

CAPITOLO 2. SOFTWARE TESTING

Figura 2.14: Copertura Number Compare

Figura 2.15: Copertura updateLadder()

Progetto Di Ingegneria del Software 40

CAPITOLO 2. SOFTWARE TESTING

Figura 2.16: White Box

Figura 2.17: Riesecuzione Test

Progetto Di Ingegneria del Software 41