I vantaggi principali dell’adozione degli unit test sono molteplici: occorre solo valutare se lo sforzo profuso viene ripagato dai vantaggi ottenuti.

> Gli unit test minimizzano l’eventualità che le modifiche introdotte possano in qualche modo inficiare il comportamento del software già rilasciato: detto in altri termini cercano di evitare che quando si eseguono delle modifiche per implementare nuove feature, o anche per risolvere qualche malfunzione, si introducano dei breaking change o anche veri e propri bachi su parti precedentemente funzionanti.

> Scrivere codice adatto per essere testato con gli unit test inevitabilmente obbliga ad utilizzare un’architettura il più possibile aderente ai migliori pattern di programmazione (vedi S.O.L.I.D. e KISS, e in particolare Dependency Injection e Inversion of Control).

> Per software che coinvolgono UI gli unit test favoriscono l’adozione di pattern di programmazione come MVVM o MVC, che disaccoppiano in modo consistente la parte UI dalla parte di logica, con tutti i benefici che questo apporta.

> Il codice per gli unit test documenta in modo chiaro e inequivocabile il funzionamento degli elementi del software, magari anche declinato a casi particolari o situazioni critiche.

....siete convinti ora ???

Nel seguito fornirò alcuni dettagli per implementare in modo corretto il navigator usando il framework FreshMVVM.

La "spieghescion" non sarà assolutamente esaustiva, e tantomeno il mio intento è quello di esporre in modo completo tutte le funzionalità offerte dal framework FreshMVVM.

Lo scopo è semplicemente quello di fare un "crash-course" che in pochi passaggi permettano di appropriarsi delle tecniche necessarie per implementare compiutamente un navigator usando FreshMVVM: daltronde la documentazione ufficiale è molto dettagliata, e per saperne di più Vi rimando ai link segnati in linkografia.

Il primo punto da sapere è che il framework si basa su una navigazione ViewModel2ViewModel, nel senso che quando si intende aprire una View (=pagina) in realtà si richiamerà la ViewModel ad esso associata: mai a poi mai si farà cenno direttamente alla pagina.

Oss.: L'attività di apertura di un nuova View è chiamata anche push, e con questo termine sarà identificata nel seguito.

Questo tipo di logica i funzionamento è assolutamente compatibile con il pattern MVVM: infatti a livello di ViewModel è assolutamente e solo permesso interagire con altre classi di ViewModel.

Ma come fa il framework ad aprire la pagina corretta se si specifica solo il relativo ViewModel ?

Esiste una naming-convention che occorre seguire religiosamente e che permette al framework di risalire alla View data la ViewModel, e viceversa.

Tali convenzione si basa sul fatto che ogni classe ViewModel dovrà avere il proprio nome che termina con il suffisso ViewModel, mentre la relativa pagina View avrà analogo nome però questa volta con il suffisso Page.

AnagraficaClientiViewModel.cs → AnagraficaClientiPage.xaml

Al posto di ViewModel è anche possibile usare PageModel

AnagraficaClientiPageModel.cs → AnagraficaClientiPage.xaml

Ogni ViewModel dovrà necessariamente derivare dalla classe FreshBasePageModel.

Nelle scorse puntate ho parlato solo unit test che riguardano genericamente delle classi: ma quando si scrive software dotato di UI che valenza possono avere questi tipi di test ?

Ovviamente se il software è ben strutturato esisteranno delle classi di servizio atte a implementare logiche di funzionamento e che saranno usate dalla logica di funzionamento della UI: in tale ambito gli unit test possono essere utilizzati per controllarne la logica di funzionamento.

Ma se le UI sono scritte seguendo il pattern MVVM ecco che è possibile è possibile anche fare anche di più.

Siccome la logica di funzionamento di una maschera è proposta dalla relativa classe che rappresenta la ViewModel, ecco che in pratica implementare degli unit test per questa nella pratica corrisponde ad eseguire dei test sul comportamento della UI stessa.

Dirò una cosa che a qualcuno potrebbe fare storcere il naso: io penso che la ragione principale per adottare il pattern MVVM per UI sia proprio quello di poter sottoporre i relativi ViewModel a unit test, in modo tale da eseguire in modo indiretto la verifica del corretto funzionamento che avranno le relative UI.

E’ importante però sottolineare che se si vuole scrivere con successo degli unit-test per un ViewModel occorre essere certi che questa sia stata implementata seguendo le “regole sacre” del pattern MVVM.

In particolare le seguenti.

> La classe non deve dipendere in alcun modo da elementi o istruzioni che coinvolgono elementi di UI (creazione di pagine, modifiche di stili, consumare eventi proposti dalla UI, visualizzazione di messaggi di warning/errrore/avviso)

> Non deve usare alcun metodo statico offerto da altre classi

> Quando occorre utilizzare usare servizi esterni occorre tassativamente usare i componenti coinvolti via interfaccia (cioè usare solo l’interfaccia, e non l’oggetto), che quindi saranno risolti in concrete object utilizzando il Dependency Injection (questa parte non dovrebbe avere più alcun segreto perchè espliticitata nelle scrose puntate della serie).

Usando i corretti pattern di progettazione di una classe, e utilizzando le opportune fake class, è sempre possibile fare tutti gli unit test del caso.

Come visto le classi menzognere (l'altro nome che abbiamo dato alle fake class) non fanno altro che implementare delle interfacce, in modo da permettere al codice in test di interagire correttamente con le funzionalità esterne, simulandole.

Tutto meraviglioso però è innegabile che scrivere fake class è una rottura di scatole infinita, e direi che dopo un po' ti toglie la voglia di implementare qualsiasi unit test.

Mi permetto di sottolineare il punto: non è sbagliato implementare unit test con l'ausili di fake class, semplicemente questa è un’attività generalmente è molto onerosa.

Per ovviare a questo sforzo ci viene in aiuto un framework che è in grado di aiutarci a bestia nella creazione di classi fake: questo meraviglioso alleato si chiama Moq.