2009-08-18 7 views
11

Sto costruendo una nuova applicazione e cerco di aderire allo sviluppo "test-first" nel modo più fedele possibile. Mi trovo in situazioni in cui ho bisogno di implementare/modificare una funzionalità che ha l'effetto di invalidare un numero di test unitari esistenti. Come dovrei avere a che fare con questo? Come la vedo io, ci sono 3 opzioni:Cosa fare quando una nuova funzione fa sì che i test unitari esistenti non siano più validi?

  • aggiornare o rimuovere tutti test esistenti per soddisfare i nuovi requisiti di funzionalità (con l'aggiunta di più se necessario), quindi implementare la funzione

  • Attuare il caratteristica prima, eseguire test per vedere gli errori, e aggiornare o rimuovere eventuali test falliti (aggiungere più se necessario)

  • Aggiungi nuovi test per la nuova funzione, implementare la funzione, eseguire tutti i test di vedere il vecchio su es sicuro, rimuovere o aggiornamento vecchie prove necessarie

La prima opzione aderisce TDD, ma può essere estremamente controproducente. La seconda opzione è la più semplice, ma per prima cosa non si effettueranno test fedelmente e potrebbero non essere "coperti" correttamente. La terza opzione è un compromesso di entrambi e attraente per un certo grado, ma corri il rischio di riscrivere un test quando potresti aver aggiornato solo uno vecchio.

Non mi sembra di avere una strategia chiara qui. Cosa fai in queste situazioni?

+0

Questo è quello che faccio quando penso a tutto il codice che ho provato che alla fine è andato nella pattumiera: http://www.youtube.com/watch?v=tgBI3-q5COM – Will

+2

Sembra strano che fare una modifica (correttamente) potrebbe interrompere diversi test di unità. Uno o due forse, ma diversi? È possibile che i test dell'unità si sovrappongano troppo? – Beta

+0

@Beta, aggiungendo un requisito per cui l'implementazione richiede ora una classe dipendente aggiuntiva. Ora gli altri test non forniscono un'implementazione fittizia dell'oggetto dipendente, quindi quando vengono eseguiti ottieni un sacco di eccezioni di riferimento null. Dovresti quindi tornare indietro e sistemare il tuo codice di configurazione in modo che possano passare. – tvanfosson

risposta

8

Vorrei scegliere un test e cambiarlo per richiedere la nuova funzione. Se non ci sono candidati ovvi, cioè, è veramente nuovo, vorrei crearne uno. Vorrei quindi scrivere il codice per superare quel test. A quel punto avrei eseguito i miei altri test e notato che alcuni di loro falliscono. A quel punto, rivisiterei ogni test a sua volta correggendo il test in modo che riflettesse la nuova funzione (quindi passerebbe senza altre modifiche al codice) o aggiornando il test in relazione alla nuova funzione (che potrebbe richiedere ulteriori modifiche al codice sotto test).

4

Vorrei creare nuovi test per la nuova funzione e aggiornare i test esistenti per adattare la funzione. Se rompi un test già funzionante, dovresti risolverlo.

4

L'implementazione della funzione include scrittura/aggiornamento dei test di unità; questo è fondamentale per lo sviluppo basato sui test. Quindi le tue seconde due opzioni sono anche TDD, non solo la tua prima. In pratica ho il sospetto si vorrà la vostra terza opzione con alcuni mods:

  1. test di scrittura per la funzione (dal momento che ti aiuta a convalidare l'API/interfaccia utente per esso)
  2. Scrivi la caratteristica
  3. recensione i test di unità in quella zona generale, per vedere quelli che dovrebbe rompere
  4. eseguire i test
  5. quelli Fix che si rompono, e se ci sono nella tua lista da # 3 che non rompere, fissarli (dovrebbero avere rotto). Se si sono verificati errori che non hai identificato, fai una ricerca per accertarti che sia, in effetti, corretto - correggi il test o la funzione come appropriato.
  6. Profit ;-)
0

sbarazzarsi dei vecchi test e scrivere nuovi. Potresti essere in grado di prendere in prestito codice dai vecchi test in alcuni punti, ma stai meglio con i test filosoficamente in linea con quello che stai cercando di fare piuttosto che tentare di cambiare la natura del vecchio test.

I test sono lì per supportare ciò che stai cercando di realizzare, e non dovrebbero funzionare contro di te.

0

Penso che ci siano due cose da considerare qui. E non so se stai pensando solo a uno o entrambi.

La prima parte è che si modifica una funzionalità poiché la specifica (o il comportamento previsto) cambia. In questo caso, ritengo che la cosa corretta da fare sia rimuovere tutti i test che descrivono comportamenti non più validi. Dal momento che sono pigro vorrei solo commentarli o saltarli per ora. Quindi inizierò a scrivere nuovi test (o decommentare/modificare quelli vecchi) per iniziare a descrivere il nuovo comportamento fino al completamento.

La seconda parte deve essere eseguita se la nuova funzione modifica un'interfaccia utilizzata da altri componenti e se i test hanno avuto esito negativo solo perché è stata modificata la funzione. In questo caso, dovrei semplicemente correggere i test in seguito una volta che la feature è stata rifinita.

1

Penso che tutti gli approcci siano ragionevoli. Otterrai lo stesso risultato.

Alcune persone amano i passaggi più piccoli e lavorare di più nell'intento originale di TDD: scrivere una riga di test, scrivere una riga di codice per risolverlo, ripetere. Se sei tu, lavora prima in modo incrementale sui tuoi vecchi test, evolvendoli o rimuovendoli nel nuovo sistema.

Se non ti dispiace mordere un pezzo più grande, immergiti in una roba nuova. Trovo che questo sia più naturale, specialmente quando si programmano le coppie quando si può essere un po 'più audaci.

Può davvero dipendere dal vostro livello di comfort e confidenza.

Secondo la nozione che idealmente una modifica dovrebbe interrompere solo un test, quindi si consiglia di rifattorizzare il codice di test in modo che questo sia il comportamento che si ha. Una sorta di metodo di configurazione condivisa potrebbe essere la soluzione.

Problemi correlati