Cosa fa e a cosa serve NUnit?
NUnit è un framework deputato alla creazione di classi di test.Sono molte le cose che si possono fare con questo framework ma qui ci occuperemo del sistema di test più semplice, ovvero, data una classe, si creano dei test sui metodi di questa classe indicando cosa è atteso in output. Questi test vengono poi eseguiti e si confronta il risultato ottenuto dall'elaborazione con quello atteso e si può rapidamente verificare se l'unità di codice (Unit) funziona correttamente.
Perché dovrei usarlo?
Può sembrare una cosa tanto semplice da risultare inutile, e forse lo è per applicazioni elementari o di piccole dimensioni; ma chiunque abbia passato giorni e giorni a testare un'applicazione di elevata complessità dopo l'implementazione di una nuova release sa bene quale differenza può fare...
Che vantaggio mi può dare NUnit in una applicazione semplice ?
Diciamo innanzitutto che i test automatizzati non possono sostituire in toto quelli manuali infatti le fasi di testing si dividono in
Automatic Testing e
Manual Testing. Il punto è che i test eseguiti a mano dagli utenti dovrebbero limitarsi a fornire informazioni sull'usabilità, sull'interfaccia e sulla possibilità di commettere errori dovuti al fattore umano (doppio click su un tasto di submit di una web application, interfaccia poco intuitiva e conseguente confusione sulle funzionalità, inserimento di dati errati...).
Ai test automatici dovrebbe essere riservato il ruolo di garantire il corretto funzionamento del motore dell'applicazione, ossia dato un corretto input, indipendentemente da come qualsiasi funzione sia stata implementata o da qualunque refactoring vi sia stato apportato, devo ottenere un corretto output.
I vantaggi di questo approccio sono: maggiore velocità, codice scritto meglio (in alcune aziende vige la prassi di versionare il lavoro della giornata solo se i test hanno dato esito positivo), maggiore affidabilità (l'utente umano può sbagliare nel valutare un risultato, il risultato stesso può essere influenzato tanto da un errore nel codice quanto da un errore umano nell'uso dell'applicazione), solo per menzionare i più immediati.
Come installare NUnit sulla macchina di sviluppo
L'installazione di
NUnit è semplicissima, basta scaricare il pacchetto dall'area Download del sito web (
NUnit Download ), scegliendo il pacchetto autoinstallante con estensione MSI per il framework che si vuole utilizzare.
Per esempio, per lavorare col
.NET Framework 2.0 bisognerà scegliere la riga indicante "win .net 2.0", ossia il link al file
"NUnit-2.4.8-net-2.0.msi" (la versione attuale è la
2.4.8) e il download parte in automatico.
Le indicazioni per l'installazione, per chi volesse leggerle, sono fornite passo passo in questa pagina (in inglese):
NUnit Installation Tuttavia l'installazione del framework non presenta davvero alcuna complicazione, facendo doppio click sul file appena scaricato si avvierà una procedura automatica che presenterà la licenza d'uso e chiederà dove salvare i file.
La licenza garantisce a ciascuno di poter usare il programma senza limitazioni, con le sole condizioni di indicare chiaramente se si distribuiscono versioni modificate, che di tali si tratta e non dell'originale.
Si può benissimo lasciare il percorso standard: saranno create le icone sul desktop e nel menu avvio, e in pochi secondi sarà tutto pronto.
Ora che
NUnit è stato installato si può testare, caricando l'apposita classe di test fornita con l'installazione stessa.
Dal menu
File scegliere
Open Project: indicare il percorso di installazione di
NUnit, da lì selezionare la cartella Bin, e in essa il file
NUnitTest.NUnitUna volta caricato il file, è sufficiente premere il tasto
Run per far partire il test.
Ecco come appare un test in cui tutti gli elementi hanno dato un risultato positivo:
Come creare una classe di test con il framework NUnit
La cosa più semplice è creare la classe di test all'interno del progetto stesso da testare.
Si potrebbe anche creare un progetto a parte per i test: in questo caso occorrerebbe semplicemente aggiungere il riferimento all'assembly che deve essere testato. Io personalmente ho trovato più pratico il primo approccio, cioè nello stesso progetto creo la classe e il suo test, anche se forse a lungo andare può creare progetti "disordinati".
Supponiamo comunque di usare questo sistema, di creare cioè la classe di test nello stesso progetto della classe funzionale.
Per prima cosa occorre aggiungere ai riferimenti del progetto quello dell'assembly di
NUnit:
poi si crea la classe di test.
Per iniziare io ho creato appositamente una classe funzionale chiamata "Calcolatrice" che implementa le cinque operazioni di somma, sottrazione, divisione, moltiplicazione e modulo, esponendo cinque metodi che richiedono in input (ovviamente) due numeri Double e restituiscono un Double come risultato.
Per eseguire i test su Calcolatrice occorre creare una classe che chiamerò, per esempio,
testCalcolatrice.vb.
Innanzitutto è necessario che questa classe importi il namespace di
NUnit:
Poi è indispensabile che la classe sia marcata come classe di test con l'attributo
<TestFixture()>, così come in figura:
Vediamo quali sono gli elementi significativi della nostra classe di test:
1) La sub di setup. È la prima che viene eseguita, ed è riconosciuta come tale dall'attributo
: il nome è assolutamente indifferente, l'ho chiamata
Init() ma avrebbe potuto essere
Inizio() o qualsiasi altra cosa.
Si usa per inizializzare gli elementi del test: in questo esempio istanzio la classe da testare e valorizzo le sue proprietà (i numeri su cui eseguire i calcoli) con 10 e 8.
2) La sub conclusiva. Anche questa viene identificata dall'attributo
<TearDown()>, e il nome che scegliamo nell'ambito dell'applicazione è indifferente.
E' l'ultima che viene eseguita: si usa per compiere le operazioni finali del test, nel caso di esempio infatti cancello l'oggetto istanziato.
3) Le varie classi di test
Queste classi, riconosciute dall'attributo
<Test()>, sono quelle che vengono eseguite in sequenza e il cui risultato sarà indicato come un successo o un fallimento in base al confronto fra la condizione attesa e la condizione risultante alla fine.
Come si definisce un test?
Un test si definisce innanzitutto creando una subroutine marcata come
<Test()>, come abbiamo appena visto.
Al suo interno devono essere eseguite tutte le operazioni da testare: la cosa fondamentale è che questa routine contenga l'indicazione del risultato atteso come condizione di riuscita.
Queste indicazioni vengono inserite con gli statement
Assert, come indicato nell'immagine.
Questi statement consentono una flessibilità molto alta rispetto al risultato atteso: è possibile controllare l'eguaglianza, l'identità, un valore booleano, una stringa contenuta in un'altra, e così via fino a controlli più complessi.
Nell'esempio indicato viene controllata l'eguaglianza fra due numeri, cioè lo statement Assert è così formato:
Assert.AreEqual(ValoreAtteso, ValoreRestituito)Per una panoramica sugli
Assert, si veda questo link:
NUnit Assertions Comunque l'installazione di
NUnit ha con sé una guida locale molto completa, che contiene una reference complessiva degli Assert.
Ho scritto il test: ora come lo eseguo ?
Una volta scritta la classe di test, occorre innanzitutto compilarla.
Chi sviluppa con
Visual Studio .NET lo fa dal menu
Genera/Build, come per tutte le altre classi:
Fatto questo, è il momento di eseguire il test.
Apriamo
NUnit, e come abbiamo fatto dopo l'installazione, carichiamo il nostro progetto.
Dal menu
File scegliamo
Open Project e seguiamo il percorso della nostra applicazione, individuando la cartella
\bin, poi (in base a com'è stata generata la classe)
Debug o
Release.
Qui si carica l'exe generato dal compilatore, e in automatico avremo a disposizione la serie di test che abbiamo generato nella nostra classe:
Possiamo eseguirli tutti, oppure uno solo, selezionandolo e scegliendo
Run.
Come si vede, questi test danno tutti un risultato positivo, ovvero tutti i metodi hanno restituito il valore atteso.
Ora modifichiamo il codice del test della sottrazione così da generare un test fallito: anziché
Assert.AreEqual(2, prcCalcolatrice.Risultato)come condizione indichiamo:
Assert.AreEqual(4, prcCalcolatrice.Risultato) N.B. non è necessario tutte le volte eseguire la load del progetto modificato: appena compilata la classe con le modifiche,
NUnit provvede da solo al reloading con la versione aggiornata.
Essendo i due valori 10 e 8, il test ovviamente fallirà per la sottrazione, e la situazione sarà questa:
Come si vede, uno dei test è fallito.
Per avere dettagli sui valori coinvolti basta cliccare, in basso, sul Tab
"Errors and Failures" per mostrare un riassunto dei valori attesi e di quelli risultanti dall'esecuzione:
Link Utili
NUnit Home Page Marco Turrini NUnit .NET Architects NUnit