progetto e realizzazione di un’infrastruttura di test per un sistema pacs
TRANSCRIPT
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
UNIVERSITÀ DEGLI STUDI DI TRIESTE
FACOLTÀ DI INGEGNERIA
Corso di Laurea specialistica in Ingegneria Informatica
Tesi di Laurea in
Prorgammazione Web
Progetto e realizzazione di un’infrastruttura di
test per un sistema PACS
Laureando Relatore
Giacomo Petronio Prof. Eric MedvetCorrelatore
Ing. Andrea Poli
Anno Accademico 2010-2011
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
Alla mia famiglia
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
Sommario
Introduzione ................................................................................................................................ 1
Motivazioni .................................................................................................................................. 2
Qualità del software..................................................................................................... 2
Software Testing .......................................................................................................... 2
Testare un PACS ........................................................................................................... 3
Marcatura CE ............................................................................................................... 3
Analisi .......................................................................................................................................... 6
Il sistema O3-DPACS ..................................................................................................... 6
Il processo attuale ........................................................................................................ 8
Teoria dei test ............................................................................................................ 13
Incidenza dei bug nel sistema .................................................................................... 15
Analisi delle classi e package...................................................................................... 17
Database Testing ........................................................................................................ 19
Test funzionali ............................................................................................................ 20
Tecnologie utilizzate .................................................................................................................. 22
JUnit ........................................................................................................................... 22
Classi Stub e Mock (Mockito) ..................................................................................... 24
DBUnit ........................................................................................................................ 27
Dependency Injection ................................................................................................ 27
Sviluppo ..................................................................................................................................... 30
Creazione di unit test ................................................................................................. 30
Database Testing (jdbc, stored procedure, jpa) ......................................................... 35
Creazione dei test di integrazione ed MBean ............................................................ 41
Test dei servizi ............................................................................................................ 44
Automazione ............................................................................................................................. 48
Script di build ed esecuzione automatici ................................................................... 48
Utilizzo di Jenkins ....................................................................................................... 49
Conclusioni ................................................................................................................................ 50
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
Risultati ottenuti ........................................................................................................ 50
Confronto ................................................................................................................... 50
Glossario .................................................................................................................................... 51
Bibliografia ................................................................................................................................. 51
Appendice .................................................................................................................................. 52
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
1
Introduzione
Lo scopo di questa tesi è quello di progettare e realizzare un’infrastruttura per migliorare il processo
di creazione ed esecuzione dei test in O3-Enterprise, con particolare attenzione sul programma
software O3-DPACS. Il raggiungimento di questo obbiettivo passa attraverso l’analisi del software
oggetto dei test, l’identificazione dei principali problemi che si vengono ad affrontare in un sistema di
tipo server, la ricerca di soluzioni e di pratiche comuni anche tramite l’utilizzo di strumenti appositi, la
creazione di test ed infine l’automazione della loro esecuzione. L’eventuale miglioramento ottenuto
viene quindi valutato mettendo a confronto il processo di test precedente con quello proposto.
Nota: mi scuso per le innumerevoli occorrenze della parola ‘test’
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
2
Motivazioni
Spesso, programmando sia per scopi personali che professionali, ci si ritrova a creare ed effettuaredei test senza porsi particolari domande sulla reale utilità o necessità di impiegare del tempo per
questo tipo di operazioni. Pur sembrando ragionevolmente ovvio che i test debbano essere effettuati
in quanto necessari per verificare il corretto funzionamento dell’applicazione, non è altrettanto
lampante quale sia la giusta quantità di test a cui sottoporre il software. Si ritiene quindi lecito
interrogarsi su quante risorse sia opportuno impiegare nella fase di test, e se l’investimento avrà un
reale ritorno e di che tipo.
Testare un programma è un processo lungo che non è a costo zero. I test vanno innanzitutto creati,
eseguiti, e ne vanno verificati i risultati; il tutto va poi rieseguito più volte nel corso della vita di un
progetto. Per ottenere tutto questo è necessario quindi allocare tutta una serie di risorse preziose edi diverso tipo: tempo, conoscenza (test vengono creati da persone che hanno conoscenza del
software) ed esperienza (esistono figure professionali che fanno dei test la loro specialità). Come se
non bastasse, tutti i test che vengono creati nel tempo, pongono l’ulteriore problema della
manutenzione che riguarda sia il software oggetto di verifica che i test stessi. Un test che non viene
aggiornato di pari passo con il software, diventa un test inutile con relativo spreco di risorse. Da
questo generico quadro della situazione si può intuire il fatto che il processo di test ha un costo non
irrilevante. Per quale motivo quindi uno sviluppatore, ed a maggior ragione un’azienda, dovrebbe
decidere di investire sui test?
Di seguito vengono esposte tre motivazioni, partendo da quella più generica valida per qualsiasisoftware, arrivando a quella più pratica, valida per un azienda come O3-Enterprise che crea
dispositivi medici.
Qualità del software
Come si è detto, lo scopo dei test è riassumibile nel concetto di miglioramento della qualità del
software. Questo concetto, pur essendo a prima vista astratto, ha un valore molto importante che
può assumere diversi aspetti; nel caso di un’azienda, questi si riconducono tutti prima o poi ad un
mero valore economico. Più la qualità del software è alta, più alto è il valore stesso del programma.
Come si può, allora, calcolarne il valore?
Non è possibile calcolare il livello assoluto della qualità del software tramite misurazioni dirette, per
questo motivo si procede con un approccio differente. Ci si può chiedere invece che cos’è che fa
diminuire la qualità di un software; siccome il numero degli errori del software (o almeno quelli di cui
si è a conoscenza) è un parametro che può essere calcolato, ed essendo questi errori portatori di una
diminuzione della qualità del software, allora si può affermare che il software con il minor numero di
errori è un software generalmente migliore di uno con più errori (a parità di funzionalità).
Software Testing
Il “software testing” è un metodo empirico di investigazione per ottenere informazioni sulla qualità
del prodotto. Tale metodo può essere utilizzato per ottenere informazioni di vario tipo. Essoconsente di avere una visione sulla presenza o meno di bug (errorei nel software); sulla effettiva
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
3
conformità a degli standard che il software dovrebbe essere in grado di gestire; sullo stato di
avanzamento del progetto, evitando rilasci prematuri dovuti a componenti software non abbastanza
robusti o addirittura mancanti; sui limiti del software stesso e sui requisiti hardware, tramite l’utilizzo
di stress-test.
Testare un PACS
Oltre alle motivazioni valide per qualsiasi tipo di programma software, per i programmi di tipo PACS,
ed in generale per qualsiasi programma ospedaliero, sono valide delle ulteriori motivazioni per
investire sui test. I programmi informatici ospedalieri seguono delle linee guida dettate da
organizzazioni internazionali (principalmente IHE) composte sia da utenti che da produttori, che
hanno lo scopo di armonizzare i diversi programmi che solitamente coesistono all’interno di uno o
più sistemi informativi ospedalieri, e lo fanno incentivando l’utilizzo di standard condivisi e procedure
comuni (DICOM, HL7, SOAP). All’interno di un sistema informativo più grande infatti, ve ne sono
diversi che hanno la necessità di condividere dati anagrafici, clinici e diagnostici dei pazienti. Lo
scambio di dati viene quindi facilitato indicando taluni protocolli di comunicazione e standardpiuttosto che altri, in maniera tale da spianare la strada ai produttori di software che si trovano già
con delle specifiche, seppur generiche, da cui partire, e che consentono di poter avere un certo grado
di confidenza sul fatto che il loro prodotto sarà capace di interfacciarsi con prodotti terzi. O3-DPACS
non si sottrae a tutto questo discorso, ed anzi trova nei protocolli e negli standard indicati, dei
requisiti contro cui può e deve essere testato.
Marcatura CE
Il programma O3-DPACS, come accennato, è un software ospedaliero, classificato a tutti gli effetti
come dispositivo medico in quanto utilizzato per effettuare diagnosi, e come tale per poter essere
commercializzato in Europa, deve possedere dei requisiti minimi di qualità e di sicurezza, garantiti
della marcatura CE.
I dispositivi medici sono raggruppati in quattro classi che vanno da un livello minimo ad un livello di
massimo rischio per il paziente fino alla morte, e sono le classi I, IIa, IIb, III. L’attribuzione ad una di
esse dipende dalla destinazione d’uso indicata dal produttore, e può variare a seconda delle
peculiarità del dispositivo.
La classificazione dei sistemi PACS è argomento controverso in quanto non solo essi sono di difficile
collocazione all’interno delle quattro tipologie, ma la classificazione stessa può variare a seconda
delle caratteristiche della particolare implementazione sotto esame.Per facilitare la loro classificazione, la comunità europea ha pubblicato delle linee guida per i
dispositivi medici “borderline”, secondo le quali a seconda delle funzionalità offerte, un PACS può
ricadere soltanto nelle prime tre classi. Il motivo per il quale questa classificazione è importante, è
che per i dispositivi a partire dalla seconda classe in poi, è necessario l’intervento di un ente terzo che
autorizzi il produttore ad apporre la marcatura CE. Secondo queste linee guida, il sistema O3-DPACS
rientrerebbe nella classe I, per la quale la marcatura potrebbe essere assegnata in autonomia. È
altresì vero che nei bandi di gara europei non è raro che tra i requisiti che le aziende debbano
possedere, vi sia una certificazione del sistema qualità.
La ditta O3-Enterprise produce anche dispositivi di classe II (workstation radiologiche), per i quali ènecessaria la verifica della qualità del processo di creazione dei software della ditta. La certificazione,
ottenuta tramite ente terzo predisposto, valuta esclusivamente la qualità del processo e non del
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
4
prodotto finale. Per questo l’azienda ha creato dei protocolli da seguire rigidamente in modo da
rendere tale processo trasparente e valutabile. Poiché queste linee guida si applicano a tutti i
prodotti dell’azienda, anche la creazione di O3-DPACS dovrà seguire lo stesso procedimento di
controllo. Ovviamente la certificazione può essere concessa o meno in base al giudizio che viene dato
al processo utilizzato per lo sviluppo del software. La definizione del processo, pur non essendo
vincolata rispetto ad una normativa specifica, trova in diverse normative europee delle linee guida su
cui è consigliabile basarsi, e che se seguite possono garantire una maggiore probabilità che il
processo venga certificato. La norma di riferimento per i dispositivi medici è la ISO 13485.
La ISO 13485 è una norma che specifica i requisiti per i sistemi di gestione della qualità che
permettono ad una organizzazione di dimostrare la sua capacità di fornire dispositivi medici che
siano conformi ai requisiti regolamentari applicabili a tali dispositivi medici. È basata sulla ben più
nota EN ISO 9001:2000 ma con delle modifiche riguardanti la parte di “soddisfazione del cliente” e al
“miglioramento continuo”.
Essendo una norma generale che si riferisce a dispositivi medici anche molto diversi tra loro, si deve
individuare quale parte della norma sia applicabile al processo di test in questione . La parte relativa
alla pianificazione della realizzazione del prodotto richiede esplicitamente che siano definite delle
attività di verifica, convalida, monitoraggio, ispezione e prove specifiche sul prodotto. Queste attività
devono produrre dei risultati che devono essere conservati e sono necessari a fornire evidenza che i
prodotti soddisfino i requisiti. Nella sezione relativa al controllo dei dispositivi di monitoraggio e
misurazione si richiede che l’organizzazione individui un sistema di monitoraggio e misurazione da
effettuare al fine di fornire evidenza sulla conformità dei prodotti rispetto ai requisiti, ed assicurarne
l’oggettività dei risultati. Ed ancora nella parte dedicata alla fase di design e sviluppo del prodotto,
viene richiesto che i risultati di questa fase, che hanno sempre lo stesso fine dell’assicurare che il
prodotto soddisfi i requisiti prefissati, siano documentati e conservati per dimostrare che il prodottosia stato effettivamente verificato. Infine, nell’attività di misura dell’efficacia della qualità del
sistema, la norma prevede che queste attività, fra le quali rientrano i test, devono essere descritte
includendo il metodo utilizzato, il criterio di accettazione o rifiuto, l’ambiente in cui sono eseguiti, i
dati di test utilizzati, i risultati ottenuti.
La ISO 13485 non è però l’unica norma che tratta di dispositivi medici, ve ne sono molte altre, ma di
sicuro interesse per quanto riguarda lo sviluppo di software per dispositivi medici vi è la CEI EN
62304. Questa norma descrive il processo relativo al ciclo di vita del software ed al suo interno si fa
esplicita menzione al sistema di test. In particolare la parte di testing del sistema software
approfondisce le norme già descritte nella 13485 per quanto riguarda i risultati derivanti dal design edallo sviluppo e successiva verifica.
La norma introduce il concetto di unità software nel processo di sviluppo del programma, e richiede
che il produttore definisca dei metodi e delle procedure per la verifica di queste unità, e che queste
verifiche siano effettuate attraverso l’esecuzione di test. Ciascuna verifica, inoltre, deve essere
validata secondo un criterio di accettazione definito a priori. Tra i criteri menzionati vi sono:
Eventi eseguiti con una sequenza predefinita
Allocazione di risorse in misura prevista
Corretta gestione degli errori
Inizializzazione delle variabili Condizioni al confine
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
5
È importante notare che è richiesto che alla termine di questa fase, i risultati dei test vengano
conservati.
Ciascuna unità software, al termine dello sviluppo e successiva verifica, deve essere integrata nel
sistema nel suo complesso. In questa fase vanno definite altre procedure di verifica, questa volta atte
ad assicurare che con l’integrazione dell’unità software non siano stati introdotti difetti nel softwareintegrato in precedenza (regression testing).
Di tutti i test definiti ed eseguiti, il produttore deve essere in grado di fornire il risultato dei test
(successo, fallimento e lista di eventuali anomalie), una documentazione sufficiente che consenta di
ripetere il test, e l’identità di chi ha eseguito il test.
L’insieme delle unità software integrate nel sistema vanno a comporre il programma completo, al
quale il produttore deve prevedere un ulteriore set di test indispensabili per verificare che tutti i
requisiti del software siano stati coperti.
In conclusione, quello che si evince da queste normative è che il miglioramento del processo di test
(creazione, esecuzione, verifica) assume un’importanza chiave al fine della marcatura CE. Creare
un’infrastruttura per O3-DPACS che faciliti il test di porzioni di software che presentano difficoltà
nella loro definizione dovuti alla particolarità dell’ambiente server su cui il programma viene
eseguito, non si limita a migliorare la qualità intrinseca del prodotto, ma è anche un tassello
fondamentale per la certificazione del sistema qualità di O3-Enteprise.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
6
Analisi
Il sistema O3-DPACS
Introduzione
Il programma oggetto dei test di questa tesi, O3-DPACS, è come già anticipato, l’implementazione di
un sistema PACS “Picture Archiving and Communication System”, ovvero un gestore di immagini
medicali, con finalità di archiviazione, trasmissione e visualizzazione delle immagini diagnostiche
digitali. I file che vengono gestiti all’interno del sistema PACS sono in formato DICOM; esso è uno
standard che definisce sia il formato delle immagini digitali che il protocollo di comunicazione atto a
inviare e ricevere immagini, oltre che ad effettuarne la loro ricerca. In un tipico caso d’uso, i file
DICOM vengono creati dalle modalità diagnostiche (TAC, ecografie, etc.) ed inviati al PACS che le
archivia e le rende disponibili per la consultazione. La consultazione, tipicamente remota, avviene
tramite l’utilizzo di workstation di refertazione, le quali cercano e recuperano le immagini dal PACS; il
tutto avviene utilizzando il protocollo di comunicazione e formato dei file DICOM. Le funzionalità
tradizionali di un PACS sono quindi:
Acquisizione dei file DICOM prodotti dalle modalità diagnostiche
Archiviazione, per la gestione delle informazioni sulle immagini acquisite
Indirizzamento dei dati verso le stazioni che lo richiedono (informazioni e immagini)
A queste funzionalità va aggiunta anche il servizio di “Worklist”, ovvero la gestione degli
appuntamenti, sempre tramite DICOM.
Oltre alle funzionalità base, O3-DPACS offre una serie di servizi secondari indispensabili, dedicati
all’integrazione con i sistemi informativi ospedalieri in cui viene installato. Queste integrazioni sono
rese possibili grazie all’adozione di un protocollo molto diffuso negli ambienti ospedalieri, HL7.
Questo protocollo è lo standard de-facto per lo scambio dei dati clinici fra sistemi informativi diversi.
I principali servizi offerti da O3-DPACS ed implementati tramite HL7 sono:
Aggiornamento anagrafica pazienti
Riconciliazione dei pazienti1
Inserimento ordini
Gestione visite
Un’ulteriore integrazione offerta da O3-DPACS è data dalla possibilità di pubblicare in un sistema
centrale di condivisione di documenti, un particolare tipo di file DICOM (“Key Object Selection”)
tramite web-services. Questo file contenente riferimenti ad altre immagini DICOM, rende noto al
sistema di integrazione di livello superiore, che nel PACS vi sono le immagini relative all’esame del
paziente di turno, e che sono disponibili per il loro recupero (IHE XDS-I).
Per gestire le diverse configurazioni e per navigare tra i contenuti del PACS, vi è anche un apposita
applicazione web che comunica con i servizi del PACS e ne può pilotare il comportamento. Questa
1In un sistema informativo può capitare che vi siano due entità paziente che si riferiscono alla stessa persona
fisica. Il procedimento che riconduce le due entità in una sola viene chiamato riconciliazione
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
7
interfaccia web è in grado di effettuare operazioni di base quali la ricerca tra contenuti, visualizzare
immagini, gestire utenti e ruoli, e alcune operazioni di manutenzione.
Fino a qui sono state descritte le funzionalità macroscopiche di O3-DPACS da un punto di vista dei
casi d’uso. Da questo elenco però sono stati tralasciati i dettagli implementativi in quanto sono stati
oggetto di analisi approfondite e che vengono esposti brevemente di seguito per dare un ideagenerale della varietà di tecnologie coinvolte nel progetto; questi dettagli verranno poi descritti con
maggiore accuratezza nelle rispettive parti in cui esporrò l’approccio utilizzato per implementare i
casi di test.
Tecnologie coinvolte
O3-DPACS è un’applicazione server, scritta in Java, che viene fatta eseguire all’interno di un
“Application Container” per Java Enterprise Edition, in particolare JBoss (4.2 e 5.1).
La parte di comunicazione tramite protocollo DICOM è implementata estendendo le funzionalità
offerte dalle librerie open-source “dcm4che”, le quali offrono anche gli strumenti per la
manipolazione dei file in formato DICOM. Queste librerie nascondono parte del protocollo a più
basso livello (gestione dei socket sia client che server, e il parsing dello stream di dati).
L’altro protocollo di comunicazione esplicitamente creato per lo scambio di dati clinici è HL7. Per la
gestione di questo canale di comunicazione il PACS sfrutta la libreria “hapi”, che similmente a quanto
avviene con le dcm4che, fornisce un livello di astrazione utile per evitare la gestione dei socket e la
manipolazione dello stream dati.
I servizi web esposti per l’integrazione con XDS utilizzano invece una libreria scritta appositamente
dal team di O3, condivisa con altri progetti; la gestione delle connessioni per i web service trova
ausilio nelle librerie “httpClient” di Apache, manipolando quindi direttamente i messaggi SOAP.L’applicazione web per fornire l’interfaccia utente utilizza la tecnologia JSF (Ja va Server Faces), al cui
vertice vengono eseguiti componenti di tipo RichFaces. La visualizzazione delle immagini è stata
recentemente rivista e si basa invece sul framework Adobe Flex.
Tutte le informazioni che vengono gestite da O3-DPACS vengono immagazzinate in un DBMS. Il PACS
è in grado di funzionare sia utilizzando DBMS Oracle che MySql. La possibilità di utilizzare uno o
l’altro, come verrà spiegato in seguito, comporta un notevole sforzo in termini di programmazione e
conseguentemente anche di creazione dei test. Le comunicazioni tra applicazione e DBMS avvengono
con metodi diversi: query composte anche a runtime ed eseguite tramite JDBC; stored procedure
richiamate sempre tramite JDBC; utilizzo di Hibernate come framework ORM (Object RelationalMapping).
La gestione dei singoli servizi del PACS, tra cui la loro configurazione e ciclo di vita, è stata
implementata con JMX; i diversi MBean che rappresentano i servizi, espongono metodi per la loro
gestione. Le implementazioni vere e proprie dei servizi fanno invece largo uso di Enterprise Java
Bean.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
8
Questa breve ma intensa carrellata di tecnologie utilizzate da O3-DPACS (non esaustiva) ha lo scopo
di evidenziare la quantità e la varietà di strumenti adottati nel sistema. Questo fatto ha avuto un
impatto non trascurabile, in quanto una buona parte del tempo è stata impiegata per il lavoro di
analisi delle diverse componenti, requisito fondamentale per poi costruire, laddove possibile, delle
pratiche, o addirittura dei piccoli framework, per creare i test veri e propri.
Il processo attuale Viene ora descritto quello che è il tipico processo di test utilizzato in O3-Enterprise per il programma
O3-DPACS, ma che viene applicato ad ogni progetto all’interno della ditta . Il processo è documentatoin dettaglio nel manuale di qualità, e viene seguito fedelmente in quanto anche da questo dipende la
certificazione ISO 13485. Ogni intervento (o caso, in inglese ‘issue’) su di un programma deve passare
attraverso una serie di stati, a partire dall’approvazione da par te del technical manager, che ne
valuta le motivazioni. Il caso, se ritenuto necessario, viene assegnato ad uno sviluppatore, il quale
come primo compito ha quello di effettuare l’analisi del problema e redigere un documento.
Dall’analisi si passa alla stesura del design dopo approvazione del documento da parte del capo
progetto, che dovrà approvare anche il documento di design. Solo a questo punto lo sviluppatore
potrà iniziare a scrivere il codice vero e proprio su di un branch del progetto (il branch in un sistema
di versionamento del codice è un ramo della linea principale, chiamata trunk). Al termine della
scrittura del codice, si passa alla fase di test. I test vengono inseriti durante ciascuna di queste fasi,
ma vi è il vincolo che per ogni requisito individuato nella fase di analisi, vi sia almeno un test
corrispondente. Se la fase di test si conclude positivamente, il caso viene marcato come pronto per
essere integrato nel sistema. Durante l’integrazione, che viene sempre svolta dal project manager, il
codice prodotto dallo sviluppatore per il caso in oggetto e presente nel branch del sistema di
versionamento, viene portato nella versione corrente del progetto (nel ‘trunk’), e vengono rieseguiti
tutti i test definiti per quell’issue.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
9
Col passare del tempo il progetto viene modificato e gli issue integrati si accumulano. Quando viene
deciso che il programma è pronto per essere rilasciato (secondo politiche aziendali), gli viene
assegnata una versione, e vengono rifatti tutti i test definiti in ciascun issue integrato a partire
dall’ultimo rilascio. Per procedere con il rilascio, vi sono degli ulteriori test obbligatori che vannosvolti per verificare le funzionalità fondamentali del programma (una sorta di regression test); infine
viene scelto un campione di test da issue datati (di rilasci precedenti) in maniera casuale.
È interessante notare che ciascun test inserito, viene eseguito un minimo di tre volte durante il ciclo
di vita dell’applicazione. Ovviamente durante la fase di sviluppo, i test molto probabilmente vengono
effettuati anche molte volte, a seconda del giudizio dello sviluppatore.
Dall’analisi del sistema di “bug tracking” utilizzato in O3, sono state estratte delle informazioni
relative all’andamento del numero di test in relazione a ciascuna versione e tempi di rilascio.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
10
Versione release date # issue # test media test/issue 1.5 06/09 12 0 - 1.6 09/10 40 50 1.25 1.7 09/10 9 21 2.3 1.7.1 10/10 1 1 - 1.7.2 10/10 1 1 -
1.8 05/11 24 57 2.35 1.8.1 06/11 3 3 1 1.9 11/11 5 26 5.2
Tabella 1 - Analisi storica dei test
Nota: le versioni a tre cifre non fanno parte del ciclo programmato dei rilasci, ma sono state create
per risolvere in velocità dei bug importanti; il numero di issue e test relativi sono bassi per questo
motivo. Inoltre la prima versione rilasciata (la 1.5) è stata fatta quando ancora non c’era un processo
di qualità definito, da cui la presenza dello zero nel numero dei test creati!
Sebbene i numeri siano bassi, si possono comunque notare delle tendenze:
Il numero di test per issue è in aumento La frequenza dei rilasci aumenta
Dalla somma di questi due fattori se ne ricava che in futuro sarà richiesto di eseguire sempre più
spesso un numero maggiore di test. Da qui un ulteriore conferma dell’esigenza di un sistema più
efficiente che possa essere d’aiuto per rendere questo processo più rapido.
Pro e contro del metodo attuale
Dall’analisi del processo di testing in uso si è cercato di cogliere quali sono i punti di forza,
valorizzandoli quanto possibile, e quali sono invece le debolezze, proponendo soluzioni che possano
essere integrate nel sistema attuale.
Regression test
Una prima osservazione è possibile farla sui regression test. I test di questo tipo hanno lo scopo di
verificare che una modifica sul codice non abbia compromesso funzionalità non direttamente
collegate alla parte sottoposta a miglioramento. Nel metodo attuale i regression test individuati sono
quelli eseguiti ad ogni rilascio, e comprendono sia quelli definiti come obbligatori, sia quelli scelti a
caso tra i test degli issue più vecchi. Questo approccio ha sicuramente la sua validità, ma il punto
debole è che vengono eseguiti solamente ad ogni rilascio, evento con frequenza bassa (circa 2 rilasci
annui programmati). L’eventuale aumento della frequenza dei rilasci permetterebbe sì di effettuare
regression test più spesso, ma richiederebbero troppo tempo in quanto alcuni di questi test sonoanche di difficile esecuzione, e mancano completamente di automatismi.
All’approccio corrente va imputato un secondo punto a sfavore. I test designati come obbligatori ad
ogni rilascio non riescono a coprire in maniera adeguata tutte le funzionalità. Riuscendo a creare dei
test automatici, la parte di codice verificata con i regression test potrebbe aumentare di molto senza
incidere troppo sul tempo impiegato per la loro esecuzione. Eventuali test automatici, inoltre,
potrebbero essere eseguiti molto più spesso, senza dover aspettare il rilascio, ma potrebbero ad
esempio essere eseguiti anche ad ogni integrazione di un issue.
Unit test
I test che vengono definiti per ciascun issue non sono quasi mai di tipo unit test. Questa particolare
tipologia di test viene utilizzata per verificare le funzionalità di singole unità logiche di codice, spesso
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
11
trovando corrispondenza nella definizione di un singolo metodo di una classe. Lo scopo è quello di
accertarsi che una classe esponga dei metodi che facciano esattamente quello che ci si aspetta dalla
loro definizione. Per come è stato pensato il processo esistente, questo tipo di test viene
completamente ignorato. Dai colloqui avuti con agli sviluppatori di O3, è emerso che è pratica
comune creare unit test durante la fase di programmazione, per esempio creando metodi Main
all’interno delle classi in cui viene verificato il comportamento della classe stessa. Purtroppo però
questo codice non viene versionato e i test vengono persi. La definizione di una pratica comune che
indichi come creare questo tipo di test, magari utilizzando un framework apposito come JUnit,
comporterebbe, a fronte di uno sforzo minimo, il salvataggio di questi test che possono essere
facilmente resi automatici e rieseguibili a piacimento.
Scripted testing
La maggior parte dei test che vengono creati in O3-Enterprise rientrano invece nella categoria “test
script” (un'altra etichetta che viene utilizzata per definire questo tipo di test è “checklist test”). Un
test così definito è composto da una serie di istruzioni scritte che devono essere eseguite sul sistemasotto test per verificarne il funzionamento. Quello che contraddistingue questo tipo di test è che le
istruzioni sono scritte in maniera informale, e l’esecuzione non è automatizzata ma destinata ad una
persona che deve eseguire le istruzioni secondo quanto scritto. Questi test non scendono quasi mai
al di sotto di un certo livello di dettaglio, e quello che testano sono principalmente dei casi d’uso del
programma. Per creare un test di questo tipo va specificato:
Ambiente di esecuzione (compreso lo stato iniziale del sistema)
Una serie di istruzioni da eseguire in sequenza
Un risultato aspettato
Analizzando questo tipo di approccio si identificano due fasi principali: progettazione del test edesecuzione del test. Ciascuna di queste fasi presentano le seguenti criticità.
Esecuzione
L'esecutore del test deve comprendere l'intento di chi ha scritto il test. L'intenzione del
creatore del test non è sempre esplicita nella descrizione e va quindi compresa dal contesto.
Se non c'è la comprensione dell'intento reale del test, allora l'esecuzione del test diventa una
mera esecuzione di istruzioni (il che non è sempre male, ma la potenzialità di un test creato
ed eseguito da una persona può essere sfruttata molto meglio, per i test automatici si
possono sfruttare le altre tecniche oggetto della tesi)
Design
Colui che deve scrivere il test deve essere in grado di indovinare con una certa precisione il
livello di conoscenza del tester che eseguirà il test. La scrittura di test richiede pazienza,
bravura nello scrivere, un livello minimo di empatia con l'esecutore del test (che talvolta è
sconosciuto). Questo è un processo tipicamente noioso, lo sviluppatore non è invogliato a
scrivere test ed una immediata conseguenza è la cattiva qualità dei test stessi.
Nel caso di applicazioni complesse, per fare in modo che un tester sia in grado di eseguire un test, a
meno che non sia lui stesso uno degli sviluppatori dell'applicazione, è necessario fornire una
descrizione molto dettagliata dei passi da eseguire, a livello anche molto basso. Es.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
12
1. Mettere un breakpoint nella classe X alla riga Y e poi alla riga Z
2. Lanciare l'applicazione in debug
3. Al punto Y verificare che il valore della variabile A sia diversa da null
4. Proseguire facendo l’operazione P
5. Al punto Z verificare che il valore della variabile A sia pari al valore contenuto nella colonna C
della tabella T con chiave primaria K.
Questo tipo di descrizione di test può sembrare estremo, ma ci sono casi in cui è necessario e viene
effettivamente utilizzato.
Un test così fatto presenta diversi problemi. Un primo problema è che nel momento in cui il codice
verrà modificato, la descrizione del test diverrà senza senso (le righe di codice in cui mettere i
breakpoint non corrisponderanno più). Se la modifica riguarda porzioni di codice ampio con relativo
refactoring del codice (variabili rinominate, o metodi spostati da una classe all'altra), allora l'intero
test avrà perso di significato.
Un ulteriore problema è dato dal fatto che con test di questo tipo il tester non acquisisce nessuna
conoscenza dell'applicazione, né aumenta la sua abilità nel testare.
Non ci sono però solo fattori negativi in questo tipo di test, che invece è uno strumento di verifica
con potenzialità molto elevata. La capacità di una persona che legge il test e lo esegue, permette
l’esecuzione di test anche molto complessi in tempi relativamente brevi. Questo è tanto più vero
quante più operazioni di tipo diverso tra loro sono richieste dal test. Si pensi anche ad esempio a ai
test necessari per verificare che l’applicazione web abbia l’aspetto voluto. Probabilmente prima o poi
si potrebbe arrivare alla definizione di un test automatizzato che riesca a fare la stessa cosa, ma con
tempi estremamente alti, e con una fragilità altrettanto alta. È invece molto più rapido e
probabilmente anche molto più affidabile relegare questo tipo di verifiche ad una persona che è in
grado di giudicare se i requisiti sono soddisfatti o meno.
Oltre alle interfacce, test di questo tipo sono indispensabili laddove le componenti coinvolte sono
numerose e di tipo anche molto diverso tra loro. Generalmente si tratta di test di integrazione a più
alto livello in cui la funzionalità testata coinvolge programmi esterni con cui il sistema deve
comunicare. Test di integrazione si trasformano in test dei casi d’uso, dove prima o poi si dovranno
testare le funzioni dell’applicazione dall’inizio alla fine, senza ricorrere a strumenti che simulano
componenti esterne, cosa che come spiegherò, è un requisito quasi fondamentale per l’automazione
dei test.
Per sfruttare meglio questo sistema è quindi necessario fare una riflessione sull’obbiettivo di ogni
singolo test. Va quindi evitato di scrivere dei script-test con un livello di dettaglio troppo elevato otroppo specifici (unit test), in quanto troveranno applicazione nei sistemi di automazione proposti
nella tesi; va invece preferito questo tipo di test laddove l’automazione è di difficile realizzazione.
Ripetibilità dei test
Un ultima considerazione sul processo esistente va fatta sulla ripetibilità dei test, intesa sia come
difficoltà nel ripetere un test, sia come probabilità che un test venga rieseguito più volte. Gli attuali
test sono definiti tutti nella stessa maniera (script-test), sia che essi vengano eseguiti con una certa
frequenza (come ad esempio i regression test), sia che la loro utilità si esaurisca all’interno dell’issue
in cui vengono definiti. La mia proposta mira a catalogare i test in queste due macro tipologie. Il
lavoro di creazione di test e loro automazione si concentrerà quindi sui test ad elevata ripetibilità.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
13
All’interno poi di questa grande categoria, andrò a distinguere ulteriormente i test in base ad altri
criteri che vengono esposti di seguito.
Teoria dei test
Definizione
Il software testing viene definito come il “processo di operare un sistema o una sua componente
sotto particolari condizioni, osservando o registrando i risultati, e valutando alcuni aspetti del sistema
o della componente” (IEEE standard 610.12-1990).
È una tecnica che tipicamente da indicazioni su come effettuare le seguenti operazioni:
Analizzare la situazione di partenza
Modellizzare lo spazio dei test
Decidere quali parti del sistema coprire
Determinare le discriminanti per il successo/fallimento (oracoli)
Configurare il sistema di test
Eseguire il sistema
Osservare il sistema
Valutarne i risultati
Da questa lista sintetica si ricava la metodologia descritta di seguito per creare un test.
Un programma può essere immaginato come una collezione di variabili in ingresso e in uscita, ed è
necessario analizzare quali sono i valori che possono assumere. A partire da questi valori, si procede
applicando un modello di campionamento che separi tutti i possibili valori in diversi gruppi a seconda
della loro capacità a far fallire il programma in esame. Per ogni variabile, dividerne i possibili valori ingruppi di equivalenza. Creare un test prendendo almeno un valore da ciascun gruppo così
determinato.
Sarà poi necessario decidere quali combinazioni di variabili sono da considerare. Si devono decidere
le condizioni finali del sistema in base alle quali è possibile concludere che un test è riuscito o è
fallito. Descrivere la configurazione del sistema e dell’ambiente in cui esso viene fatto eseguire. Solo
a questo punto è possibile eseguire il test, osservarne il comportamento e valutare il successo dal
risultato.
Tipi di test
In letteratura si usa catalogare i test in base al loro scopo e destinazione d’uso. Di seguito vengono
illustrati i 5 tipi di test più utilizzati. Esistono ovviamente anche altre categorie, che vengono ricavate
secondo i criteri più diversi, ma ritengo che quelle che seguono sono di gran lunga quelle più
riconosciute dai maggiori testi che trattano dell’argomento e dalle risorse in rete.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
14
In questa suddivisione, il criterio è una miscela tra l’oggetto sottoposto a verifica e lo scopo della
verifica. Man mano che ci si muove dal livello più basso a quello più alto, i test diventano più
funzionali e richiedono che porzioni sempre maggiori dell’applicazione siano presenti fino ad arrivare
alle due categorie più estese dove si verifica il programma nella sua totalità.
Unit test
Lo scopo principale degli unit-test è verificare che l’applicazione si comporti come da requisiti e
scovare difetti nel codice nelle primissime fasi di sviluppo. Anche se i test di altro tipo come i test
funzionali perseguono gli stessi obbiettivi, gli unit-test offrono altri vantaggi per i quali vengono
scelti:
Maggiore copertura del codice rispetto a test funzionali
Incoraggiano il refactoring
Individuano regressioni
Documentano il comportamento voluto
Introducono delle metriche di misura del codice
Gli unit test permettono una copertura del codice non raggiungibile con altri sistemi. Questa è una
possibilità che deve essere sfruttata laddove ve ne sia una reale necessità. La copertura del 100% del
codice è un obbiettivo che comporta un notevole impiego di risorse, con un ritorno in termini di
efficacia discutibile. Vi sono però dei casi in cui una copertura il più ampia possibile di porzioni di
codice particolarmente sensibili è da ricercarsi. Unit test hanno anche il vantaggio di riuscire a
simulare condizioni di errore che sono altresì molto difficili da ottenere con test funzionali.
Essendo tra i primi utilizzatori del codice scritto, gli unit-test mettono per primi in evidenza eventuali
difetti nell’architettura del codice. Scrivere test costringe lo sviluppatore a creare codice facilmente
testabile, isolato (basso accoppiamento), e con delle API (interfacce di programmazione) chiare edesplicative.
Una serie di test creati per una classe è anche un efficace metodo per documentare il
comportamento voluto della classe e un valido esempio di utilizzo di quella classe.
Anche per gli unit test si possono individuare delle categorie di test, distinguibili secondo un criterio
che verrà utilizzato durante la creazione dei test per O3-DPACS. Queste categorie si differenziano per
i “confini” del codice sotto test.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
15
Tipo di test Descrizione
Test di unità logiche Test che si focalizza su un singolo metodo. I confini possono esserecontrollati utilizzando metodi quali la creazione di Mock e Stub
Test di integrazione di unità Test che si concentra sull’interazione tra diverse unità logiche. Il numero
di unità coinvolte può variare fino a coinvolgere anche componenti ditipo diverso (DBMS, file system, network)
Test funzionale di unità Test che estende i suoi confini fino a coinvolgere stimoli esterniall’applicazione e verificare la reazione del programma. La definizione di
questo tipo di test si basa sui casi d’uso
Tabella 2 - Tipi di unit-test
L’interazione fra i diversi tipi di test sono illustrati meglio nella seguente illustrazione. L’utilizzo di
tutti e tre i tipi consente di coprire bene l’applicazione e conferire maggiore confidenza quando si
tratta di fare dei cambiamenti.
Esistono altri due tipi di test molto utilizzati, ma che non rientrano nello scopo della tesi e che includo
per completezza. Questi sono stress-test e test di accettazione. I primi vengono utilizzati per
conoscere quali sono i limiti strutturali dell’applicazione, come ad esempio il numero di utenti
contemporanei che il programma è in grado di servire con prestazioni accettabili, su di un
determinato hardware. Il secondo tipo di test viene invece utilizzato quando vi è un committente che
paga per il prodotto che si sta sviluppando ed è lo strumento decisionale per capire se sono stati
soddisfatti i requisiti del cliente. Questi test sono spesso dei test di casi d’uso e di performance, ma
non escludono anche test più soggettivi come la valutazione dell’aspetto dell’interfaccia. È
importante notare che i test di accettazione non vengono eseguiti dal team di sviluppo ma dal cliente
stesso.
Incidenza dei bug nel sistema
Prima di proseguire con la progettazione di quello che sarà il sistema di test da realizzare, si è cercato
di capire se esistono delle parti di programma più esposte ad errori di altre su cui concentrare gli
sforzi, ed è stato fatto andando a vedere lo storico dei bug degli ultimi rilasci.
O3-Enterprise utilizza un sistema di tracciabilità dei difetti (infelice traduzione personale di “bug-
tracking system”) per registrare tutti gli eventi legati al software, inclusi quindi i bug scovati e loro
stato di risoluzione.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
16
Dal lavoro di ricerca è emersa la tabella presente in appendice, dalla quale sono stati estratti i
seguenti dati riguardanti l’andamento generale dei difetti segnalati.
Nota sulla classificazione dei bug:
Minor: sono errori che non pregiudicano il funzionamento del sistema la cui risoluzione può
essere rimandata
Major: difetti del software che vanno risolti quanto prima ma che non pregiudicano il
funzionamento globale
Critici: compromettono il funzionamento di almeno una parte fondamentale del programma
ed hanno la priorità massima
PACSCORE PACSWEB WADO totale
Minor Major Critical Minor Major Critical Minor Major Critical Minor Major Critical
2011 6 2 0 12 0 0 4 0 0 20 4 0
2010 14 7 1 4 1 4 3 1 0 21 9 5
2009 6 5 2 5 4 2 2 2 1 13 11 5
2008 0 4 0 0 5 0 0 0 0 0 9 0
Tabella 3 - Analisi storica dei bug
Osservazioni:
Tra il 2009 e 2010 il numero dei bug critici e major è rimasto praticamente invariato. Sono
aumentati i bug minor.
Tra il 2010 e 2011 non è emerso nessun bug critico, e i major sono stati dimezzati. Il numero
dei bug minor è rimasto alto. Nel 2008 il sistema di bug tracking era ancora ai primordi quindi non può far testo.
Il dato più rilevante è che il numero dei bug minor è sempre alto. Difetti di questo tipo sono da
imputarsi all’introduzione di nuove funzionalità del sistema. I controlli effettuati sui casi d'uso più
critici hanno raggiunto un buon livello di efficacia, rimane invece basso il livello sui servizi di nuova
creazione, dove unit ed integration test possono fare la differenza.
Dopo aver identificato quali tipi di test mancano maggiormente nel sistema, il passo successivo è
stato vedere se ci sono delle aree più predisposte a difetti su cui concentrare il mio lavoro. Nella
seguente lista sono incluse quelle parti di O3-DPACS che hanno avuto un incidenza maggiore di bug.
Dal totale dei difetti del software registrati, sono qui riportate soltanto quelle aree alle quali possono
essere attribuite almeno il 10% dei bug totali (per l’elenco completo vedere la tabella in appendice):
1. Servizi dicom: 23%
2. Gestione del DBMS: 14,5%
3. Servizio di Worklist: 12,5%
4. Gestione dei servizi del PACS (ciclo di vita e configurazioni): 10,4%
5. Il restante 40% riguarda problemi non catalogabili in macro aree.
Questa lista vuole essere una sorta di scaletta da cui partire per affrontare il lavoro assegnando delle
priorità. Va notato che analizzando l’elenco completo con maggiore attenzione, si può osservare
come i problemi legati alla gestione del DBMS si trovano anche in aree diverse da quella
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
17
esplicitamente assegnatagli, acquisendo così un’importanza ancora maggiore, motivo per il quale è
stato dato molto spazio ai test legati al DBMS.
Analisi delle classi e package
È stata analizzata in dettaglio la struttura del sistema O3-DPACS con lo scopo di assegnare a ciascuna
classe (o insieme di classi), il tipo di test che è possibile creare. Per ogni classe è stata valutata la
possibilità di creare un unit-test corrispondente e l’eventuale utilità. In alcuni casi è stato possibile, in
altri invece ciò è estremamente difficile a causa di un alto livello di accoppiamento tra classi.
L’alternativa è quindi un test di integrazione che coinvolga la classe in esame assieme a tutta una
serie di classi da cui esso dipende. In quest’ultimo caso sono state indicate quali componenti sono
coinvolte. Ad esempio per le classi che non mantengono uno stato interno ma offrono funzioni di
utilità come potrebbe essere il calcolo di un hash, è stata prevista la creazione di un unit-test. Per
classi più complesse come ad esempio quelle che gestiscono la persistenza dei metadati a partire da
oggetti dicom, il test non può che essere di tipo integrazione.
Il criterio utilizzato per “marcare” le classi che possono essere delle buone candidate da sottoporre a
unit test, è stato vedere se di volta in volta le seguenti condizioni erano verificate o meno.
Un test non è unit-test quando:
Comunica con un DBMS
Comunica attraverso la rete
Coinvolge il filesystem
Ha bisogno di configurazioni speciali dell'ambiente
Un unit-test invece deve essere:
Veloce
Ripetibile
Indipendente
Auto esplicativo
“Opportuno”
Inoltre qualsiasi classe che non abbia alcuna logica interna (classi 'entità'), non deve essere oggetto di
unit test.
Sono stati scartati metodi che accedono al database o alla rete, metodi che chiamano in cascata altre
classi (a meno che non siano facilmente interpretabili da classi Stub o Mock), e sono inclusi metodiche hanno una logica il cui risultato cambia in base ai parametri d'ingresso. Metodi che modificano lo
stato o il comportamento dell'applicazione non rientrano in questi casi.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
18
package “it.units.htl.dpacs.helpers”
Anonimizer Unit test
Compression Unit test
DateHelper Unit test
DateTimeRange Unit test
FileHasher Unit test
GlobalConfigurationLoader Integration test (DBMS)
MailerSystem Integration test (DBMS)
PhysicalMediaTimerTask Integration test (DBMS)
package “it.units.htl.dpacs.valueObjects”
Tutte le classi (Privi di logica)
package “it.units.htl.dpacs.core” VarLoader Unit test
Package “it.units.htl.dpacs.dao”
StoragePerformer Integration test (FileSystem)
UserManager Integration test (DBMS)
Tutte le altre classi Functional test (Classi EJB)
UidGenerator Unit Test
DcmFramesToMF Integration test (DB, FS)
DcmQuerier Integration test (Dicom, networking)
KosBuilder Unit test
StudiesVerifierWorker Integration test (DBMS, FileSystem, networking)
XdsClient Integration test (networking)
XdsMessageCreator Integration test (FileSystem, DBMS)
Package “it.units.htl.dpacs.servers”
Tutte le classi Functional Test (Classi MBean)
Package “it.units.htl.dpacs.servers”
Tutte le classi Functional Test (Classi MBean)
Package “it.units.htl.maps”
Classi entità JPA (privy di logica)
Classi DAO Unit test
Tabella 4 - Analisi delle classi e dei package
Questa tabella non è esaustiva, il numero totale delle classi del progetto O3-DPACS è circa 300. Le
classi non in elenco sono state omesse in quanto interfaccie, classi abstract, classi appartenenti al
modulo web, ed altre classi che hanno pochissima logica interna e sono per lo più degli aggregatori di
dati.
Una nota particolare riguarda il modulo web. Esso presenta delle caratteristiche molto differenti datutto il resto del progetto O3-DPACS. Al suo interno ci sono diverse servlet con della logica interna,
filtri (es. per l'autenticazione), ed altre classi che sono strettamente legate con il ciclo di vita di
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
19
un'applicazione web. Il test di questo progetto richiede un approccio specifico, con l'utilizzo di
tecniche e strumenti appositi. Ci sono inoltre delle integrazioni con tecnologie diverse da java (Flex),
e la parte di presentazione si basa sulle Java Server Faces arricchite con le librerie di RichFaces, tutte
infrastrutture che rendono particolarmente difficile la creazione di test automatici che
richiederebbero strumenti specifici come JSFUnit, o Selenium. Vista quindi la natura di questo
progetto e dopo l'analisi iniziale, è stato scelto di tralasciare questa componente e concentrare gli
sforzi sul test del resto del progetto.
Database Testing
Testare lo strato software che si occupa della gestione del DBMS pone diverse problematiche:
Impossibilità di isolare la classe in esame (deve accedere al DBMS)
Complessità del test (inserimento dati di test, pulizia finale)
Velocità (overhead dovuto all’apertura/chiusura delle connessioni e accesso al filesystem)
Per risolvere i primi due problemi si può ricorrere a strumenti più o meno complessi che vengono
incontro alle esigenze dello sviluppatore che vuole evitare di dover scrivere troppo codice solo per
creare unit test. In questi casi infatti la tentazione di evitare di scrivere test diventa sicuramente
molto alta, e la probabilità di non aggiornare test vecchi lo è ancora di più. Uno di questi tool utilizzati
è DBUnit, un'estensione di JUnit che verrà introdotta in seguito.
Il terzo problema, quello legato alla velocità dei test, è un problema che si può definire tale nel
momento in cui vi sono centinaia di test da eseguire prima di ogni build, rendendo vano di fatto il
vantaggio di avere unit test eseguibili ad ogni modifica del codice.
Nel caso dell'applicazione O3-DPACS questo problema ancora non si pone essendo stato sviluppatoun numero di test del database non elevato. Il problema viene quindi rimandato, anche perché la
soluzione più gettonata dalla letteratura di questo momento è quella di diminuire il tempo di
comunicazione con il database portandolo direttamente sul computer dello sviluppatore (vi sono casi
in cui più sviluppatori si trovano costretti ad utilizzare un'unica istanza remota del database per fare
test e sviluppare regolarmente). Ma è possibile fare di meglio utilizzando un DBMS in memoria il
quale non deve accedere alle risorse del filesystem diminuendo il tempo di accesso sia in scrittura
che in lettura ai dati (Hypersonic DB, Derby, Java DB, SQLite).
Purtroppo però non è sempre possibile ricorrere ad un DBMS di questo tipo. L'applicazione O3-
DPACS infatti, sfrutta pesantemente le ottimizzazioni che sono ottenibili con le Stored Procedure diOracle e MySQL. Non avendo uno strato di astrazione del database, l'applicazione non è in grado di
utilizzare database che non siano quelli sopracitati, né tantomeno database "volatili".
Ritornando ai problemi legati alla complessità del codice necessario all'interazione con il database, i
tipici test che vengono creati sono quelli che verificano la correttezza delle operazioni di inserimento
ed estrazione dei dati. Test più avanzati hanno a che fare con le chiamate a Stored Procedure. Il
risultato di tutti questi casi, però, dipende fortemente dallo stato in cui si trova il database nel
momento della loro esecuzione. Se al termine di un test di inserimento di dati in una tabella avente
dei vincoli di unicità, il test non "pulisse" il database, una seconda esecuzione dello stesso test
comporterebbe il fallimento dello stesso!
Pensando invece al caso dell'estrazione di dati, il database dovrebbe essere opportunamente
riempito con dei dati validi, ed eventualmente vuotato al termine del test. Tutte queste operazioni da
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
20
effettuare prima e dopo ogni test non sono impossibili da effettuare, ma sono sicuramente molto
verbose da codificare, con un’elevata probabilità di commettere degli errori, ritrovarsi poi a testare il
codice del test stesso. DBUnit risolve parte di questi problemi permettendo di fatto una
semplificazione della scrittura dei test di database, rendendo più facile l'inizializzazione dello stato
del database e riportandolo allo stato iniziale una volta terminato tutto.
Nell'applicazione di O3-DPACS, la gestione dei dati svolge un ruolo di fondamentale importanza; per
lo più si le interazioni con il DB sono operazioni "delicate" in quanto essendo complesse, hanno
maggior probabilità di contenere degli errori. Per questo motivo per la creazione dei test del
database è stata posta un'attenzione maggiore, cercando diverse strategie per semplificare il
compito. I sistemi di accesso al database utilizzati nell'applicazione sono di vario tipo a seconda delle
necessità. Per operazioni molto semplici come potrebbe essere la SELECT per ottenere il valore di
una singola colonna in una tabella di tipo chiave-valore, vengono quasi sempre utilizzate le api JDBC
in cui la query SQL è residente nel codice stesso. Man mano che le operazioni da fare sono sempre
più complesse, l'approccio utilizzato diventa quello delle chiamate a Stored Procedure, che sono
invece presenti nel DBMS. C'è un ulteriore approccio, utilizzato prevalentemente in quella partedell'applicazione dedicata all'interfaccia web, che sfrutta invece Hibernate come astrazione del
database.
Test funzionali
Dopo aver individuato un possibile elenco di unit test e di integrazione, si è passati all’analisi dei test
che sono attualmente definiti, dai quali è stata ricavata una lista di test che possono essere oggetto
di automazione con conseguente riduzione dei tempi per la loro esecuzione. Questi test, essendo
derivati da quelli attuali, sono tutti di tipo funzionale, e ciascuno di essi descrive un tipico caso d’uso
dell’applicazione. Da notare che pochissimi dei seguenti test sono inseriti nella lista di quelliobbligatori da effettuare ad ogni rilascio. Una loro automazione consentirebbe di poterli inserire tutti
senza problemi.
Test funzionali sul protocollo DICOM
o Test di storage (salvataggio di immagini e metadati) di più studi (esami) contenenti
dati su paziente e studio da individuarsi tramite classi di equivalenza. Il risultato
dovrebbe essere un test eseguito più volte con dati sempre diversi.
o Test di retrieve (recupero di immagini e metadati) con dati individuati come sopra
tramite classi di equivalenza.
o
Test di query (ricerca nell’archivio tramite metadati)
Test funzionali sul protocollo HL7
o Gestione dei messaggi di update
o Gestione dei messaggi di riconciliazione
o Gestione dei messaggi su appuntamenti
Test dei sistemi opzionali e di integrazione
o Creazione ed invio dei messaggi XDS-I (web-service)
o Servizio di Worklist (liste di lavoro)
o Servizio di cancellazione studi
o Anonimizzazione
o Compressione studio Generazione a runtime di file jnlp (java web-start)
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
21
o Recupero di immagini via wado
o Task monitoraggio memorie di massa
o Test algoritmi (hash, base64)
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
22
Tecnologie utilizzate
Nell’arco di tutto il periodo di lavoro su questa tesi, sono state valutate diverse tecnologie chepotessero rivelarsi utili per facilitare la scrittura dei test. Quando in seguito varrà descritto in
dettaglio il processo che ha portato alla creazione dei test in un modo piuttosto che in un altro, ci
saranno dei riferimenti a tre software in particolare più alcune tecniche di programmazione che sono
state impiegate. Queste software sono JUnit, Mockito, DBUnit mentre le tecniche di
programmazione vedono l’utilizzo del pattern “Dependency Injection”, l’utilizzo di classi “Stub” e di
classi “Mock”.
JUnit
Questo software è probabilmente il framework per la creazione di test più conosciuto e diffuso, enon soltanto in ambiente Java. Come suggerisce il nome, è nato per facilitare la creazione di unit test.
Non è il solo framework esistente di questo tipo: il diretto concorrente è TestNG (“Next
Generation”). Quest’ultimo è un progetto più recente, creato per colmare le principali lacune di
JUnit:
Supporto nativo ai test parametrici
Ordine di esecuzione dei test
Riesecuzione dei soli test falliti
Nonostante queste differenze la scelta è ricaduta comunque su JUnit in quanto le stesse
caratteristiche sono ottenibili tramite l’utilizzo di plugin. Questi sono infatti molto più numerosiproprio grazie al fatto che JUnit è sul mercato da più tempo, cosa che ha influito positivamente anche
sul livello di adozione che è più capillare. A questo dobbiamo aggiungere il fatto che in Eclipse (l’IDE
di sviluppo utilizzato in O3-Enterprise) vi è il supporto nativo a questo framework.
Dalle interviste effettuate agli sviluppatori dell’azienda era emerso che degli unit test vengono
tipicamente creati durante la fase di sviluppo senza seguire una metodologia particolare, ed infine
“cestinati” una volta accertato il corretto funzionamento della classe. L’usanza è quella di creare un
metodo Main all’interno della classe oggetto di verifica e provare a richiamarne i metodi. La verifica
può avvenire semplicemente osservando lo standard output sul quale vengono stampati i risultati dei
metodi.Questo approccio presenta diverse debolezze:
1. Un unico test per classe. Potendo inserire un singolo metodo Main per ciascuna classe, anche
il test può essere definito una sola volta. Per ovviare a questo si commentavano man mano
porzioni del metodo Main a seconda di quello che era il metodo da esaminare.
2. Esecuzione manuale di un test per volta. Per l’esecuzione si deve specificare di volta in volta
qual è la classe sotto esame contenente il metodo Main.
3. Struttura variabile. Ogni sviluppatore utilizza un suo sistema, che può variare anche da classe
a classe, rendendo difficile il suo riutilizzo per chi non è l’autore.
4. Mix di codice operativo e codice di test nella stessa classe. Questo oltre ad esserestilisticamente brutto, rende anche difficile capire al volo se una classe ha un rispettivo test.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
23
Tutti questi problemi si risolvono impiegando JUnit nel seguente modo:
1. La pratica comune suggerisce di creare una classe di test JUnit associata alla classe sotto
esame. Al suo interno è possibile creare tanti metodi quanti sono i casi che si vogliono
verificare (tipicamente almeno uno per ogni metodo pubblico).
2. È possibile definire una “suite” che raggruppa più test JUnit. In questo modo è possibileeseguire tutti casi definiti in tutte le classi della suite in una sola volta.
3. JUnit impone che ogni test-case sia annotato con “@Test”, rendendo esplicita la sua
definizione. Inoltre prevede che ci possano essere dei metodi che vengono richiamati prima e
dopo l’esecuzione di ogni test, tramite l’utilizzo di altre annotazioni. Tutto questo, assieme
alle convenzioni di scrittura suggeriti da JUnit, permette di mantenere una struttura coerente
anche tra sviluppatori diversi.
4. JUnit suggerisce che per ogni classe da testare, venga creata una classe con lo stesso nome a
cui aggiungere il suffisso “Test”. In questo modo vi è una chiara distinzione tra qual è il codice
operativo e quale ne verifica il funzionamento, mantenendo al contempo evidente la loro
relazione.
Un’altra convenzione utilizzata in questo lavoro è quella di dichiarare nella classe di test, una
variabile di nome ‘instance’ dello stesso tipo della classe sotto esame. In questo modo sarà evidente,
in qualsiasi test, qual è l’istanza della classe sotto test.
Per chiarire meglio l’utilizzo di questo strumento viene fornito un semplice esempio. Si supponga di
avere una classe ‘Anonimizer’ che espone un metodo pubblico ‘anonimize’ che accetta come
parametro un oggetto di tipo ‘DicomMetaInfo’. Si procederà quindi a creare una classe JUnit così
formata:
In JUnit i metodi annotati con @Before e @After vengono chiamati prima e dopo l’esecuzione di ogni
test, anche per quelli definiti nella stessa classe. Infatti per ogni metodo annotato con @Test, il
motore di JUnit istanzia una classe distinta. In questo modo l’esecuzione di un test non può avere in
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
24
nessun modo conseguenze sull’esecuzione di un secondo test. Se da un lato è un vantaggio, dall’altro
rende difficile l’esecuzione di test dove l’esecuzione di uno dipende dal risultato di un altro.
Poiché i metodi contrassegnati come Before ed After vengono richiamati in ogni test-case definito,
non è il posto ideale dove effettuare delle operazioni di inzializzazione costose in termini di tempo
(come ad esempio la connessione al DBMS). Queste operazioni, dove possibile, è consigliabileinserirle in metodi annotati con @BeforeClass ed @AfterClass. Questi metodi, che devono essere
statici, vengono richiamati solamente una volta per tutti i metodi @Test definiti nella classe. In
questo caso una limitazione deriva dal fatto che tutte le risorse inzializzate in questi metodi devono
per forza di cose essere statiche, e condivise tra tutti i test contenuti nella classe.
Un’ultima nota riguarda la collocazione fisica delle classi di test. La presenza simultanea di classi
“vere” e rispettive classi di verifica all’interno dello stesso package può risultare caotica. Per ovviare
al problema è possibile sfruttare le possibilità offerte dagli IDE di sviluppo. In Eclipse ad esempio si
possono definire più cartelle per i sorgenti di uno stesso progetto. Mantenere una cartella separata
contenenti i sorgenti dei test rende il progetto più strutturato. Questo faciliterà anche il compito
dell’automazione dell’esecuzione dei test; come verrà mostrato, sarà possibile programmare un task
che esegua tutti i test-case di JUnit presenti soltanto nella cartella specificata.
Classi Stub e Mock (Mockito)
I principi su cui si fonda il concetto di unit-test che sono stati esposti fin’ora, per i quali un test deve
verificare il comportamento di una sola classe o addirittura di un solo metodo, sono difficilmenteriscontrabili nella realtà. Il motivo è che le classi che non hanno dipendenze verso altre classi (che
non siano quelle della distribuzione standard di Java), in un progetto vero, sono poche. È tipico il caso
in cui ci sono dei riferimenti a classi di utilità per fare delle conversioni, per recuperare configurazioni
varie, o per avere lo stato di altre classi da cui si dipende. Tutto questo però, oltre ad essere indice di
una tecnica di programmazione datata in quanto non pensata per agevolare la creazione di test,
pone dei problemi che devono essere comunque risolti.
L’obbiettivo finale è isolare completamente la classe di cui vogliamo verificare il comportamento dal
resto del sistema. Per riuscire in questo compito si può procedere nel seguente modo: identificare
quali sono le variabili e i loro tipi che creano dipendenze con il resto del programma. Una voltaidentificate, è necessario capire come sostituirle in qualche modo con delle variabili di tipo “simile”
(stessa interfaccia, o classi figlie). Queste nuove classi devono essere create di volta in volta, e la loro
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
25
logica interna va programmata in base alle esigenze di quel specifico test; spesso è sufficiente creare
delle classi completamente prive di logica.
Questa è una tecnica che viene utilizzata per creare delle classi “fantoccio”, le quali possono
assumere due nomi differenti a seconda di alcuni dettagli sulla loro particolare implementazione. Si
parla quindi di classi “Stub2
” e di classi “Mock3
”. Sebbene entrambe queste tecniche abbiano lo scopo di sostituire delle classi che non devono far
parte del test, le classi Stub si differenziano in quanto vengono create in maniera tale che forniscano
una risposta predefinita per il test in atto. Solitamente non sono in grado di rispondere diversamente
a seconda dei parametri di chiamata. Un buon esempio di classe Stub potrebbe essere un finto
servizio web che per un determinato test deve rispondere “404”.
Una classe Mock, invece, è qualcosa di più raffinato, in quanto può essere programmata per
rispondere in maniera diversa a seconda del tipo di chiamata e dei parametri. Un Mock creato per un
test specifico viene configurato in modo che si comporti in un certo modo, e si aspetta di ricevere
delle chiamate secondo una determinata specifica.
Un'altra diff erenza è data dal tipo di verifica che si vuole effettuare quando si utilizza uno o l’altro
tipo. Nel caso degli Stub la verifica viene solitamente fatta sullo stato finale della classe: dopo la
chiamata ad un servizio che risponde “404” la classe si porrà in uno stato particolare che si andrà a
controllare.
Nel caso dei Mock invece, la verifica è più orientata al comportamento. Rimanendo sullo stesso
esempio, si potrebbe controllare che il finto servizio web, impersonificato questa volta da un Mock,
venga effettivamente chiamato dalla classe in oggetto e che non riceva altre richieste. Lo stato finale
della classe in oggetto è meno importante.
Da un punto di vista del loro utilizzo, è importante notare che è estremamente più semplice creare
delle classi Stub. Esse devono infatti comportarsi solamente in un modo, non hanno stato interno e i
loro metodi forniscono sempre lo stesso risultato.
Le classi Mock sono tutt’altro che semplici da creare: esse devono mantenere uno stato interno,
collezionare informazioni sul numero e l’ordine delle chiamate ai vari metodi, informazioni da cui
dipendono i valori restituiti dai metodi esposti. Per questo motivo sono emersi dei framework che
facilitano la loro creazione ed utilizzo.
Nel mondo Java in questo momento esistono almeno 6 progetti di questo tipo: EasyMock, jMock,
Mockito, Unitils Mock, PowerMock e JMockit. L’utilizzo di un tale strumento è sicuramente
fondamentale per questo lavoro, ma il confronto delle loro caratteristiche dichiarate ha reso
evidente che le differenze non sono tali da giustificare una comparazione più accurata.
2 Stub, termine inglese che significa “matrice”, cioè l’elemento originale da cui si creano le copie
3 Mock, termine inglese che significa “fantoccio, finto”
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
26
Caratteristica EasyMock
jMock Mockito UnitilsMock
PowerMock
JMockit
Verifica numero invocazioni di un metodo Si Si Si No Si Si
Mock parziale Si No Si Si Si Si
Zero configurazione (inizializzazione contesto) Si Si Si Si No Si
@RunWith non necessario Si Si Si No No Si
Confronto semplificato tra oggetti VO Si No Si Si Si Si
Mock in cascata No No Si Si No Si
Supporto Mock interfacce multiple No No Si No No Si
Auto injection dei Mock No No Si Si No Si
Mock di Enum
No No No No No SiSingle jar file No No Si No No siTabella 5 - Confronto tra Mocking framework
Appurato il fatto che tutti gli strumenti sopracitati fossero in grado di creare dei Mock a partire dalla
classe da impersonificare, il criterio utilizzato per la scelta è stato quello della curva di
apprendimento. Sono stati analizzati diversi esempi del loro utilizzo, in base ai quali è stato scelto
mockito che già dalle prime prove, si è rivelato molto intuitivo. Questo fatto può sembrare di poca
importanza, ma considerando che dovrà venire introdotto a diversi sviluppatori, questo è stato un
motivo sufficiente per far ricadere la scelta su questo prodotto. Un ulteriore punto a favore per
mockito deriva dalla quantità e “peso” delle librerie da introdurre nel flusso di lavoro. L’unicadipendenza necessaria è infatti una singola libreria da meno di 1,5Mb.
Per iniziare ad utilizzare mockito è sufficiente aggiungere al classpath l’unico jar richiesto. Dopodichè
è possibile creare Mock a partire da qualsiasi classe. Il ciclo di vita dei Mock in mockito è il seguente:
Creare un Mock Object sulla classe o interfaccia
Dichiarare il comportamento atteso
Utilizzo indiretto (da parte dell’oggetto sotto verifica)
Verifica dell’utilizzo (come è stato usato)
Di seguito un esempio sul suo utilizzo (preso e opportunamente semplificato da uno dei casi di test
creati per O3-DPACS). In questo caso si voleva creare un Mock dell’interfaccia java.sql.DataSource.
Quando veniva richiamato il metodo getConnection, la connessione restituita doveva essere quella
configurata per quel particolare test, che veniva opportunamente inizializzata in un metodo annotato
con @Before (di JUnit).
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
27
L’oggetto sotto esame è objectUnderTest , al quale viene passato il finto DataSource. Questo viene
programmato per restituire la connessione opportunamente inizializzata quando gli verrà invocato il
metodo getConnection. Alla fine del test ci si accerta che il metodo sia stato effettivamente invocato.
DBUnit
DbUnit è un'estensione di JUnit, ed ha come unico scopo quello di facilitare il movimento di dati
dentro e fuori dal DBMS, utilizzando dei "dataset" come astrazione dei dati. I dataset di DbUnit
possono assumere diverse forme, ma la più comune è quella di un file xml contenente i dati veri e
propri. DbUnit viene quindi utilizzato per inizializzare il database portandolo in uno stato conosciuto,
contenente esattamente quei dati che servono al test. In questo modo è possibile mantenere questi
dati in un file xml assieme alla classe di test, con conseguente versionamento. DbUnit si rivela molto
utile anche per confrontare un set di dati estratti dal database tramite il test con un dataset preciso.
Una particolarità interessante di DbUnit è che l'inserimento di un dataset nel database può essere
fatto ordinando a DbUnit di rimuovere dati preesistenti che corrispondo al dataset in questione in
modo tale da avere un set di dati sempre "pulito" su cui lavorare.
Molto comoda è anche la funzione che permette di creare un dataset a partire da dati presenti in un
dato DBMS, filtrando i dati per tabella o per valori.
Dependency Injection
La “Dependency Injection” (DI) è un pattern di programmazione nato con lo scopo di migliorare la
testabilità di sistemi software, oltre che facilitare la creazione di componenti indipendenti. Talvolta il
concetto che ne sta alla base viene riferito anche con il nome di “Inversion Of Control” (IoC). Si può
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
28
trovare anche sotto il nome di “Hollywood Principle” (“don’t call us, we’ll call you”), che ho
personalmente reinterpretato come il “principio del colloquio di lavoro” (“le faremo sapere”).
Un componente è un aggregato di codice scritto e pensato per essere utilizzato, senza modifiche, da
un’applicazione che è fuori dal controllo di chi lo ha creato. ‘Senza modifiche’ significa che il
programma utilizzatore non ne può cambiare il codice sorgente, anche se gli è permesso dimodificarne il comportamento estendendolo nella misura prevista dal creatore del componente.
Per comprenderne il principio può essere utile accompagnare la spiegazione con un esempio
esplicativo. In questo esempio il modulo definito dalla classe GlobalConfiguration espone un metodo
che restituisce tutte le proprietà di una certa categoria.
class GlobalConfiguration...public Property[] propertiesFor(String category) {
List allProperties = finder.findAll();for (Iterator it = allProperties.iterator(); it.hasNext();) {
Property prop = (Property) it.next();if (!prop.getCategory().equals(category)) it.remove();
}
return allProperties.toArray(new Property[allProperties.size()]);
}
Sorvolando sulla qualità del codice, quello che è importante notare è che la classe utilizza un oggetto
finder per recuperare tutte le proprietà. Per far sì che questo modulo sia indipendente dal sistema
utilizzato per la gestione delle proprietà, si può estrarre un interfaccia per il finder che dichiari un
metodo findAll . In questo modo la classe GlobalConfiguration può ignorare l’attuale
implementazione del finder .
public interface PropertyFinder {
List findAll();
}
A questo punto però, da qualche parte si deve pur inizializzare la variabile finder con la sua
implementazione, ad esempio nel costruttore.
private PropertyFinder finder;
public GlobalConfiguration() {
finder = new TextFileGlobalConfiguration("configuration.txt");
}
Questa implementazione del PropertyFinder legge le proprietà da un file di testo. Ma cosa succede se
questo modulo viene utilizzato da un’applicazione che però vuole utilizzare un database al posto del
file di testo? Siccome GlobalConfiguration utilizza l’interfaccia PropertyFinder , è sufficiente crearne
una seconda implementazione che legga i dati dal DBMS. Rimane però il problema che il finder viene
inizializzato nel costruttore; è stata infatti creata una dipendenza verso TextFileGlobalConfiguration.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
29
Dal diagramma delle classi si vede che GlobalConfiguration è dipendente sia dall’interfaccia che dalla
sua implementazione. Per ovviare a questo problema e fare in modo che l’unica dipendenza sia
quella verso l’interfaccia, si utilizza la tecnica della Dependency Injection.
L’idea di base è avere un oggetto separato che si assume la responsabilità di assegnare la corretta
implementazione dell’interfaccia in GlobalConfiguration.
Il risultato è quello che nei manuali di design pattern viene chiamato “plugin pattern”. Ora dovrebbe
anche essere chiaro anche il motivo del nome “Hollywood Principle” (don’t call us, we’ll call you). La
classe GlobalConfiguration è ‘passiva’ rispetto alle sue dipendenze, si aspetta che qualcun altro si
prenda la responsabilità di inizializzare un implementazione adeguata del PropertyFinder e che gli
venga notificato. Questo è il principio di base, poi ci sono diverse interpretazioni che differiscono per
il modo in cui le dipendenze vengono soddisfatte. Tipico è il caso delle dipendenze passate come
parametri nel costruttore. Altre volte si prevede un implementazione di default, modificabile tramite
setter (questo è il metodo più utilizzato nel lavoro di refactoring eseguito su parte di O3-DPACS perrenderlo testabile).
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
30
Sviluppo
Per la creazione dei casi di test per O3-DPACS è stato seguito un determinato ordine. Le prime classiche sono state controllate sono quelle che dall’analisi sono risultate idonee per essere sottoposte a
test di unità logiche. Va sottolineato il fatto che la creazione di questo tipo di test fatta a posteriori ha
poca valenza se il fine è scovare eventuali errori. La maggior parte del codice che è stato sottoposto
a questo controllo esiste da diversi anni e viene regolarmente usato senza riscontrare problemi. Il
momento della creazione degli unit-test, invece, dovrebbe essere contestuale alla creazione delle
singole classi. Lo scopo è coprire con dei test quella parte di codice di più “basso livello”, cercando di
mettere in difficoltà il sistema con i dati più critici. Il motivo per il quale sono stati comunque creati
questi casi di test di unità, è per identificare le difficoltà comuni e proporre delle soluzioni. Inoltre,
con la creazione di buon numero di casi, sarà possibile verificare che il processo di automazione della
loro esecuzioni funzioni correttamente.
Lo sviluppo è proseguito con la verifica di tutto ciò che comunica con un DBMS, cercando le soluzioni
migliori per i diversi casi (query dirette via JDBC, chiamate alle Stored Procedure, accesso ai dati
tramite JPA). Nella fase successiva sono state prese in considerazione le classi che interagiscono con
più unità, creando degli appositi test di integrazione. Alla fine si è arrivati ai test funzionali passando
per i servizi Dicom ed Hl7 del PACS (MBean ed EJB).
Creazione di unit test
Per questa tipologia, un buon punto di partenza è stato il package it.units.htl.dpacs.helpers. Al suo
interno vi si trovano una serie di classi di utilità che offrono funzioni che ben si prestano ad essere
verificate in isolamento, analizzando l’output a seconda degli input forniti.
Anonimizer
La prima classe analizzata e testata è la it.units.htl.dpacs.helpers.Anonimizer. Questa classe espone
dei metodi che accettano un dataset Dicom, un oggetto che contiene dei metadati riguardanti un file
Dicom (dati anagrafici del paziente, dettagli degli esami, etc.). Il risultato è lo stesso dataset, ma
spogliato di alcuni dati per impedire il riconoscimento del paziente.
La creazione del test con JUnit in questo caso è banale. Quello su cui è stato possibile riflettere è
l’insieme dei dati da utilizzare. Le variabili in ingresso sono numerose, e sono date dai campi deldataset che devono essere anonimizzati. Per ogni variabile però, si individuano solamente due classi
di equivalenza: variabile valorizzata e variabile non valorizzata.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
31
Variabili Classi equivalenza
Dati paziente null valorizzato
Nome null valorizzato
Cognome null valorizzato
Id null valorizzato
… null valorizzato
Dati medico curante
Nome null valorizzato
Cognome null valorizzato
… null valorizzato
In base a queste considerazioni, per questa classe è stato sufficiente creare due casi per ogni
metodo.
Si potrebbe pensare che due classi di equivalenza siano poche, ma questa considerazione nasce
dall’analisi diretta del codice della classe Anonimizer. È possibile vedere come i valori delle variabili
non vengano mai lette, ma solamente sostituite con dei valori standard, previo controllo sul loro
essere null o meno. Quando un test viene creato esplorando il codice sorgente dell’oggett o
sottoposto a verifica, si dice che si sta eseguendo del “white box” testing. Questo si differenzia dal
metodo di “black box” testing che non prevede che chi scrive i test abbia conoscenza
dell’implementazione dell’oggetto. Il white-box testing ha il vantaggio che permette la copertura di
una maggiore, se non totale, porzione di codice. Lo svantaggio sta nel fatto che il tester di solito è lo
stesso che ha sviluppato la classe in esame, e per questo è meno obbiettivo.
DateHelper
La classe DateHelper fornisce un metodo getFirstUsefulDate che a partire da una stringa, restituiscedata e ora corrispondente. Se la combinazione di data e ora rappresenta un instante nel passato,
allora restituisce la prima occorrenza di quell’ora nel futuro. Questo metodo viene utilizzato per la
configurazione di più servizi, in particolare per far iniziare l’esecuzione di diversi task temporizzati.
In questo caso le classi di equivalenza sono più interessanti, e vengono riportate nella seguente
tabella con il rispettivo risultato aspettato.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
32
Input D,T (data e ora) Expected Output (Date)
Null Null
Formato di D,T non valido Null
D,T > now() Data e ora corrispondente a D,T
D < today(), T > now() Data del giorno corrente, ora pari a T
D,T < now() Data del giorno seguente, ora pari a T
Il risultato di questa tabella è la classe DateHelperTest con 5 metodi, uno per caso di test.
DateTimeRange
Con la DateTimeRange si rimane sugli strumenti per la manipolazione di date. È interessante notare
come per questa classe fosse già previsto un test nel sistema preesistente. Questo è uno dei pochi
casi in cui è stato esplicitamente definito una unit-test utilizzando l’unico sistema che era previsto,
quello degli script-test (istruzioni testuali, esecuzione manuale).
DateTimeRange nasce dalla necessità di dover gestire intervalli di date in maniera precisa,
prevedendo molte opzioni. Viene utilizzata per supportare l’interrogazione delle liste di lavoro dato
un certo intervallo di tempo. La complicazione arriva proprio dal numero di parametri e dai loro
valori possibili.
Questa classe è più complessa delle precedenti, ma è completamente isolata dal resto
dell’applicazione, per questo motivo viene riportata come esempio significativo di test di unità
realizzato sul sistema.
Il funzionamento prevede che ad un’istanza vengano configurati gli estremi degli intervalli definiti dadue estremi “sinistri” (data inizio, ora inizio) e due “destri” (data fine, ora fine). È possibile impostare
da uno a tutti e quattro i parametri per ottenere risultati differenti. Dopo aver inizializzato gli estremi
voluti, è possibile ottenere la data e ora (in formato java.util.Date) del limite destro e del limite
sinistro dell’intervallo impostato. L’analisi dei possibili valori ha portato alla seguente tabella, che
copre tutti i casi possibili.
DATE TIME Expected output
FROM TO FROM TO FROM TO
X Y J K x.j <= DATA <= y.kX Y J - x.j <= DATA <= Y
X Y - K X <= DATA <= y.kX Y - - X <= DATA <= Y
- Y J K - <= DATA <= y.k- Y J - - <= DATA <= Y- Y - K - <= DATA <= y.k- Y - / - <= DATA <= Y
X - J K x.j <= DATA <= -X - J - x.j <= DATA <= -X - - K X <= DATA <= -X - - - X <= DATA <= -
- - J K J <= DATA <= K- - J - J <= DATA <= -
- - - K - <= DATA <= K- - - - - <= DATA <= -
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
33
La metà sinistra della tabella copre tutti gli input possibili, mentre sulla sinistra viene riportato il
risultato aspettato per ogni caso. La X e la Y rappresentano delle date, mentre la J e la K
rappresentano delle ore. Le celle degli input contenenti il simbolo ‘–‘ significano che l’estremo
corrispondente non è impostato. Nelle celle dell’output invece significa che il limite è indefinito. Da
questa tabella è stato creata una classe di test contenente tutti i 16 casi significativi individuati.
FileHasher
Ci sono casi in cui non è possibile creare lo unit-test di una classe senza modificarne il codice. Questo
è un problema che si presenta frequentemente in O3-DPACS, come in tutti i programmi scritti senza
avere in mente questo obbiettivo. La classe FileHasher ne è un buon esempio.
Questa semplice classe computa l’hash di un file passato come parametro assieme al nome
dell’algoritmo da utilizzare. Al suo interno però va ad interrogare un gestore di proprietà del sistema
per conoscere la dimensione del buffer da utilizzare. Questa dipendenza non consente di testare la
funzionalità di hash poiché, preso al di fuori del contesto in cui si aspetta di essere eseguita, il gestore
di proprietà non funziona (in questo caso è un MBean che interroga un DBMS).
Il refactoring di questa come di altre classi, ha come vincolo fondamentale quello di mantenere
laddove possibile, l’interfaccia della classe modificata invariata. Questo requisito è necessario per
assicurarsi che gli utilizzatori sparsi nel resto dell’applicazione, non debbano a loro volta essere
intaccati, rimanendo sicuri che tutto continuerà a funzionare.
Analizzando la classe sotto esame si vede come il gestore di proprietà viene richiamato all’interno del
metodo doHash. Per non modificare questo comportamento (giusto o sbagliato che sia), è stata
aggiunta una proprietà a livello di classe contenente il valore della dimensione del buffer, ed un
relativo metodo setter .
Nella funzione doHash è stato aggiunto un
controllo in modo che il gestore venga interrogato
solamente se il setter non è stato esplicitamente
chiamato.
A questo punto è stato possibile creare il test, che
dato un file di riferimento, verifica che l’hash
restituito dal metodo sia corretto tenendo conto
dell’algoritmo utilizzato. Gli algoritmi di hash
testati sono SHA-1, SHA-256 e MD5. Per la
realizzazione è stata sfruttata la funzionalità di
JUnit per rieseguire lo stesso test-case più volte variandone i parametri. Il parametro variato è
l’algoritmo, mantenendo fisso il file di riferimento; ovviamente anche il risultato aspettato varia con
l’algoritmo, quindi i parametri passati al test sono la coppia algoritmo-risultato atteso.
Figura 1 - diagramma di flusso del metodo doHashmodificato
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
34
UidGenerator
In Dicom, ogni immagine è univocamente identificata da un UID (Universal ID), formato da una serie
di caratteri numerici separati dal carettere punto. Il valore finale è la composizione di più parti:
Root id: identificativo univoco dell’organizzazione che crea l’uid delle istanze
Study Instance UID: id relativo dello studio (esame)
Series Instance UID: id relativo della serie (ogni studio può avere n serie)
SOP Instance UID: id relativo della singola immagine.
Esempio di Sop Instance UID:
La classe UidGenerator viene utilizzata per generare uid con la
root id assegnata ad O3-Enterprise. La cosa interessante è che
data un’istanza, è possibile generare degli UID per nuovi studi,
serie ed istanze. Qui non ci sono input in base ai quali cambia il
risultato, ma è lo stato interno della classe che cambia in base ai
metodi invocati (senza parametri) ciascuno dei quali restituisce
l’uid del tipo richiesto. Di conseguenza l’obbiettivo del test non sarà quello di verificare il risultato in
base ai parametri di ingresso, ma sarà quello di verificare l’output ad ogni cambiamento di stato.
Lo stato di ogni istanza è dato dalla terna UID dello studio (X), UID della serie (Y) e UID dell’istanza (Z).
È possibile modellizzare la classe come una macchina a stati da cui è possibile ricavare la seguente
tabella delle transizioni:
T1 T2 T3 T4
Stato inizale X;Y;Z X;Y;Z X;Y;Z X;Y;Z
Evento getNewStudy getNewSerie getNewInstance reset
Effetto X++ Y++ Z++ X = newStudyUid();
Y = newSeriesUid();
Z = 1;
Stato finale X+1;Y;Z X;Y+1;Z X;Y;Z+1 X’;Y’;Z’
Nella teoria dei test si parla di “0-switch coverage” quando i test creati sono pari al numero di
transizioni. In questo caso i casi sarebbero 4. Fermo restando che la copertura totale di una classe di
questo tipo è impossibile (esistono infiniti stati), per aumentare la copertura con i test, è necessario
provare un numero maggiore di combinazioni stato-transizione. Lo “1-switch coverage” prevede che
vengano esplorate le combinazioni scendendo di un livello nell’albero delle combinazioni, con
conseguente incremento esponenziale dei casi di test.
UidGenerator
+ getNewStudyUid() : String+ getNewSeriesUid() : String+ getNewInstanceUid() : String+ reset ()
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
35
Figura 2 - 1-switch coverage per UidGenerator
L’albero in figura rappresenta tutte le diramazioni possibili fino al secondo livello. I cerchi rossi
indicano gli stati e transazioni appartenenti allo “0-switch”, mentre aggiungendo i cerchi rossi si
raggiunge lo “1-switch coverage”, con un totale di 16 casi di test. Ciascun test parte dallo stato
rappresentato dalla radice e arriva fino alla foglia più esterna, coprendo tutte le transizioni previste
dal percorso.
KosBuilder
Fra tutti gli unit-test creati, l’ultimo caso che viene proposto è stato scelto perché si presta bene
all’introduzione di un problema comune in molte parti del codice di O3-DPACS. La classe KosBuilder
ha il compito di costruire un file dicom particolare detto “KOS” (Key Object Selection), che al suo
interno non contiene immagini ma solamente riferimenti a istanze di altri file dicom. Il kos viene
creato in base ai parametri di ingresso, che in questo caso è un oggetto KosMetaInfo, contenente
tutti i dati necessari per ottenere un file kos.
Il problema nel testare questa come altre classi, è dato dal fatto che il test dovrebbe verificare che il
file generato contenga i dati corretti secondo quanto passato in ingresso. Questa operazione può
essere vista come una sorta di conversione dal tipo A al tipo B. La verifica d ovrebbe dire se l’istanza
di A “equivale” all’istanza di B. Per fare questo è quindi utile creare dei comparatori che siano in
grado di confrontare istanze di tipo diverso tra loro.
Per il caso di KosBuilder è stata creata una classe KosComparator costruita in maniera tale da
verificare che i dati provenienti dal KosMetaInfo siano stati correttamente riportati nel relativo file
KOS. A questo punto per la scrittura del test, ci si riconduce alla procedura già vista dell’analisi delle
variabili di ingresso (in questo caso le proprietà del KosMetaInfo) individuandone le classi di
equivalenza e scrivere i casi di test di conseguenza.
Database Testing (jdbc, stored procedure, jpa)
Test di classi DAO
In O3-DPACS esiste un certo numero di classi DAO utilizzate per l’accesso ai dati salvati nel DBMS.Tutte queste classi hanno una struttura simile tra loro ed utilizzano query SQL standard tramite i
connettori JDBC. Espongono una serie di metodi pubblici che astraggono prevalentemente delle
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
36
SELECT ed in minor numero degli UPDATE. Ciascun metodo ottiene una connessione da un
DataSource, acquisito a sua volta tramite JNDI lookup.
Queste classi si aspettano quindi che a runtime ci sia un contesto JNDI in cui vi sia registrato un
DataSource dal quale recuperare le connessioni al DBMS, ma tutto ciò in un unit-test non è possibile.
È necessario modificare queste classi facendo in modo che l’acquisizione di una connessione possaavvenire anche in un modo differente, mantenendo al contempo il sistema esistente.
Per fare questo le classi DAO sono state modificate aggiungendo un costruttore (oltre a quello
preesistente senza parametri) nel quale viene passato un DataSource che la classe deve utilizzare per
ottenere le connessioni. In questo modo il comportamento originale non è stato intaccato ma per
effettuare i test sarà possibile fornire un DataSource configurato appropriatamente.
Per mostrare il risultato viene riportato il caso della classe UserManager.
Il metodo privato getConnection veniva richiamato da ogni metodo pubblico per ottenere una
connessione dal DataSource. Nel refactoring il DataSource è una proprietà privata che viene
inizializzata nel costruttore.
Avendo isolato le classi DAO dal resto del sistema, contesto JNDI incluso, rendendole testabili, resta il
problema di dover fornire un DataSource ad ogni classe prima di verificarne i vari metodi.
A questo scopo è stata scritta un’apposita classe astratta che se estesa, facilita la creazione di
DataSource validi che vengono poi forniti alle classi sotto test. Se utilizzata, automaticamente ciascun
caso di test viene eseguito N volte, dove N è il numero di DBMS su cui si vuole testare. Ad ogni
esecuzione, il caso verrà testato su una connessione verso un DBMS diverso.
Tutto ciò è possibile specificando nella classe astratta (JDBCTestCase) che per eseguire i test venga
utilizzato il motore di JUnit per test parametrici.
In questo modo tutti i metodi contrassegnati dall’annotazione @Test verranno eseguiti N volte,
ciascuna avente un JDBCConnectionMetadata diverso. Quest’ultima classe è un contenitore di
parametri utilizzati per la connessione al DBMS (driver, user, password, url jdbc, schema, vendor).
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
37
L’inizializzazione del DataSource avviene in un metodo di JDBCTestCase annotato con @Before. In
realtà non viene creato un vero e proprio DataSource, ma viene utilizzato un Mock.
Oltre alla connessione JDBC, ne viene creata anche una seconda dedicata a DBUnit. Il risultato è che
qualsiasi classe estenda JDBCTestCase, avrà automaticamente a disposizione un DataSource valido da
poter passare all’istanza sotto test, ed una connessione DBUnit per preparare il DBMS al test.
Per utilizzare questa classe è sufficiente estenderla, dopodiché è possibile utilizzare il DataSource e la
connessione per DBUnit, come è stato fatto nel caso di UserManagerTest:
Con questa tecnica è stato possibile testare diverse classi DAO, evitando di dover ogni volta creare
una connessione e un caso diverso per ogni DBMS supportato.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
38
Stored Procedure
L’approccio per l’accesso ai dati più diffuso non è tramite l’utilizzo delle classi DAO ma tramite
chiamate a Stored Procedure sparse un po’ ovunque nella logica di O3-DPACS. Sebbene la
valutazione di questa scelta non sia oggetto di questo lavoro, lo è sicuramente il problema di come
testare le Stored Procedure. Queste vengono inserite in svariati punti di metodi il cui scopo principale
non è quello della comunicazione con il database; per questo motivo non si andrà a testare quei
metodi ma si andrà a creare una batteria di unit-test, ciascuno dei quali avente il compito di
verificare il corretto funzionamento di una stored-procedure.
La totalità delle stored procedure definite in O3-DPACS sono state suddivise in categorie in base al
tipo di entità su cui vanno ad operare e il tipo di operazione SQL (INSERT, UPDATE, DELETE, SELECT).Per l’elenco completo e relativa classificazione si faccia riferimento alla tabella in appendice.
Come per i test delle classi DAO, anche in questo caso è stata creata una classe astratta che si occupa
della maggior parte dei dettagli sulla creazione della connessione, molto simile alla JDBCTestCase.
Tutte le classi risultanti dalla categorizzazione delle stored-procedure estendono
StoredProcedureTestCase.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
39
I test delle stored-procedure (SP) si differenziano da quelli “semplici” che utilizzano JDBC con le
operazioni SQL tradizionali in quanto la sintassi delle chiamate alle SP cambia a seconda del DBMS su
cui si esegue la procedura.
if (isOracle) {callableStatement = connection.prepareCall("{call getPatientInfo(?,?)}");
callableStatement.registerOutParameter(2, OracleTypes.CURSOR);
callableStatement.execute();
resultSet = (ResultSet) callableStatement.getObject(5);} else if(isMySql) {
callableStatement = cononnection.prepareCall("{call getPatientInfo(?)}");
resultSet = callableStatement.getResultSet();}
Per ovviare a questo problema è stata creata una classe astratta StoredProcedure che si comporta da
involucro per le CallableStatement (classe Java utilizzato per eseguire le stored procedure via JDBC),
le cui implementazioni per MySQL ed Oracle si occupano di utilizzare la sintassi corretta. La creazionedi oggetti StoredProcedure avviene attraverso l’utilizzo di una “Factory”, alla quale viene passata la
connessione e restituisce l’implementazione corretta di StoredProcedure per il DBMS in uso.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
40
StoredProcedureFactory spf = new StoredProcedureFactory(connection);storedProcedure = spf.getStoredProcedure();
callableStatement = storedProcedure.prepareCall("getPatientInfo");
callableStatement.execute();resultSet = storedProcedure.getResultSet();
Il risultato di questa infrastruttura è che per testare una stored-procedure è sufficiente creare una
classe che estenda la classe astratta StoredProcedureTestCase, e almeno un metodo annotato con
@Test in cui è possibile utilizzare un’istanza di StoredProcedure già opportunamente inizializzata.
Ciasuno di questi metodi @Test verrà eseguito una volta per ogni tipo di DBMS configurato.
JPA (Hibernate)
Le interfacce JPA (Java Persistence Api) e la loro implementazione Hibernate, non sono un’esclusiva
di Java Enterprise, anche se la maggioranza degli utilizzatori sono applicazioni web che vengono
eseguite in web container come Tomcat o JBoss. Tuttavia è possibile sfruttare questa tecnologia
anche all'infuori di un container. È quindi possibile creare test per quello strato dell'applicazione che
sfrutta JPA come astrazione della base dati.
Per riuscire nell'opera di testare le classi che utilizzano direttamente le API di JPA, è necessario
configurare l'ambiente in cui esse andranno eseguite. In particolare le API di JPA prevedono che nelclasspath vi sia un file di configurazione persistence.xml contenuta nella cartella META-INF, con
all'interno la definizione delle cosiddette persistenceUnit, ciascuna delle quali descrive un set di classi
che devono essere considerate come entità persistenti (classi che astraggono tabelle del database)
ed una serie di configurazioni necessarie per creare connessioni al database.
Per poter testare le classi e i metodi che utilizzano JPA, sarà quindi sufficiente creare una
'persistence-unit' contenente tutte le informazioni necessarie per connettersi al database di test.
Dalla classe di test sarà così possibile ottenere un'istanza di EntityManager (principale interfaccia
messa a disposizione da JPA attraverso la quale è possibile interagire con le "entità persistenti") ed
effettuare tutte quelle operazioni che vengono normalmente fatte all'interno dei metodi delle classi
che si vogliono testare. Rimane però un problema tipico delle applicazioni enterprise: nelle classi da
testare, l'EntityManager viene ottenuto praticamente sempre tramite lookup jndi. Portando queste
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
41
classi fuori dal container di JBoss dove normalmente vengono eseguite, il lookup fallisce e si deve
scegliere una fra le varie soluzioni studiate.
In questo caso particolare si è scelto di arricchire la classe da testare aggiungendo un metodo
setEntityManager() con il solo scopo di permettere l’assegnazione di un EntityManager creato
appositamente per test, come avveniva per i DataSource.
Creazione dei test di integrazione ed MBean
I test di integrazione coinvolgono classi che hanno numerose dipendenze verso altre classi. La
situazione ideale vorrebbe che queste classi “secondarie” siano completamente isolate dal resto
dell’applicazione e ignare del loro utilizzatore (candidate ideali per unit-test). Purtroppo nella realtà
ciò non avviene, rendendo molto difficile la verifica della classe che al suo interno fa riferimento a
numerose altre classi. Se queste ultime a loro volta dipendono da altre classi, allora il test non può
che essere fatto sull’ambiente finale, dove l’applicazione viene eseguita solitamente. Ci sono casi in
cui è più conveniente eseguire i test in questo modo, ma in altri è possibile riportarsi ad una
situazione favorevole alla creazione di test di porzioni di applicazione, passando attraverso un
processo di refactoring. Questo lavoro può essere anche difficile, ma se l’obbiettivo viene raggiunto,
allora i vantaggi ripagano sicuramente dello sforzo.
Come esempio di test di integrazione reso possibile grazie al refactoring, viene riportato il caso della
classe StoragePerformer. Di seguito ne viene riportato il workflow:
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
42
Il test di integrazione si basa sull'ipotesi che le singole componenti ivi usate siano già state testate nei
loro rispettivi unit-test (Compression e FileHasher). In questo test invece si testeranno le seguentisituazioni per coprire i vari percorsi:
Test case 1: salvataggio in directory non esistente, con conseguente creazione del path (il
salvataggio in directory già esistente è considerabile come un sottoinsieme di questo caso)
Test case 2: l'hash viene calcolato e restituito col metodo getHash
Test case 3: il file viene compresso se richiesto
Problemi e soluzioni adottate:
Dipendenza dalla classe Compression: l’istanza veniva recuperata da un MBean nel
costruttore; questo perché l’istanza restituita è già stata configurata correttamente inprecedenza in altri punti dell’applicazione. Per test, è stato aggiunto un costruttore a
StorageServer che accetta un’istanza di Compression.
Dipendenza dalla classe FileHasher: l’istanza viene creata all’interno de l metodo che salva il
file su disco, ma i parametri della sua configurazione vengono ricavati dal MBean di
DicomServer. Per mantenere invariato questo comportamento è stato creato un Mock del
DicomServerMBean registrato in un MBeanServer di test.
L'integrazione con il filesystem rende necessaria l’esistenza di una directory disponibile sul
filesystem del sistema di test. Una possibilità è quella di prevedere una directory temporanea
dedicata sul sistema di test. Un’altra possibilità, che è quella adottata, vuole che si utilizzi ladirectory corrente. Questa soluzione è stata preferita in quanto ha un impatto minore sul
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
43
sistema di test, e non ha bisogno di configurazioni. Al termine del test la cartella temporanea
viene rimossa.
Uno dei principali problemi che si sono presentati in questa classe nasce dal fatto che diverse
configurazioni vengono prese da diversi MBean registrati in un MBeanServer (tecnologia JMX).
Questo approccio si ritrova in numerose classi, per questo motivo si è cercata una soluzione chepotesse garantire alle classi sotto esame di trovare gli MBean richiesti, ottenendo dei parametri di
configurazione opportunamente settati caso per caso.
Gli MBean utilizzati in O3-DPACS sono:
DicomServerMBean
HL7ServerMBean
StorageSCPMBean
QueryRetrieveSCPMBean
WorklistServiceMBean
StudiesVerifierMBean
MPPSSCPMBean
CompressionSCPMBean
ImageMaskingSCPMBean
ForwarderServiceMBean
AuditLogServiceMBean
Questi MBean vengono utilizzati in molteplici punti dell’applicazione per recuperare i parametri di
configurazioni per i vari servizi Dicom (Storage, Query/Retrieve, Worklist), HL7, verifica degli studi,
etc.
Per ciascuno di essi è possibile creare un Mock, che viene registrato su un MBeanServer fatto partire
prima di ogni test e fermato al termine. Per semplificare questo processo si può creare anche qui una
classe astratta per JUnit.
Le classi sotto esame sono le varie StoragePerformer , StorageServer , StorageSCU etc. Queste classi siaspettano di trovare i vari MBean registrati nell’MBeanServer , dai quali ottenere i parametri di
configurazione. MBeanTestCase crea un MBeanServer apposito dove vengono registrati i Mock degli
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
44
MBean, e vengono resi recuperabili facilmente con i vari getNomeMBean. In questo modo le classi di
test che estendono MBeanTestCase per preparare l’ambiente possono prendere il Mock dell’MBean
di interesse, valorizzarne i vari parametri ed essere sicuri che la classe sotto test verrà eseguita
leggendo i parametri configurati appositamente.
Test dei servizi
Tra i vari servizi di O3-DPACS, quello più importante è probabilmente il servizio di Storage. Questo
viene utilizzato alla ricezione di immagini diagnostiche tramite il protocollo dicom. I dettagli sulla
comunicazione tra client e server vengono delegati ad una libreria java apposita “dcm4che”. Questa
libreria astrae i dettagli sulla creazione del server ed espone un interfaccia a callback dove
l’applicazione può registrarsi per gestire determinate transazioni. In dicom l’invio di immagini avviene
tramite la transazione “C-STORE”; O3-DPACS è programmato in maniera tale che alla ricezione di un
immagine venga richiamato, tramite callback di dcm4che, il metodo doCStore della classe
StorageServer .
Il test di questo metodo consente di verificare la logica di business relativa alla ricezione di file dicom.
Normalmente per effettuare dei test è necessario avviare l’applicazione al completo. L’obbietivo è
quindi evitare tutto ciò isolando il più possibile la classe in esame.
Il primo passo è identificare le dipendenze. Dall’analisi della classe sono state evidenziate le seguenti
dipendenze:
1. Anonimizer : aggiunto ai parametri del costruttore
2. GlobalConfigurationLoader : vedi nota-1
3. StorageSCPMbean: già presente nei parametri del costruttore
4. DicomStorageDealerLocal : aggiunto ai parametri del costruttore
5. CompressionSCP: vedi nota-2
6. DicomStorageDealer : aggiunto ai parametri del costruttore
7. ImageMaskingSCP: vedi nota-3
8. DicomDbDealer : aggiunto ai parametri del costruttore
Nota-1
GlobalConfigurationLoader è una classe che espone un metodo statico getConfigParam per
recuperare dei parametri di configurazione dal DBMS. Per rendere StorageServer indipendente da
questa classe e quindi dalla presenza del DBMS, è stato effettuato un refactoring di
GlobalConfigurationLoader : è stata creata un’interfaccia “ConfigurationLoader” la quale espone ilmetodo getConfigParam, e GlobalConfigurationLoader è diventata una implementazione che
recupera i dati dal DBMS. Per il test di StorageServer , viene passato un Mock dell’interfaccia.
Nota-2
Di CompressionSCP viene richiamato soltanto il metodo statico getCompressionTransferSyntax , che a
sua volta richiama un metodo di DicomDbDealer . È stata quindi eliminata questa dipendenza a favore
della chiamata diretta a DicomDbDealer.
Nota-3
Di ImageMaskingSCP vengono usati i metodi isImageElaborationEnabled, getMaskTags, getMasks. I
primi due richiamano i metodi di DicomDbDealer , quindi sono stati eliminati in favore a chiamate
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
45
dirette a quest’ultimo. Il terzo metodo è un metodo statico al cui interno non ci sono ulteriori
dipendenze, quindi è stato mantenuto.
Il costruttore della classe StorageServer originale ha 1 solo parametro. Quello creato appositamente
per consentirne il test ne ha 5. Non sono stati riscontrati casi con un numero ancora maggiore di
dipendenze, per questo motivo si è ritenuto che esplicitare questi parametri nel costruttore sia unasoluzione accettabile, motivazione avvalorata anche dal fatto che rende più evidente quali sono le
oggetti utilizzati di cui si deve tener conto.
In questo modo è stato ottenuto un livello di isolamento sufficiente per poter sottoporre la classe a
test all’infuori del container J2EE.
Per testare il metodo doCStore è necessario creare un server dicom apposito sfruttando le librerie
dcm4che, e registrare l’istanza di StorageServer quale “ascoltatore” (listener ) per transazioni di tipo
“C-STORE”. A questo punto è possibile inviare un’immagine dicom al server attravers o una seconda
classe creata appositamente.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
46
Il test degli altri servizi dicom segue la stessa struttura, quello che cambia è il tipo di transazione
effettuata dal DicomClient e l’istanza della classe sotto esame che viene registrata nel DicomServer
come classe da chiamare alla ricezione di quella determinata operazione.
Lo stesso approccio è da utilizzarsi anche per i servizi HL7. Cambiano le librerie, ma il principio di
utilizzo lo stesso. Anche queste librerie prevedono la creazione di un Server HL7 al quale viene
registrata la classe che si occupa di gestire i vari messaggi. Le classi da testare hanno lo stesso nome
della transazione, quindi per i messaggi ADT^A08 (aggiornamento anagrafica paziente), si testa la
classe ADTA08 tramite la classe di test ADTA08Test, la quale crea il client e server HL7 e gestisce
l’invio del messaggio e successiva verifica dei risultati.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
47
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
48
Automazione
Per l’automazione dell’esecuzione dei test è stato scelto di usare Jenkins. Questo è uno dei server di“Continuous Integration” (CI) esistenti e tra i più utilizzati; “l’integrazione continua” è una pratica di
sviluppo del software dove le modifiche al codice vengono integrate frequentemente. Ad ogni
integrazione dovrebbe seguire un build automatico (compilazione e “impacchettamento” dei vari jar,
war, ear), eseguito su un server apposito, verificato con l’esecuzione di tutti i test definiti per il
progetto. I requisiti per mettere in pratica questa metodologia sono:
1. codice su repository (SVN, CVS, git)
2. codice con commit frequenti sul trunk (commit di ogni issue)
3. commit di codice sempre "funzionante"
4. tool di building automatico (ant, maven, make) 5. server di CI (Jenkins, Cruise Control, Apache Continuum, etc.)
Il processo di sviluppo di O3-DPACS soddisfa pienamente i primi tre punti. Il quarto punto è
parzialmente implementato (esistono e vengono utilizzati gli script di build dei vari pacchetti, che
va integrato con uno script per la compilazione dei test e della loro esecuzione). Nel quinto
punto entra in gioco Jenkins.
Script di build ed esecuzione automatici
O3-DPACS utilizza script Ant per la compilazione e impacchettamento dei sorgenti. Di conseguenza è
stato utilizzato anche per la compilazione delle nuove classi di test. Il task per la loro compilazione èstato integrato nello script preesistente, affiancandolo a quelli originali.
Per l’esecuzione dei test invece, è stato creato uno script ant apposito “Test Runner.xml” con i
seguenti task:
Il task “Compile and run” è un task che dichiara solo dipendenze e fa scattare gli altri test nell’ordine
indicato nel grafico.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
49
Il primo task chiamato è “Prepare for tests” che copia i file di configurazione necessari ai test (dati di
test, file xml, e file di proprietà per le connessioni ai DBMS). “Compile core tests” compila i sorgenti
dei test, ma non prima di aver compilato i sorgenti dell’applicazione. Infine lancia il task che esegue
tutti i test JUnit presenti nei sorgenti.
Utilizzo di Jenkins
L’obbiettivo finale è riuscire a configurare il server di CI in maniera tale che ad ogni commit sul trunk
dell’SVN, vengano automaticamente scaricati gli ultimi sorgenti, compilati, ed eseguiti tutti i test,
creando un report visualizzabile da interfaccia web.
Jenkins viene distribuito come un singolo file “war” (applicazione web Java Enterprise), che può
essere eseguito all’interno di un container J2EE, ma può essere anche eseguito come applicazione
“stand-alone” in quanto nella distribuzione è già compreso un mini container J2EE. Ovviamente
questo pone delle limitazioni alle possibilità di configurazione, ma per il momento è più che
sufficiente. Per far partire l’applicazione è sufficiente eseguire il comando:
java –jar jenkins.war
In questo modo viene avviato un server web con l’applicazione al suo interno. La configurazione
avviene completamente tramite interfaccia web. I passi necessari per automatizzare il build e i test di
O3-DPACS sono:
Creare un “Job” Jenkins per O3-DPACS
Configurare il repository SVN in modo tale che prenda i sorgenti dal trunk del progetto
Specificare gli script ant per il build dell’applicazione
Aggiungere il secondo script ant per l’esecuzione dei test Il “job” così configurato è in grado di compilare applicazione e test, ed eseguire questi ultimi. Per fare
in modo che questo job venga eseguito ad ogni commit sul trunk, è necessario aggiungere un poll sul
repository SVN che controlli periodicamente se ci sono modifiche dall’ultimo controllo.
Per ottenere il report dei test è stato necessario modificare lo script “Test Runner” affinchè generi un
report XML, dopodiché da Jenkins è sufficiente indicare la directory dove vengono salvati i report per
fare in modo che questi vengano caricati nell’interfaccia web.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
50
Conclusioni
Risultati ottenuti
Il progetto O3-DPACS è stato arricchito da una serie di strumenti che consentono e facilitano la
scrittura di unit-test per diverse componenti dell’applicazione che altrimenti richiederebbero
l’esecuzione dell’intera applicazione in un ambiente completamente configurato. Le componenti
principali sono:
Classi DAO
Stored procedure
Classi che accedono al DBMS tramite Hibernate
Classi che utilizzano gli MBean di JMX
Servizi Dicom e HL7
Sono inoltre stati affrontati gli ostacoli più ricorrenti emersi nel tentativo di testare classi con
dipendenze, analizzando i vari problemi e individuando soluzioni comuni come il refactoring delle
classi sfruttando il pattern di programmazione della “Dependency Injection”. Ci si è avvalsi di ulteriori
tecniche per aumentare il disaccoppiamento tra moduli ricorrendo a classi Stub e Mock e relativi
framework.
Affianco all’attuale processo di testing del software di O3-Enteprise, sono stati integrati gli unit-test
con l’introduzione di JUnit come framework di base e sono stati creati dei test veri e propri su parti
eterogenee del codice. Nel farlo, sono state utilizzate tecniche di software testing quali ilpartizionamento delle variabili di input in classi di equivalenza e copertura “intelligente” del codice
tramite esplorazione dei grafi.
È stata infine proposta una soluzione funzionante per adottare la tecnica della “Continuous
Integration” che permette l’esecuzione automatica dei test ad ogni modifica del codice versionato su
SVN.
Confronto
Dell’insieme di tutti i test creati, soltanto alcuni possono essere considerati equivalenti a dei test
preesistenti. Perciò solo di questi è stato possibile fare un confronto diretto in termini di tempod’esecuzione. Dalle interviste fatte agli sviluppatori di O3-DPACS (5 persone) sono stati ricavati dei
dati soggettivi sui tempi d’esecuzione da cui sono emersi i seguenti dati.
Tipo di test Prima Dopo
Unit Test 2-15 minutiImmediati ed automatici
Functional Test 15-60 minuti
È stato possibile distinguere due categorie di test a seconda del tempo necessario per la loro
esecuzione. Quelli che ho qui riportato come “Unit Test” sono quelli più semplici e veloci, la cui
verifica non richiede più di 15 minuti. Ve ne sono altri che sono più complessi e che possono
richiedere fino a 60 minuti. In entrambi i casi con la nuova infrastruttura la loro esecuzione è
immediata ed automatica.
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
51
Glossario
HL7: standard internazionale che definisce un protocollo di comunicazione tra sistemi informativisanitari
DICOM: standard per la diagnostica di immagini
IHE: iniziativa internazionale che promuove l’interoperabilità tra sistemi informativi sanitari
attraverso l’indicazione di standard e processi comuni per facilitare l’integrazione tra software
ospedalieri eterogenei.
XDS-I: profilo di IHE per la condivisione di “puntatori” dicom (Key Object Selection, KOS) tra sistemi
informativi diversi.
JMX: Java Management Extension, tecnologia Java che consente la pubblicazione di interfacce per lagestione delle applicazioni java. Le interfacce sono chiamate MBean e vengono registrate in un
MBeanServer con un nome univoco. Tramite l’MBeanServer è possibile invocare i metodi esposti
dagli MBean, ai quali si possono anche passare dei parametri, consentendo così la configurazione a
runtime di applicazioni tramite un’interfaccia standard.
JNDI: è una API java per servizi di directory quali LDAP, RMI, DNS. Nei container Java Enterprise è
utilizzato per registrare risorse messe a disposizione dal container per le applicazioni che vi sono
ospitate. Tra queste risorse ci sono i DataSource per la connessione ai DMBS.
SVN: Subversion, sistema per la gestione del versionamento di codice sorgente.
Bibliografia
[1] UNI EN ISO 13485:2003
[2] UNI CEN ISO/TR 16969 (guida per l’applicazione della 13485)
[3] CEI EN 60601-1-4 norme generali per la sicurezza (sistemi elettromedicali programmabili)
[4] CEI EN 62304 Norma (Software per dispositivi medici – processi relativi al ciclo di vita delsoftware)
[5] Manuale per la classificazione dei dispositivi medici “borderline” http://ec.europa.eu/health/medical-devices/files/wg_minutes_member_lists/borderline_manual_ol_en.pdf
[6] M. Fowler, D. Rice, M. Foemmel, E. Hieatt, R. Mee, R. Stafford
Patterns of Enterprise Application Architecture - Addison-Wesley Professional, 2002
[7] P. Tahchiev, F. Leme, V. Massol, G. Gregory
JUnit in Action, Second Edition - Manning Publications, 2010
[8] Graham Bath, Judy McKay
The Software Test Engineer's Handbook - Rocky Nook, 2008
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
52
Appendice
o3 Consortium & o3 Enterprise Projects Management
Displaying 48 issues at 21/Feb/12 09:32:54 AM.
IssueType
Summary Area
SYS Bug Sometimes the second instance of a study is not stored in fastestAccess database
SYS Bug Change class Dbms to include the chance to use both Oracle and non-Oracledatasources
SYS Bug Oracle out of resources: ORA-01000 maximum open cursors exceeded
SYS Bug Correct getRetrievalInfo under Oracle
SYS Bug On Oracle: querying by study date brings an Exception
SYS Bug [StorageCommitment] Unable to retrieve information, the queries executed on PACSDB are wrong
SYS Bug Problems in inserting records in "Images" table
SYS Bug [CMove] The connection is released before the ack by the SCP dicom
SYS Bug Cancel and Abort seem not to work properly
SYS Bug C-FIND: when asking ProcedureCodeSeq a NullPointerException is thrown
SYS Bug [MoveServer] If at least patient id is specified, the system throws an Exception
SYS Bug Correct getDataForCMove and getRetrievalInfo
SYS Bug C-FIND: Check that Required fields are supported correctly
SYS Bug Presentation Contexts may not be handled properly
SYS Bug Move Dealer does not retrieve results by called by WADO, when this is called usingprivate ip
SYS Bug O3-DPACS ignores c-cancel requests
SYS Bug CalledAET is never checked
SYS Bug [Query] Ranged matching on the studies doesn't work (in modality "from Date")
SYS Bug [ForwarderService] Service locks down after first run service
SYS Bug The timer which checks whether the storage media is running out of space does notconsider the media type
SYS Bug Services don't start from web if autostart is not used
SYS Bug [Dicom Server and HL7 Server] The configuration isn't reloaded correclty
SYS Bug Forwarder Service doesn't work on Oracle
SYS Bug Compressing and storing images with jai not properly installed, fails. A success statusis however returned.
storage
SYS Bug Storage media could not save the image
SYS Bug Worklist search on intervals are not cross-dbms worklist
SYS Bug Worklists: management of timestamps in other DBs
SYS Bug [Worklist] Some Modality SCU refuse the worklist
SYS Bug Not all Worklist tags are treated correctly
SYS Bug [WorkList] if the third party view doesn't contain all aspected comlumns, the worklistserver throw up an exception.
SYS Bug [Worklist] The system put SPSStartDate in the PatientBirthdate Dicom Tag
SYS Bug ADT A40 should not update the target information
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
53
SYS Bug Single quotes in Patient Id do not allow proper storage
SYS Bug Multiframe generation: wrong series UID in generated file
SYS Bug Some exceptions are fake and need to be removed
SYS Bug Memory consumption too high when processing hash
SYS Bug If Procedure Code Sequence is requested, possible nullpointer exception
SYS Bug If more than two MBeanServers are registered on MBeanServerFactory ambiguos logmessage are sended.
SYS Bug [Image Masking] If there is a difference between TS saved in FileMetaInfo andTranferSyntax dicom tag image masking propagates this discrepany and dcm4che libthrow an Exception
SYS Bug The creation of ATNA message has not to be blocking, Better management of presentation context and transfersyntax
SYS Bug FORWARDER: When deleting a study, update the available bytes in PhysicalMedia
SYS Bug installation following the instructions fails
SYS Bug IMAGEIO Bug: Use a jai_imageio.jar released later than Dec 4 2007
SYS Bug exception on duplicated ProtocolCodeSequence...
SYS Bug if there isn't any Node config in the DB the o3-dpacs servers note start.
SYS Bug If the node has the compressione enabled but does not accept compressed images,O3-DPACS should not compress them when sending.
SYS Bug when Patient ID is the same between two patients, O3-DPACS should not accept thestudy
SYS Bug when Anonymization is enabled, query with teh patient first name, last name andbirdth day should be disabled
Generated at Tue Feb 21 09:32:54 CET 2012 by Giacomo Petronio using JIRA 4.2.4-b591#591.
6 - Estrazione dei bug del sistema e suddivisione per aree
Stored Procedure Tipo Categoria Classe di test
ADDNEWPATIENT insert patient InsertPatientStoredProceduresTest
ADDNEWSTUDY insert study StudyStoredProceduresTest
ADDSTUDYTRACKING insert availability AvailabilitySPTest
ARCHIVESTUDY update media MediaSPTest
COMPLETEFORWARDPROCESS forward ForwardSPTest COMPLETEMFCREATION mf MultiFrameSPTest
COMPLETEOLDSTUDIES availability AvailabilitySPTest
COMPLETESTUDY availability AvailabilitySPTest
DELETEINSTANCES delete instance InstancesSPTest
DOCHANGEPASSWORD conf ConfigurationStoredProceduresTest
GETALLSERIESFROMSTUDY select series SeriesStoredProceduresTest
GETALLSTUDIESFROMPATIENT select study StudyStoredProceduresTest
GETDATAFORCMOVE move MoveSPTest GETEMAILCONFIGURATIONS select email EmailStoredProceduresTest
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
54
GETEMAILFROMROLEFK select email EmailStoredProceduresTest
GETEVENTEMAIL select email EmailStoredProceduresTest
GETGLOBALCONFIGURATION select conf ConfigurationStoredProceduresTest
GETINSTANCES select instance InstancesSPTest
GETORCREATEPATIENT insert patient InsertPatientStoredProceduresTest
GETPASSWORDCONSTRAINTS conf ConfigurationStoredProceduresTest
GETPATIENTBASICINFO select patient SelectPatientStoredProceduresTest
GETPATIENTBASICINFOAN select patient SelectPatientStoredProceduresTest
GETPATIENTHL7CONTEXTSTUDIES select patient SelectPatientStoredProceduresTest
GETPATIENTINFO select patient SelectPatientStoredProceduresTest
GETPATIENTINFOFORRECO select patient SelectPatientStoredProceduresTest
GETRETRIEVEALINFO OthersSPTest
GETSERIESBASICINFO select series SeriesStoredProceduresTest
GETSERIESINSTANCES select instance InstancesSPTest
GETSTUDIESFORMOVEVISIT select move MoveSPTest
GETSTUDIESTOVERIFY select studyverifier StudyVerifierSPTest
GETSTUDYBASICINFO select study StudyStoredProceduresTest
GETSTUDYBASICINFOAN select study StudyStoredProceduresTest
GETSTUDYINFOFORRECO select study StudyStoredProceduresTest
GETURLTOINSTANCE media MediaSPTest GETUSERFOREMAIL select email EmailStoredProceduresTest
GETVERIFIEDSTUDIESINSTANCES select studyverifier StudyVerifierSPTest
IAINSERTCORRECTSTUDIES availability AvailabilitySPTest
IAINSERTCORRECTSTUDY availability AvailabilitySPTest
IARECONCILEWRONGSTUDY availability AvailabilitySPTest
IASWAPPATIENTASSOCIATION availability AvailabilitySPTest
INITSCHEDULEPROCESS OthersSPTest
INSERTHL7ALLERGY insert patient InsertPatientStoredProceduresTest
INSERTHL7OBSERVATION insert patient InsertPatientStoredProceduresTest
INSERTKOSRELATIONSHIP insert OthersSPTest
INSERTSTUDYTOVERIFY insert studyverifier StudyVerifierSPTest
INSERTVERIFIEDDATE update studyverifier StudyVerifierSPTest
ISCONVERTED mf MultiFrameSPTest
ISUSERAUTHENTICATED conf ConfigurationStoredProceduresTest
MAPSETTINGFROMMEDIATOSTUDY OthersSPTest
MOVESTUDY move MoveSPTest
MOVESTUDYTOPATIENT move MoveSPTest
5/14/2018 Progetto e realizzazione di un infrastruttura di test per un sistema PACS - slid...
http://slidepdf.com/reader/full/progetto-e-realizzazione-di-uninfrastruttura-di-test-per-un
55
MOVEVISIT move MoveSPTest
REMOVEKOSRELATIONSHIP OthersSPTest
RESETSTUDIESTORECONCILE study StudySPTest
RETRIEVEVISITPERSTUDY select study StudySPTest
ROLLBACKCONVERSIONDATE mf MultiFrameSPTest
SELECTFORWARDEDSTUDIES select forward ForwardSPTest
SELECTSTUDIESTOARCHIVE select forward ForwardSPTest
SELECTSTUDIESTOFORWARD select forward ForwardSPTest
SETEXPIRATIONDATE update conf ConfigurationStoredProceduresTest
UPDATEFORWARDEDSCHEDULE update forward ForwardSPTest
UPDATEFORWARDSCHEDULE update forward ForwardSPTest
UPDATEPASSWORD update conf ConfigurationStoredProceduresTest
UPDATEPATIENTINFORMATION update patient UpdatePatientStoredProceduresTest
UPDATEPHYSICALMEDIASIZE update media MediaSPTest
UPDATESCHEDULE update forward ForwardSPTest
Tabella 7 - Classificazione delle stored procedure