Nello scorso post ho fatto un mare di chiacchere, ma non sono ancora arrivato al succo di come si creano praticamente gli unit-test.

Mi è sembrato corretto dare prima degli elementi di contesto per meglio comprenderne fini e utilizzi.

Poi tutto sommato a pensarci bene il blog è mio, per cui per quale motivo mi devo giustificare ??

Quindi dicevo: gli unit-test sono una metodologia che permette di programmare dei test in modo automatico.

L’idea è quella di isolare dal contesto gli elementi principali del software e programmare dei test continui per assicurarne il corretto funzionamento.

Tutto questo suona bene, ma… non è tutto oro quello che luccica. Infatti implementare gli unit-test è indubbiamente faticoso, e introduce anche la necessità di conoscere tutta una serie di strumenti che servono semplicemente a favorire i test, e a null’altro.

In questa piccola serie proporrò due di questi strumenti che ritengo indispensabili: xUnit e Moq.

 

Un primo esempio

Immaginiamo di dover scrivere una libreria che implementi una classe che propone semplici calcoli matematici.

Creiamo a tal scopo un progetto libreria (Class Library .Net Framework in C#) che chiameremo BizMathLib: l’unica classe del progetto ha la struttura nel seguito.

 

L’intento è quello di creare una serie di unit-test che dovranno testare il funzionamento dei due metodi sopra.

Per fare questo è buona norma porre questi test in un progetto separato che conterrà esclusivamente gli unit-test per la libreria in analisi.

Per fare questo è possibile creare un nuovo progetto nella medesima solution di tipo xUnit Test Project): quest’ultimo dovrà riferire il progetto che contiene i metodi da testare, per cui TestBizMathLab.

Successivamente possiamo concentrare la nostra attenzione sulla classe del progetto di unit-test che è stato creato dal template, e modificarla come nel seguito.

Nella classe UnitTestBizMath abbiamo approntato ben due unit-test, ognuno dei quali verifica la funzionalità dei due metodi della classe BizMath.

Prima di proseguire è possibile evidenziare che uno unit-test coincide con un metodo di una classe contenuta in una progetto di di tipo xUnit, e che a sua volta è decorato con [Fact].

Una cosa interessante è che all’interno di una classe possono essere contenuti un numero arbitrario di unit-test, vale a dire di metodi marcati con [Fact].

Oss.: All'interno della stessa classe possono coesistere anche metodi NON marcati con [Fact]: vengono considerati come di utility o appoggio.

Analogamente un progetto xUnit può contenere un numero assolutamente arbitrario di classi contenenti a loro volta unit-test.

Il nome di ogni classe, così come di ogni metodo/unit-test, è assolutamente arbitrario: comunque è buona norma seguire un corretto naming-convention.

In generale il nome della classe è qualcosa tipo il seguente.

UnitTest + Nome della classe in test

Quindi nel nostro caso UnitTestBizMath.

Il metodo dovrebbe indicare il tipo di test in analisi.

Nome Metodo in test + Cosa si sta testando + risultato atteso.

All’interno dello unit-test si segue di solito un pattern chiamato delle tre A: Arrange, Act e infine Assert.

Arrange indica che si preparano le condizioni per eseguire il test (si instanziano variabili o si creano oggetti).

Nella fase Act si esegue il codice da testare e si raccolgono i risultati: infine in Assert si confronta il risultato ottenuto con quello atteso.

Qualche parola sulla terza A occorre farla: per eseguire Assert si usa in modo originale una classe chiamata Assert, fornita dal framework xUnit, e che propone dei metodi statici per eseguire il confronto tra il risultato atteso/ottenuto.

Nel caso dello unit-test ApplicaIva_IvaApplicataA100 si è usata l’assert che indica che se il risultato è uguale a un valore prestabilito, allora lo unittest risulta essere con esito positivo: per fare questo si è usato il metodo Equal che ha come primo argomento il risultato atteso, e come secondo il risultato ottenuto dal codice in esecuzione e che deve essere testato.

Assert comunque propone anche altri metodi statici, alcuni dei quali (quelli che ritengo i più utilizzati) sono presentati nella tabella nel seguito.

NotEqual Il test è passato quando i valori differiscono
True Il test è passato se il valore argomento è true
InRange Il test è passato se il valore è nel range di valori specificato
Contains Il test è passato se un valore è presente nella lista di valori del secondo argomento

 

Occorre dire che all’interno di uno unit-test possono essere poste più righe di Assert: in tal caso lo unit-test si intende passato e soddisfatto se tutti gli Assert danno risultato positivo.

Comunque l’idea fondante dovrebbe essere che ogni unit-test dovrebbe testare solo una funzionalità particolare, e quindi teoricamente dovrebbe proporre un solo Assert: nel caso sopra il secondo assert ha senso, secondo me, perché si vuole testare un caso particolare, cioè se tutto funziona correttamente anche in presenza di cifre con la virgola.

Ora che abbiamo apparecchiato per bene questi due unit test come si possono eseguire ?

Visual Studio ha il supporto per rilevare tutti gli unit test presenti nelle varie classi, e quindi marcati con Fact, ed eseguirli.

Lo strumenti usato, in questo caso, è il Test Explorer. Per eseguire detto test da Visual Studio agire su Test → Run → Run all test.

Visual Studio, con l’ausilio di xUnit.net, eseguirà tutti i test che troverà nella solution e visualizzerà il risultato.

Particolarmente utile è il fatto che dalla stessa maschera è anche possibile eseguire il debug di detti test, al fine di comprendere meglio eventuali errori o risultati strani proposti.

Oss.: Osservo che negli esempi di questa serie verrà utilizzato xUnit per eseguire unit-test: questo, comunque, non non rappresenta l’unico sistema. Ovviamente sistemi diversi da xUnit avranno nomenclature e metodi per corredare i metodi/test differenti da quanti qui esposto.

Linkografia

Informatica pressapochista - Un viaggio negli unit-test: Introduzione - Prima parte
Informatica pressapochista - Un viaggio negli unit-test: xUnit e dintorni – Seconda parte
GitHub Page Informatica Pressapochista
Home Page xUnit