Domanda

Ho letto di TDD e vorrei usarlo per il mio prossimo progetto, ma non sono sicuro di come strutturare le mie lezioni con questo nuovo paradigma. La lingua che vorrei usare è Java, anche se il problema non è specifico della lingua.

Il progetto

Ho alcuni componenti hardware forniti con un'interfaccia ASCII-over-RS232. Posso emettere semplici comandi, ottenere risposte semplici e controllarli come se fossero dai loro pannelli frontali. Ognuno ha una sintassi leggermente diversa e set di comandi molto diversi. Il mio obiettivo è creare un'astrazione / interfaccia in modo da poterli controllare tutti attraverso una GUI e / o chiamate di procedura remote.

Il problema

Credo che il primo passo sia quello di creare una classe astratta (sono pessimo nei nomi, che ne dici di "Communicator"?) per implementare tutte le cose come l'I / O seriale, e quindi creare una sottoclasse per ogni dispositivo. Sono sicuro che sarà un po 'più complicato di così, ma questo è il cuore dell'applicazione nella mia mente.

Ora, per i test unitari, non credo di aver davvero bisogno dell'hardware reale o di una connessione seriale. Quello che mi piacerebbe fare è consegnare ai miei Comunicatori un InputStream e OutputStream (o Reader e Writer) che potrebbero provenire da una porta seriale, file, stdin / stdout, convogliati da una funzione di test, qualunque cosa. Quindi, vorrei solo che il costruttore di Communicator prendesse questi come input? In tal caso, sarebbe facile affidare la responsabilità di impostare tutto sul framework di test, ma per la verità, chi stabilisce la connessione effettiva? Un costruttore separato? La funzione chiama di nuovo il costruttore? Una classe separata che ha il compito di "connettere" il Comunicatore ai flussi I / O corretti?

Modifica

Stavo per riscrivere la sezione del problema per ottenere risposte alla domanda che pensavo di porre, ma penso di averlo capito. Avevo (correttamente?) Identificato due diverse aree funzionali.

1) Gestione della porta seriale

2) Comunicare con il dispositivo (comprenderne l'output e generare comandi)

Qualche mese fa, avrei combinato tutto in una classe. La mia prima idea di staccarmi da questo è stata quella di trasmettere solo i flussi IO alla classe che comprende il dispositivo e non sono riuscito a capire chi sarebbe stato quindi responsabile della creazione dei flussi.

Dopo aver fatto più ricerche sull'inversione del controllo, penso di avere una risposta . Avere un'interfaccia e una classe separate che risolvano il problema n. 1 e lo passino al costruttore della classe (es?) Che risolve il problema n. 2. In questo modo, è facile testarli entrambi separatamente. # 1 collegandosi all'hardware effettivo e consentendo al framework di test di fare cose diverse. # 2 può essere testato ricevendo una derisione di # 1.

Sembra ragionevole? Devo condividere maggiori informazioni?

È stato utile?

Soluzione

Con TDD, dovresti far emergere il tuo design , iniziare in piccolo, con piccoli passi e far crescere le tue lezioni test per test, a poco a poco.

CHIARITO: Inizia con una classe concreta, per inviare un comando, testarlo con un mock o uno stub. Quando funzionerà abbastanza (forse non con tutte le opzioni), testalo sul tuo dispositivo reale, una volta, per convalidare il tuo simulatore / stub / simulatore.

Una volta che la classe per il primo comando è operativa, inizia a implementare un secondo comando, allo stesso modo: prima il tuo mock / stub, poi una volta contro il dispositivo per la convalida. Ora, se vedi delle somiglianze tra le tue due classi, puoi rifattorizzare il tuo design basato su classi astratte o su qualcosa di diverso.

Altri suggerimenti

Ci scusiamo per essere un po 'incentrato su Linux ..

Il mio modo preferito di simulare gadget è scrivere driver di dispositivo di carattere che simulare il loro comportamento. Questo ti dà anche abilità divertenti, come fornire un'interfaccia ioctl () che fa in modo che il dispositivo simulato si comporti in modo anomalo.

A quel punto .. dai test al mondo reale, importa solo quale dispositivo (i) effettivamente apri, leggi e scrivi.

Non dovrebbe essere troppo difficile imitare il comportamento dei tuoi gadget .. sembra che prendano istruzioni molto semplici e restituiscano risposte molto semplici. Ancora una volta, un semplice ioctl () potrebbe dire al dispositivo simulato che è giunto il momento di comportarsi in modo errato, quindi puoi assicurarti che il tuo codice gestisca adeguatamente tali eventi. Ad esempio, fallire intenzionalmente su ogni ennesima istruzione, dove n viene selezionato casualmente sulla chiamata a ioctl ().

Dopo aver visto le tue modifiche penso che stai andando esattamente nella giusta direzione. TDD tende a guidarti verso un design composto da piccole classi con una responsabilità ben definita. Vorrei anche fare eco al consiglio di Tinkertim: un simulatore di dispositivo che puoi controllare e "provocare". comportarsi in modi diversi è prezioso per i test.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top