Domanda

Mentre io ho scritto unit test per la maggior parte del codice che ho fatto, ho da poco messo le mani su una copia del TDD con l'esempio da Kent Beck. Ho sempre rimpianto certe decisioni progettuali che ho fatto da quando hanno impedito l'applicazione di essere 'verificabile'. Ho letto il libro e mentre alcuni di essi sembra alieno, sentivo che avrei potuto gestire e ho deciso di provarlo sul mio progetto attuale, che è fondamentalmente un sistema client / server in cui i due pezzi comunicano tramite. USB. Uno sul gadget e l'altro sul host. L'applicazione è in Python.

Ho iniziato molto presto e ottenuto impigliato in un pasticcio di riscritture e prove piccoli che poi ho figurato in realtà non prova nulla. Ho buttato via la maggior parte di loro e e ora hanno una domanda di lavoro per la quale le prove sono tutte coagulate in appena 2.

Sulla base delle mie esperienze, ho alcune domande che vorrei chiedere. Ho guadagnato alcune informazioni da Nuovo per TDD: ci sono applicazioni di esempio con test per mostrare come fare TDD ma hanno alcune domande specifiche che mi piacerebbe risposte a / discussione?.

  1. Kent Beck utilizza una lista che si aggiunge alla e colpisce fuori dal per guidare il processo di sviluppo. Come si fa a fare un elenco del genere? Inizialmente ho avuto un paio di elementi come "server dovrebbe start up", "server dovrebbe abortire se il canale non è disponibile", ecc ma hanno ottenuto mescolato e finalmente ora, è solo qualcosa come "client dovrebbe essere in grado di connettersi al server" (che avvio del server sussunta ecc.).
  2. Come si fa a gestire riscrive? Inizialmente ho scelto un sistema half duplex sulla base di named pipe in modo da poter sviluppare la logica applicativa sulla mia macchina e poi aggiungere la parte di comunicazione USB. Li trasferisce a diventare una cosa basata presa e poi spostato da usare socket grezzi di utilizzare il modulo Python SocketServer. Ogni volta le cose cambiate, ho scoperto che ho dovuto riscrivere parti considerevoli dei test che era fastidioso. Avevo pensato che i test sarebbero stati una guida un po 'invariabile durante il mio sviluppo. Hanno appena sentito come più codice da gestire.
  3. avevo bisogno di un client e un server di comunicare attraverso il canale di testare entrambi i lati. Potrei prendere in giro uno dei lati per testare l'altro, ma poi l'intero canale non sarebbe stato testato e temo che mi mancherebbe che. Questo ha penalizzato l'intero rosso / verde / refactoring ritmo. Questo è solo mancanza di esperienza o sto facendo qualcosa di sbagliato?
  4. Il "falso finché si rendono" mi ha lasciato con un sacco di codice disordinato che poi ho passato un sacco di tempo per il refactoring e ripulire. E 'questo il modo in cui le cose funzionano?
  5. Al termine della sessione, ora ho il mio client e server in esecuzione con circa 3 o 4 test di unità. Mi ci sono voluti circa una settimana per farlo. Credo che avrei potuto fare in un giorno, se dovessi usare i test di unità dopo il modo in cui il codice. Non riesco a vedere il guadagno.

Sto cercando per i commenti e consigli da parte di persone che hanno implementato progetti di grandi dimensioni non banali completamente (o quasi completamente) utilizzando questa metodologia. Ha senso per me di seguire la via dopo ho qualcosa già in esecuzione e si desidera aggiungere una nuova funzionalità ma farlo da zero sembra faticoso e non vale la pena.

P.S. :. Per favore fatemi sapere se questo dovrebbe essere comunità wiki e io segnarlo come quella

Aggiorna 0 : Tutte le risposte sono state altrettanto utile. Ho scelto quello che ho fatto perché in risonanza con le mie esperienze più.

Aggiorna 1 :! Pratica pratica pratica

È stato utile?

Soluzione

Come commento preliminare, TDD richiede pratica. Quando guardo indietro ai test che ho scritto quando ho iniziato TDD, vedo un sacco di problemi, proprio come quando guardo codice che ho scritto qualche anno fa. Continuare a farlo, e proprio come si comincia a riconoscere il buon codice di male, le stesse cose che accadrà con i test - con pazienza.

  

Come si fa a fare un elenco del genere? io   inizialmente aveva alcuni elementi come "server   dovrebbe start up "" server dovrebbe interrompere   se il canale non è disponibile", ecc, ma   hanno ottenuto misti e finalmente ora, è   solo qualcosa come "cliente dovrebbe essere   in grado di connettersi al server "

"La lista" può essere piuttosto informale (questo è il caso del libro di Beck), ma quando si sposta a fare gli articoli nel test, provare a scrivere le istruzioni in un "[Quando succede qualcosa a questo], quindi [questa condizione dovrebbe essere vero in quel formato]". Questo vi costringerà a pensare di più su ciò che è si sta verificando, come si verifica e si traduce direttamente in test - o se lo fa, non dovrebbe dare un indizio su quale pezzo di funzionalità è mancante. Pensate caso d'uso / scenario. Per esempio "server dovrebbe start up" non è chiaro, perché nessuno sta avviando un'azione.

  

Ogni volta le cose cambiate, ho scoperto che   Ho dovuto riscrivere parti considerevoli   i test che era fastidioso. mi piacerebbe   capito che i test sarebbero un   guida un po 'invariabile durante il mio   sviluppo. Hanno appena sentito come più   codice per gestire.

In primo luogo, sì, le prove sono più codice, e richiede una manutenzione - e la scrittura di test mantenibili prende la pratica. Sono d'accordo con S. Lott, se è necessario modificare i test molto, si sono probabilmente testando "troppo in profondità". Idealmente si desidera testare a livello dell'interfaccia pubblica, che non è destinata a cambiare, e non a livello del dettaglio di implementazione, che potrebbe evolversi. Ma parte dell'esercizio è di venire con un design, così si dovrebbe aspettare di ottenere un po 'di sbagliato e devono spostare / refactoring i test pure.

  

ho potuto deridere uno dei lati per testare   l'altra ma poi l'intero canale   non sarebbe provato e mi preoccupo che   Mi mancherebbe che.

Non del tutto sicuro di quello. Dal suono di esso, utilizzando un finto era l'idea giusta: prendere un lato, deridere l'altro, e verificare che ogni lato funziona, supponendo che l'altro è implementato correttamente. Testare l'intero sistema insieme è test di integrazione, che anche voi volete fare, ma non è in genere parte del processo di TDD.

  

Il "falso finché si rendono" mi ha lasciato   con un sacco di codice disordinato che poi ho   speso un sacco di tempo per il refactoring e   pulire. È questo il lavoro come vanno le cose?

Si dovrebbe spendere un sacco di tempo refactoring, mentre facendo TDD. D'altra parte, quando si è falso, è temporanea, e il tuo passo successivo immediato dovrebbe essere quello di un-falso. In genere non si dovrebbero avere più test di passaggio perché si finto esso -. Si dovrebbe essere incentrata su un pezzo alla volta, e lavorare su refactoring al più presto

  

Credo che avrei potuto fare in un giorno   quando uso il test di unità dopo   modo di codice. Non riesco a vedere il guadagno.

Anche in questo caso, ci vuole pratica, e si dovrebbe ottenere più velocemente nel tempo. Inoltre, a volte TDD è più fruttuoso di altri, trovo che in alcune situazioni, quando so esattamente il codice che voglio scrivere, è solo più veloce per scrivere una buona parte del codice, e poi scrivere i test.
Oltre a Beck, un libro mi è piaciuto è l'arte di Unit Testing, da Roy Osherove. Non è un libro TDD, ed è Net-oriented, ma si potrebbe desiderare di dare un aspetto comunque: una buona parte è su come scrivere i test mantenibili, qualità test e questioni connesse. Ho trovato che il libro in risonanza con la mia esperienza dopo avere prove scritte e, a volte fatica a farlo bene ...
Quindi il mio consiglio è, non gettare la Towel troppo in fretta, e dargli un po 'di tempo. Si potrebbe anche voler dare un colpo a qualcosa di più facile - la comunicazione server di prova relativi cose non suona come il progetto più semplice per iniziare con

Altri suggerimenti

  
      
  1. Kent Beck utilizza un elenco ... finalmente ora, è solo qualcosa come "client dovrebbe essere in grado di connettersi al server" (che sussunto server di avvio, ecc.).
  2.   

Spesso una cattiva pratica.

prove separate per ciascuno strato separato dell'architettura sono buone.

test consolidati tendono a oscurare i problemi architettonici.

Tuttavia, testare solo le funzioni pubbliche. Non tutte le funzioni.

E non investire un sacco di tempo a ottimizzare la vostra prova. Ridondanza nelle prove non fa male tanto quanto lo fa nella domanda di lavoro. Se le cose cambiano e un test funziona, ma un altro break di prova, forse allora si può refactoring i test. Non prima.

  

2. Come si fa a gestire riscrive? ... ho scoperto che ho dovuto riscrivere parti considerevoli delle prove.

Si sta testando a un livello troppo basso di dettagli. Testare l'interfaccia più esterno, pubblico visibile. La parte che dovrebbe essere immutabile.

E

Sì, significativo cambiamento architettonico significa cambiamento significativo test.

E

Il codice di prova è come dimostrare le cose funzionano. E 'importante quasi quanto l'applicazione stessa. Sì, è più codice. Sì, è necessario gestirlo.

  

3. Avevo bisogno di un client e un server di comunicare attraverso il canale di testare entrambi i lati. Potrei prendere in giro uno dei lati per testare l'altro, ma poi tutto il canale non sarebbe essere testato ...

Non ci sono test di unità. Con mock.

Ci sono i test di integrazione, che mettono alla prova il tutto.

Non confonderli.

È possibile utilizzare strumenti di test di unità per fare i test di integrazione, ma sono cose diverse.

E avete bisogno di fare entrambe le cose.

  

4. Il "falso che fino a renderlo" mi ha lasciato con un sacco di codice disordinato che poi ho passato un sacco di tempo per il refactoring e ripulire. È questo il lavoro come vanno le cose?

Sì. Questo è esattamente come funziona. Nel lungo periodo, alcune persone trovano questo più efficace di sforzare il cervello cercando di fare tutto il design in attacco. Alcune persone non piace questo e vogliono fare tutto il design in attacco; sei libero di fare un sacco di disegno in anticipo se si desidera.

Ho scoperto che il refactoring è una buona cosa e design in attacco è troppo difficile. Forse è perché ho codifica per quasi 40 anni e il mio cervello si sta esaurendo.

  

5. Non riesco a vedere il guadagno.

Tutti i veri geni scoprono che i test li rallenta.

Il resto di noi non può essere che il nostro codice funziona finché non avremo una serie completa di test che rivelarsi che funziona.

Se non avete bisogno di prova che il codice funziona, non è necessario il test.

  

Q. Kent Beck utilizza una lista che si aggiunge alla e colpisce fuori dal per guidare il processo di sviluppo. Come si fa a fare un elenco del genere? Inizialmente ho avuto un paio di elementi come "server dovrebbe start up", "server dovrebbe abortire se il canale non è disponibile", ecc ma hanno ottenuto mescolato e finalmente ora, è solo qualcosa come "client dovrebbe essere in grado di connettersi al server" (che avvio del server sussunta ecc.).

Comincio con la scelta di qualsiasi cosa io possa controllare. Nel tuo esempio, si è scelto "server viene avviato".

Server starts

Ora guardo per qualsiasi prova più semplice potrei voler scrivere. Qualcosa con meno variazioni, e un minor numero di parti in movimento. Potrei prendere in considerazione "server configurato correttamente", per esempio.

Configured server correctly
Server starts

In realtà, però, "server viene avviato" dipende "server configurato correttamente", così mi fanno si che chiaro collegamento.

Configured server correctly
Server starts if configured correctly

Ora cerco variazioni. Io chiedo: "Che cosa potrebbe andare storto?" Ho potuto configurare il server in modo non corretto. In quanti modi diversi che importa? Ognuno di coloro che fa una prova. Come potrebbe il server non iniziare, anche se ho configurato correttamente? Ogni caso di che fa una prova.

  

Q. Come si fa a gestire riscrive? Inizialmente ho scelto un sistema half duplex sulla base di named pipe in modo da poter sviluppare la logica applicativa sulla mia macchina e poi aggiungere la parte di comunicazione USB. Li trasferisce a diventare una cosa basata presa e poi spostato da usare socket grezzi di utilizzare il modulo Python SocketServer. Ogni volta le cose cambiate, ho scoperto che ho dovuto riscrivere parti considerevoli dei test che era fastidioso. Avevo pensato che i test sarebbero stati una guida un po 'invariabile durante il mio sviluppo. Hanno appena sentito come più codice da gestire.

Quando cambio comportamento, trovo ragionevole per cambiare i test, e anche di cambiare loro per primi! Se devo cambiare i test che non controllano direttamente il comportamento Sono in procinto di cambiare, però, questo è un segno che i miei test dipendono da troppi comportamenti diversi. Quelli sono i test di integrazione, che mi sembrano una truffa. (Google "test di integrazione sono una truffa")

  

Q. Avevo bisogno di un client e un server di comunicare attraverso il canale di testare entrambi i lati. Potrei prendere in giro uno dei lati per testare l'altro, ma poi l'intero canale non sarebbe stato testato e temo che mi mancherebbe che. Questo ha penalizzato l'intero rosso / verde / refactoring ritmo. Questo è solo mancanza di esperienza o sto facendo qualcosa di sbagliato?

Se io costruisco un client, un server e un canale, quindi cerco di controllare ogni in isolamento. Comincio con il cliente, e quando ho test-drive, io decido come il server e canali devono comportarsi. Poi a implementare il canale e server ogni modo che corrisponda al comportamento di cui ho bisogno. Quando si controlla il cliente, ho stub il canale; durante il controllo del server, ho deridere il canale; durante il controllo del canale, ho stub e finto sia client che server. Spero che questo ha un senso per voi, dal momento che ho di fare alcune gravi ipotesi sulla natura di questo client, server e dei canali.

  

Q. Il "falso che fino a renderlo" mi ha lasciato con un sacco di codice disordinato che poi ho passato un sacco di tempo per il refactoring e ripulire. È questo il lavoro come vanno le cose?

Se si lascia che il codice di "fingere" ottenere molto disordinato prima di pulirlo, allora si potrebbe avere speso troppo tempo fingendo. Detto questo, trovo che anche se finisco per ripulire più codice con TDD, il ritmo globale si sente molto meglio. Questo deriva dalla pratica.

  

Q. Alla fine della sessione, ora ho il mio client e server in esecuzione con circa 3 o 4 test di unità. Mi ci sono voluti circa una settimana per farlo. Credo che avrei potuto fare in un giorno, se dovessi usare i test di unità dopo il modo in cui il codice. Non riesco a vedere il guadagno.

Devo dire che a meno che il client e il server sono molto, molto semplice, è necessario più di 3 o 4 test ciascunoper controllare a fondo. Mi immagino che i test di controllo (o almeno eseguire) un certo numero di comportamenti diversi in una sola volta, e che potrebbe spiegare lo sforzo che ti ha portato a scrivere di loro.

Inoltre, non misurare la curva di apprendimento. La mia prima esperienza TDD vero consisteva di ri-scrittura vale la pena di lavoro di 3 mesi a 9, 14 ore al giorno. Ho avuto 125 test che hanno avuto 12 minuti per l'esecuzione. Non avevo idea di quello che stavo facendo, e sembrava lento, ma si sentiva costante, ei risultati sono stati fantastici. I essenzialmente ri-scritto in 3 settimane ciò che in origine sono voluti 3 mesi per ottenere sbagliato. Se ho scritto ora, probabilmente potrei farlo in 3-5 giorni. La differenza? La mia suite di test avrebbe 500 test che prendono 1-2 secondi per l'esecuzione. Che è venuto con la pratica.

Come un programmatore alle prime armi, la cosa che ho trovato difficile di sviluppo test-driven è stata l'idea che il test dovrebbe venire prima.

Per il novizio, che non è vero. Design viene prima. (interfacce, oggetti e classi, metodi, qualunque sia il caso di lingua). Poi si scrive il test per questo. Poi si scrive il codice che in realtà fa cose.

E 'stato un po' da quando ho guardato il libro, ma Beck sembra di scrivere come se il disegno del codice appena sorta di accade inconsciamente nella tua testa. Per i programmatori esperti, questo può essere vero, ma per niubbi come me, Nuh-uh.

Ho trovato i primi capitoli di codice completo davvero utile per pensare alla progettazione. Essi sottolineano il fatto che il vostro disegno potrebbe cambiare, anche una volta che sei giù al livello Nitty Gritty di attuazione. Quando ciò accade, si può anche essere necessario ri-scrivere i test, perché erano basati sugli stessi presupposti come il vostro disegno.

Coding è difficile. Andiamo shopping.

Per il punto uno, vede un ho chiesto un po 'indietro in relazione al vostro primo punto.

Invece di gestire gli altri punti a loro volta, ti offro un consiglio mondiale. Pratica. Mi c'è voluto un bel po 'e un paio di progetti un po' incerti '(personali però) a vero e proprio TDD get. Solo Google per molto motivi più convincenti sul perché TDD è così buono.

Nonostante le prove di guida alla progettazione del mio codice, ho ancora ottenere una lavagna e scarabocchio fuori qualche disegno. Da questo, almeno hai qualche idea di quello che sono destinate ad essere fare. Poi produco l'elenco delle prove per apparecchio che credo di aver bisogno. Una volta che si inizia a lavorare, più funzioni e test vengono aggiunti alla lista.

Una cosa che spiccava dalla tua domanda è l'atto di riscrivere di nuovo i test. Questo suona come si sta effettuando test comportamentali, piuttosto che dello Stato. In altre parole, le prove di sembrare troppo strettamente legati al codice. Pertanto, una semplice modifica che non influisce l'uscita si romperà alcuni test. Unit testing (almeno buona unit testing) troppo, è una competenza da padroneggiare.

Vi consiglio il blog test Google piuttosto pesantemente, perché alcuni degli articoli in là ha reso la mia prova per TDD progetti molto meglio.

I le named pipe sono stati messi dietro la giusta interfaccia, cambiando il modo che l'interfaccia è implementata (da named pipe per socket a un'altra libreria socket) deve solo prove di impatto per la componente che implementa tale interfaccia. Quindi tagliare le cose più / in modo diverso avrebbe aiutato ... Questa interfaccia le prese sono dietro probabilmente evolverà a.

ho iniziato a fare TDD forse 6 mesi fa? Sto ancora imparando me stesso. Posso dire nel corso del tempo le mie prove e il codice hanno ottenuto molto meglio, in modo da tenere il passo. Consiglio vivamente il libro xUnit Design Patterns pure.

  

Come si fa a fare un simile elenco da aggiungere alla   e colpire da a guidare la   processo di sviluppo? Inizialmente ho avuto un   alcuni elementi come "server dovrebbe iniziare   up "" server dovrebbe interrompere se il canale   non è disponibile"

I prodotti in todo list TDD sono a grana più fine di quello, mirano a test un comportamento di un metodo unico, per esempio:

  • test di successo connessione client
  • test di client di connessione tipo di errore 1
  • test di client di connessione tipo di errore 2
  • test di successo comunicazione client
  • comunicazione client test fallisce quando non sono collegati

Si potrebbe costruire un elenco di test (positivi e negativi) per ogni esempio che ha dato. Inoltre, quando il test delle unità non si stabilisce una connessione tra il server e il client. Basta richiamare i metodi di isolamento, ... Questo risponde alla domanda 3.

  

Come si fa a gestire riscrive?

Se l'unità di comportamento prova prove e non applicazione, quindi non devono essere riscritti. Se il codice di prova unità realmente crea una pipa denominata per comunicare con codice di produzione e, quindi, ovviamente, i test devono essere modificate quando si passa da tubo a presa. Prove di unità devono stare lontano da fonti esterne come file system, reti, database perché sono lenti, possono essere non disponibili ... vedere questi norme Unit Testing .

Ciò implica la funzione livello più basso non sono testati unità, saranno provati con test di integrazione, in cui l'intero sistema è testato end-to-end.

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