Mokabyte

Dal 1996, architetture, metodologie, sviluppo software

  • Argomenti
    • Programmazione & Linguaggi
      • Java
      • DataBase & elaborazione dei dati
      • Frameworks & Tools
      • Processi di sviluppo
    • Architetture dei sistemi
      • Sicurezza informatica
      • DevOps
    • Project Management
      • Organizzazione aziendale
      • HR
      • Soft skills
    • Lean/Agile
      • Scrum
      • Teoria della complessità
      • Apprendimento & Serious Gaming
    • Internet & Digital
      • Cultura & Società
      • Conferenze & Reportage
      • Marketing & eCommerce
    • Hardware & Tecnologia
      • Intelligenza artificiale
      • UX design & Grafica
  • Ultimo numero
  • Archivio
    • Archivio dal 2006 ad oggi
    • Il primo sito web – 1996-2005
  • Chi siamo
  • Ventennale
  • Libri
  • Contatti
Menu
  • Argomenti
    • Programmazione & Linguaggi
      • Java
      • DataBase & elaborazione dei dati
      • Frameworks & Tools
      • Processi di sviluppo
    • Architetture dei sistemi
      • Sicurezza informatica
      • DevOps
    • Project Management
      • Organizzazione aziendale
      • HR
      • Soft skills
    • Lean/Agile
      • Scrum
      • Teoria della complessità
      • Apprendimento & Serious Gaming
    • Internet & Digital
      • Cultura & Società
      • Conferenze & Reportage
      • Marketing & eCommerce
    • Hardware & Tecnologia
      • Intelligenza artificiale
      • UX design & Grafica
  • Ultimo numero
  • Archivio
    • Archivio dal 2006 ad oggi
    • Il primo sito web – 1996-2005
  • Chi siamo
  • Ventennale
  • Libri
  • Contatti
Cerca
Chiudi

Nel numero:

99 settembre
, anno 2005

Pratiche di sviluppo del software

VI – Code Coverage

Marco Piraccini e Stefano Rossini

Marco Piraccini

Marco Piraccini è nato a Cesena il 09/10/1975. E‘ laureato in Ingegneria Informatica presso la facoltà di Bologna con una tesi sull‘assessment della maturità del processo di testing e
in Fisica Computazionale presso la facoltà di Udine con una tesi sull‘uso di GRID per le simulazioni Monte Carlo (nell‘ambito di un esperimento di astrofisica).
Attualmente lavora come Software Architect per una società di consulenza. Il suo Blog è disponibile al seguente indirizzo: http://darkav.blogspot.com/

Marco Piraccini e Stefano Rossini

Stefano Rossini

Stefano Rossini è nato a Giussano (MI) il 29/10/1970 e ha conseguito il diploma universitario in Ingegneria Informatica presso il Politecnico di Torino. Ha maturato più di venti anni di esperienza in diversi progetti Enterprise mission-critical ricoprendo i ruoli di IT Program Manager, Project Manager & Software Architect presso importanti gruppi bancari, pubblica sanità, pubblica amministrazione e software house.

Attualmente ricopre il ruolo di Sofware Factory Manager, Lean Change Agent ed Enterprise Architect presso Capgemini.

Esperto in ambito di sanità pubblica come Project/Program Manager per la governance dei progetti IT strategici di Cartella Clinica Elettronica (CCE) e Fascicolo Sanitario Elettronico (FSE).

Esperto in ambito bancario dove ha ricoperto per una decina d'anni il ruolo di Project Manager e Leader Software Architect (BPM, IWBank e BPS) occupandosi della pianificazione e gestione del progetto, del coordinamento del gruppo di sviluppo software sia InHouse che Nearshore/Offshore. Esperto nella conduzione di progetti secondo metodologia di Project Management PMBok e metodologia agile Scrum.

Si occupa di Java dal 1999 arrivando da precedenti esperienze in C e C++ in ambito Telco (Alcatel & Siemens). Ha pubblicato più di un centinaio di articoli su argomenti di IT Governance, Project Management, architetture enterprise e problematiche di Integrazione e SOA. È coautore dei libri "Manuale pratico di Java" (2001) e "La programmazione della piattaforma J2EE" (2005) editi da Hops/Tecniche Nuove. Certificazioni IT Governance: COBIT V.4.1 Foundation Certificate; certificazioni IT Service Management: ITIL V.3 Foundation Examination; certificazioni Project Management: CSM - Scrum Master, CSPO - Scrum Product Owner, PMI: 35 contact hours.

Profilo linkedin: http://www.linkedin.com/pub/stefano-rossini/30/977/242

MokaByte

Pratiche di sviluppo del software

VI – Code Coverage

Marco Piraccini e Stefano Rossini

Marco Piraccini e Stefano Rossini

Le misure di copertura sono importanti per definire il grado di affidabilità delle suite di test e quindi, indirettamente, per verificare la qualità del codice che viene testato tramite esse.

Introduzione

Nei precedenti numeri apparsi su MokaByte nella sezione Metodologia si è parlato di Test Driven Development (vedere [MOKA_TDD]) e di qualità  del Software (vedere [MOKA_QS_1] e [MOKA_QS_2]).

In [MOKA_QS_1]) si è parlato di qualità  a livello di codice e si è visto come, applicando delle regole di audit sul codice prodotto, sia possibile migliorarne la qualità  nel rispetto delle Code Convention e/o Linee guida proposte.

Si è visto come partendo da un codice di esempio che gestiva una semplice conversione da lire in euro, applicando le regole di audit definite da Sun (Sun Code Conventions) e utilizzando il prodotto Open Source Checkstyle (vedere[CHECKSTYLE]) il codice risultasse di bassa “qualità “:

Applicando le regole di audit sul codice, Checkstyle può creare un report HTML. Nel caso in esame si erano rilevate ben 11 violazioni delle Sun Code Convention.

Rimuovendo gli errori di codifica (code e naming convention disattese) il codice è risultato essere, dal punto di vista prettamente della qualità  sintattica e stilistica, migliore sia in termini di leggibilità  che di coerenza.

Ovviamente un codice che rispetta delle linee guida di codifica non è necessariamente corretto funzionalmente e robusto.

Com‘è possibile verificare/certificare la correttezza del funzionamento del codice?
Le metodologie di test possono dare un concreto aiuto in questa direzione.

Ad esempio, la presenza di test funzionali ed i test di unità  può dare una misura della correttezza e la robustezza del software.

I test funzionali hanno lo scopo di verificare il corretto funzionamento “ai morsetti” del sistema (end-to-end). Normalmente chi definisce questi test non conosce il comportamento “interno” del software, quindi questi test vengono disegnati seguendo una strategia “black box”.
Viceversa, la strategia “white-box” presume che i test vengano definiti sulla base della conoscenza del funzionamento interno del sistema. I test di unità , il cui scopo è di verificare la correttezza di singole componenti del sistema, e che normalmente sono di responsabilità  degli sviluppatori, possono essere definiti utilizzando una strategia white-box, o un approccio “ibrido”.

In XP i test funzionali (Functional Test) sono stati rinominati test di accettazione (Acceptance Test) per enfatizzare che i test devono dimostrare/garantire l‘aderenza del prodotto SW ai requisiti e di conseguenza mettere in grado il Customer di accettare o meno il prodotto SW mediante la definizione di precisi criteri di accettazione (Acceptance Criteria). Di fatto in XP si cerca di portare le tematiche/problematiche di Qualità  Assurance piu‘ vicine al gruppo di sviluppo di quanto non avvenga generalmente, nella maggior parte dei casi infatti il Q&A viene gestito da un team di lavoro indipendente e separato dallo sviluppo.

E‘ importante notare come gli stessi test di accettazione diventino anche importantissimi per verificare sistematicamente la non regressione del sistema (vedere [MOKA_TDD]). Questo è ovviamente vero anche per le suite di unit tests.

Quindi, mentre la qualità  dei test di accettazione è misurata implicitamente con la verifica dei requisiti del cliente, occorre definire una metodologia per misurare la qualità  delle suites di unit test. Questo è importante perché altrimenti non sappiamo quando possiamo “fidarci” di una suite di test o, in generale, non possiamo controllare quello che non riusciamo a misurare.

I parametri più comunemente utilizzati per la misura quantitativa della qualità  dei test sono le misure di copertura.

Esistono in letteratura varie tipologie e livelli di copertura misurabili. Ne descriveremo alcune fra le più comuni.

Tipologie e livelli di copertura del code coverage

  • Statement coverage

Conosciuto anche come “line coverage”, è la misura definita dal numero di linee di codice eseguite dalla suite di test sul numero totale di linee. E‘ evidentemente la misura più semplice che si può effettuare. Misure simili (ma più grossolane) sono la copertura dei metodi (method coverage) o delle classi (class coverage).

  • Block coverage

Simile allo statement coverage, il block coverage considera ogni sequenza di codice “consecutiva” (cioè senza biforcazioni) come un blocco. Questo serve a considerare correttamente casi del tipo:

if (condizione) {99 righe di codice} else {1 riga di codice bacata...}

Un test con condizione = true copre le linee al 99% (che, guardando solo i numeri, è un ottimo risultato), ma solo un 50% sulla misura di block coverage…
Questo dimostra che lo statement coverage, il tipo di copertura più intuitivo, può essere fuorviante!

  • Branch coverage

Si possono considerare altri casi in cui lo statement coverage può dare dei risultati ingannevoli, ad esempio:

Integer var = null;if (condizione) {var = new Integer(0);} return var.toString();

Questo codice ha una misura di statement coverage al 100% (se condizione=true), ma se condizione=false, genera una NullPointerException.
Introduciamo quindi la misura di branch coverage, che ci dice quanti dei possibili rami del codice sono stati coperti. In realtà  questo tipo di misura non è frequente, in quanto è molto complesso riuscire a determinare tutti i possibili percorsi. Mentre per uno statement di if è semplice (ma in questo caso si riesce a comunque a determinare una copertura corretta anche tramite block coverage), non è sempre semplice / possibile determinare la copertura di cicli di cui non si conosce a priori il numero di esecuzioni. Da notare che nemmeno questo tipo di copertura (che normalmente non viene effettuato se non in casi semplici) protegge da alcune tipologie di errore….

  • Condition Coverage

Prendiamo ad esempio il pezzo di codice:

if ((somma != null) || (somma.equals(""))) {System.out.println("Somma non e‘ null");}

Se questo pezzo di codice viene eseguito da un test con somma != null, si ottiene 100% alla misura di statement coverage, block coverage e branch coverage…però la seconda condizione booleana non viene coperta e contiene un errore. La misura della percentuale di esecuzione delle condizioni è chiamata condition coverage.

Utilizzo delle misure di copertura

Un criterio quantitativo di copertura viene spesso utilizzato come soglia, (es. 90% degli statement) raggiunta la quale l‘attività  di testing viene considerata troppo costosa e viene quindi interrotta. E‘ chiaro che occorre raggiungere un giusto compromesso (dove “giusto” dipende da molti fattori, non ultima la criticità  del software prodotto) tra risultati di copertura e numero/qualità  dei test della suite.

Inlotre si possono usare queste misure per valutare l‘efficacia di una fase preliminare di testing funzionale e per capire se questa ha lasciato scoperte (non esercitandole) alcune strutture del programma.

Esempio

I concetti descritti in questo articolo sono stati provati tramite il tool OpenSource di misura della copertura “Emma”, uno dei tanti disponibili (vedere bibligrafia).
Emma può fornire misure di copertura di classe, metodo, statement e blocchi. Inoltre può produrre dei report html in cui visualizza (con colori diversi) le righe non eseguite.
Le righe contenenti espressioni booleane in cui non tutte le condizioni sono state coperte sono rappresentate in un colore differente (giallo). Non viene quindi data una misura numerica di questo tipo di copertura ma le condizioni non testate possono essere comunque individuate.

Esemplificando quanto detto fino ad ora riprendiamo in esame l‘esempio presentato nei precedenti numeri … un po‘ “triviale” ma (speriamo!) efficace.

Supponiamo di avere verificato il funzionamento della classe EuroConverter con la seguente classe di Test JUnit:

public class ConverterTestCase extends TestCase {protected void setUp() {}protected void tearDown() {}public ConverterTestCase(String string) {super(string);}public void testConvertiEuroInLire() {  try {double res=EuroConverter.convertiLireInEuro("1936.27");assertEquals("Non ho ottenuto la conversione prevista:","1.0",""+res);} catch (Exception ex) {fail(ex.getMessage());}} public static Test suite() {TestSuite suite = new TestSuite("Converter TestSuite");suite.addTest(new ConverterTestCase("testConvertiEuroInLire"));return suite;}}

dove la classe EuroConverter è la seguente:

public class EuroConverter{/** Valore in lire dell‘euro */private static final double EURO = 1936.27;private EuroConverter(){} // ... per didattica/** Converte le lire in euro * @param  somma il valore delle lire da convertire * @return il corrispondente valore in euro * @throws ConversionException se la somma non e‘ un valore valido */public static double convertiLireInEuro(String somma) throws Exception{System.out.println("EuroConverter.convertiLireInEuro: valore arrivato["+somma+"]...");if ((somma != null) || (somma.equals(""))) {System.out.println("Somma non e‘ null"); // ... per didattica }if(somma == null || "".equals(somma.trim())) { String errMsg = "convertiLireInEuro: ERRORE ! Somma["+somma+"] da convertire NON valida!";System.out.println(errMsg);throw new Exception(errMsg);}double valoreSomma=0;try{valoreSomma=Double.parseDouble(somma);}catch(NumberFormatException nfe){nfe.printStackTrace();throw new Exception("Conversione Double in Stringa fallita: " + nfe.getMessage()); }System.out.println("convertiLireInEuro: valore somma da convertire["+valoreSomma+"]...");return valoreSomma/EURO;}}

Eseguendo il test si ottiene un report HTML che riporta una copertura di classe del 100% (l‘unica classe è stata testata), una copertura di metodo del 50% (manca l‘esecuzione del costruttore della classe), una copertura di blocco del 60% e di linee del 53%

Andando in dettaglio sulla copertura della classe, è interessante notare che esistono due blocchi non coperti, (le righe non eseguite sono in rosso) e una condizione parzialmente coperta (in giallo) che nasconde un bug (con somma uguale a null si avrà  un NullPointerException dovuto alla seconda condizione in OR: somma.equals(“”)).

Da questo report si capisce come la classe di test non sia sufficiente.
Quantomeno bisogna aggiungere dei nuovi metodi di test che prevedano i casi di test con somma=null,somma valga stringa vuota e che somma contenga una stringa non numerica

Conclusioni

Le misure di copertura sono importanti per definire il grado di affidabilità  delle suites di test e quindi, indirettamente, la qualità  del software che viene da loro testato. Le metriche che sono state introdotte sono metriche strutturali, e la loro misura deve essere vista come complementare alla verifica di copertura funzionale da parte dei Functional Test.

In conclusione, abbiamo aggiunto, all‘audit del codice e al test funzionale, un nuovo strumento metodologico per aumentare la nostra confidenza sulla qualità  del codice prodotto.

Esempi

Dal menu in alto a sinistra, è possibile scaricare gli esempi appena visti

Riferimenti bibliografici

[MOKA_TDD]
S. Rossini, “Pratiche di sviluppo del software. Parte I: Test Driven Development”, MokaByte 86, Giugno 2004

[MOKA_QS_1]
S. Rossini: “Qualità  del software.Parte I: Auditing del codice”, Mokabyte 90, Novembre 2004

[MOKA_QS_2]
S. Rossini: “Qualità  del software. Parte II: I Test”, Mokabyte 91, Dicembre 2004

[CCA]
S. Cornett, “Code Coverage Analysis”
http://www.bullseye.com/coverage.html#intro

[HTMCC]
B. Marick, “How to Misuse Code Coverage”
http://www.testing.com/writings/coverage.pdf

[AFIT]
Il Testing
http://www.dsi.unifi.it/~fantechi/INFIND/testing.ppt

[OSCCTJ]
Open Source Code Coverage Tools in Java
http://java-source.net/open-source/code-coverage

[EMMA]
http://emma.sourceforge.net

[SATDD]
Scott W. Ambler, “Test Driven Development”
http://www.agiledata.org/essays/tdd.html

[KBTDD]
Kent Beck, “Test Driven Development: By Example”, Addison Wesley

[TFD]
Michael Feathers, “Test First Design”
http://www.xprogramming.com/xpmag/test_first_intro.htm

[SSJCC]
Selezione dei tools di code coverage per Java
http://europetravelogue.com/blog/pivot/entry.php?id=41

[JUNIT]
http://www.junit.org/index.htm

 

Facebook
Twitter
LinkedIn
Marco Piraccini e Stefano Rossini

Marco Piraccini

Marco Piraccini è nato a Cesena il 09/10/1975. E‘ laureato in Ingegneria Informatica presso la facoltà di Bologna con una tesi sull‘assessment della maturità del processo di testing e
in Fisica Computazionale presso la facoltà di Udine con una tesi sull‘uso di GRID per le simulazioni Monte Carlo (nell‘ambito di un esperimento di astrofisica).
Attualmente lavora come Software Architect per una società di consulenza. Il suo Blog è disponibile al seguente indirizzo: http://darkav.blogspot.com/

Marco Piraccini e Stefano Rossini

Stefano Rossini

Stefano Rossini è nato a Giussano (MI) il 29/10/1970 e ha conseguito il diploma universitario in Ingegneria Informatica presso il Politecnico di Torino. Ha maturato più di venti anni di esperienza in diversi progetti Enterprise mission-critical ricoprendo i ruoli di IT Program Manager, Project Manager & Software Architect presso importanti gruppi bancari, pubblica sanità, pubblica amministrazione e software house.

Attualmente ricopre il ruolo di Sofware Factory Manager, Lean Change Agent ed Enterprise Architect presso Capgemini.

Esperto in ambito di sanità pubblica come Project/Program Manager per la governance dei progetti IT strategici di Cartella Clinica Elettronica (CCE) e Fascicolo Sanitario Elettronico (FSE).

Esperto in ambito bancario dove ha ricoperto per una decina d'anni il ruolo di Project Manager e Leader Software Architect (BPM, IWBank e BPS) occupandosi della pianificazione e gestione del progetto, del coordinamento del gruppo di sviluppo software sia InHouse che Nearshore/Offshore. Esperto nella conduzione di progetti secondo metodologia di Project Management PMBok e metodologia agile Scrum.

Si occupa di Java dal 1999 arrivando da precedenti esperienze in C e C++ in ambito Telco (Alcatel & Siemens). Ha pubblicato più di un centinaio di articoli su argomenti di IT Governance, Project Management, architetture enterprise e problematiche di Integrazione e SOA. È coautore dei libri "Manuale pratico di Java" (2001) e "La programmazione della piattaforma J2EE" (2005) editi da Hops/Tecniche Nuove. Certificazioni IT Governance: COBIT V.4.1 Foundation Certificate; certificazioni IT Service Management: ITIL V.3 Foundation Examination; certificazioni Project Management: CSM - Scrum Master, CSPO - Scrum Product Owner, PMI: 35 contact hours.

Profilo linkedin: http://www.linkedin.com/pub/stefano-rossini/30/977/242

Marco Piraccini e Stefano Rossini

Marco Piraccini e Stefano Rossini

Tutti gli articoli
Nello stesso numero
Loading...

Soluzioni Oracle per la scalabilità

Come rendere scalabili le applicazioni Oracle

Il nome della cosa

Sun rivede e uniforma i nomi delle proprie piattaforme

Spring Web Flow in un esempio pratico

Il Jug Avis Web (aka MagicBox)

Il networking in Java

II parte: il TCP e i socket

Validare il codice Java

Preveniamo lo spaghetti code

Multimedialità su J2ME

IV parte: riproduzione, registrazione e transcodifica video

Autenticazione password crittografata

Una semplice applicazione Struts

Integrazione di applicazioni Enterprise

Parte VIII: l‘Enterprise Integration Component Server di Librados

MokaCMS – Open Source per il Web Content Management

VII parte: Da XML ad PDF utilizzando XSLT e FO (seconda puntata)

Nella stessa serie
Loading...
Mokabyte

MokaByte è una rivista online nata nel 1996, dedicata alla comunità degli sviluppatori java.
La rivista tratta di vari argomenti, tra cui architetture enterprise e integrazione, metodologie di sviluppo lean/agile e aspetti sociali e culturali del web.

Imola Informatica

MokaByte è un marchio registrato da:
Imola Informatica S.P.A.
Via Selice 66/a 40026 Imola (BO)
C.F. e Iscriz. Registro imprese BO 03351570373
P.I. 00614381200
Cap. Soc. euro 100.000,00 i.v.

Privacy | Cookie Policy

Contatti

Contattaci tramite la nostra pagina contatti, oppure scrivendo a redazione@mokabyte.it

Seguici sui social

Facebook Linkedin Rss
Imola Informatica
Mokabyte