Questo repository contiene un esercizio svolto in classe durante il corso di TDD.
Quando si progetta un sistema grande, ci piacerebbe basare il nostro design sul modo in cui verrà realmente utilizzato il nostro sistema. In questo modo, le storie degli utenti e i criteri di accettazione diventano molto più di un semplice traguardo: sono un principio guida per l'intero sistema.
Questo approccio risolve (o limita) parecchi problemi. Ad esempio, elimina l'over-engineering, poiché scriviamo il codice solamente per quello che sappiamo che l'utente ha bisogno). Partire dall'interfaccia pubblica (contratto) dell'applicazione riduce il rischio di deviare dallo scopo principale dell'applicazione; inoltre, riduce i problemi d'integrazione perché la facciamo in modo frequente e continuo.
Questo esercizio mira a distillare quell'esperienza su un problema complesso che può essere affrontato in un paio d'ore, scrivendo un software per gestire una libreria (bookshelf). In questo caso, la nostra interfaccia utente è semplice e composta da pochi entry-point HTTP, ci limiteremo a scrivere alcune delle API che potranno essere utilizzate da un'interfaccia utente grafica. Valgono gli stessi principi.
Ci eserciteremo utilizzando i test di accettazione come guida per scrivere i test unitari e poi il codice di produzione vero e proprio. Se fatto correttamente e in modo scrupoloso, il risultato sarà un sistema semplice e in grado di evolvere con poco sforzo e senza brutte sorprese alla fine.
Per implementare questo esercizio possiamo utilizzare sia l'approccio Classic che quello con i mock. La prima implementazione che faremo è con TDD Classic.
In questo repository è presento uno scheletro di un'applicazione Web API scritta in .NET Core.
La classe BookshelfController
è l'interfaccia della nostra applicazione e la sua definizione non può essere modificata, ma andranno implementati i metodi al suo interno.
La classe Book
rappresenta il nostro dato principale e per comodità e semplicità è stata implementata e non può essere modificata, dato che, a tutti gli effetti, è parte dell'interfaccia pubblica.
- una chiamata
GET
mi restituisce la lista dei libri presenti nella libreria e.g./api/bookshelf
; - una chiamata
GET
con il parametroID
di un libro mi restituisce il libro cercato oppure unHTTP - Not Found
se il libro non esiste e.g./api/bookshelf/<ID>
; - una chiamata
POST
aggiunge il libro passato come body della chiamata alla libreria e.g./api/bookshelf
; - una chiamata
PUT
con il parametroID
aggiorna il libro corrispondente con il body della chiamata oppure restituisce unHTTP - Not Found
e.g./api/bookshelf/<ID>
; - una chiamata
DELETE
con il parametroID
rimuove il libro corrispondente oppure restituisce unHTTP - Not Found
e.g./api/bookshelf/<ID>
;
- nel dubbio implementare la soluzione più semplice;
- non preoccupatevi di validare i campi o le chiamate, non è lo scopo di questo esercizio, supponete che siano sempre corretti;
- usate i comportamenti desiderati per scrivere dei test di accettazione;
- alcuni comportamenti desiderati nascondono 2 comportamenti differenti, quindi sarà necessario scrivere 2 test di accettazione (uno per ogni comportamento);
- siete liberi di utilizzare un repository-in-memory, ma i test unitari devono utilizzare un'apposito repository di test (disaccoppiate il codice);