it-swarm.it

Svantaggi dello sviluppo guidato dai test?

Cosa perdo adottando il design test driven?

Elenco solo negativi; non elencare i benefici scritti in una forma negativa.

189
IanL

Diversi aspetti negativi (e non sto affermando che non ci sono benefici - specialmente quando si scrive la fondazione di un progetto - alla fine si risparmierebbe molto tempo):

  • Big time investment. Per il caso semplice si perde circa il 20% dell'implementazione effettiva, ma per i casi complicati si perde molto di più.
  • Complessità aggiuntiva. Per i casi complessi i tuoi casi di test sono più difficili da calcolare, suggerirei in casi come quello di provare a utilizzare il codice di riferimento automatico che verrà eseguito in parallelo nella versione di debug/test, invece del test unitario dei casi più semplici.
  • Impatti del design. A volte il design non è chiaro all'inizio e si evolve man mano che procedi - questo ti costringerà a ripetere il test che genererà una grande perdita di tempo. Suggerirei di posticipare i test unitari in questo caso fino a quando non avrai ben compreso il progetto.
  • Continuous Tweaking. Per le strutture di dati e gli algoritmi della scatola nera i test unitari sarebbero perfetti, ma per gli algoritmi che tendono a essere modificati, ottimizzati o messi a punto, ciò può causare un grande investimento che si potrebbe affermare di non avere giustificata. Quindi usalo quando pensi che si adatti effettivamente al sistema e non forzare il design a adattarsi al TDD.
126
Adi

Se vuoi fare un TDD "reale" (leggi: prova prima con i passaggi rosso, verde, refactor), allora devi anche iniziare a usare mock/stub, quando vuoi testare i punti di integrazione.

Quando inizi a usare i mock, dopo un po 'vorrai iniziare a usare Dependency Injection (DI) e un contenitore Inversion of Control (IoC). Per fare ciò è necessario utilizzare le interfacce per tutto (che hanno molte insidie).

Alla fine, devi scrivere molto più codice, che se lo fai semplicemente alla "vecchia maniera". Invece di una semplice classe cliente, devi anche scrivere un'interfaccia, una classe simulata, una configurazione IoC e alcuni test.

E ricorda che anche il codice di test dovrebbe essere mantenuto e curato. I test dovrebbero essere leggibili come tutto il resto e ci vuole tempo per scrivere un buon codice.

Molti sviluppatori non capiscono bene come fare tutto questo "nel modo giusto". Ma poiché tutti dicono loro che TDD è l'unico vero modo per sviluppare software, provano solo il meglio che possono.

È molto più difficile di quanto si possa pensare. Spesso i progetti realizzati con TDD finiscono con un sacco di codice che nessuno capisce davvero. I test unitari spesso verificano la cosa sbagliata, nel modo sbagliato. E nessuno è d'accordo su come dovrebbe essere un buon test, nemmeno i cosiddetti guru.

Tutti questi test rendono molto più difficile "cambiare" (al contrario del refactoring) il comportamento del tuo sistema e le semplici modifiche diventano troppo difficili e richiedono molto tempo.

Se leggi la letteratura TDD, ci sono sempre alcuni esempi molto validi, ma spesso nelle applicazioni della vita reale, devi avere un'interfaccia utente e un database. È qui che TDD diventa davvero difficile e la maggior parte delle fonti non offre buone risposte. E se lo fanno, comporta sempre più astrazioni: oggetti finti, programmazione su un'interfaccia, schemi MVC/MVP ecc., Che richiedono ancora molta conoscenza e ... devi scrivere ancora più codice.

Quindi fai attenzione ... se non hai un team entusiasta e almeno uno sviluppatore esperto che sa scrivere buoni test e sa anche alcune cose sulla buona architettura, devi davvero pensarci due volte prima di percorrere la strada del TDD .

186
Thomas Jespersen

Quando arrivi al punto in cui hai un gran numero di test, la modifica del sistema potrebbe richiedere la riscrittura di alcuni o tutti i test, a seconda di quelli che sono stati invalidati dalle modifiche. Ciò potrebbe trasformare una modifica relativamente rapida in una che richiede molto tempo.

Inoltre, potresti iniziare a prendere decisioni di progettazione basate più su TDD che su principi di progettazione realmente validi. Considerando che potresti aver avuto una soluzione molto semplice e impossibile da testare nel modo richiesto dal TDD, ora hai un sistema molto più complesso che in realtà è più soggetto agli errori.

66
Eric Z Beard

Penso che il problema più grande per me sia l'enorme perdita di tempo che ci vuole per "entrarci". Sono ancora all'inizio del mio viaggio con TDD (vedi il mio blog per gli aggiornamenti delle mie avventure di prova se sei interessato) e ho trascorso letteralmente ore per iniziare.

Ci vuole molto tempo per mettere il cervello in "modalità test" e scrivere "codice testabile" è un'abilità in sé.

TBH, non sono rispettosamente d'accordo con commenti di Jason Cohen su come rendere pubblici i metodi privati, non è di questo che si tratta. Non ho fatto più metodi pubblici nel mio nuovo modo di lavorare di prima . Tuttavia, comporta modifiche architettoniche e consente di "moduli hot plug" di codice per rendere tutto più semplice da testare. Dovresti non rendere gli interni del tuo codice più accessibili per farlo. Altrimenti torniamo al punto di partenza con tutto ciò che è pubblico, dov'è l'incapsulamento in quello?

Quindi, (IMO) in breve:

  • La quantità di tempo impiegata per pensare (ovvero effettivamente grok'ing testing).
  • Le nuove conoscenze richieste per sapere come scrivere codice testabile.
  • Comprensione delle modifiche all'architettura necessarie per rendere testabile il codice.
  • Aumentare la tua abilità di "TDD-Coder" mentre cerchi di migliorare tutte le altre abilità richieste per il nostro glorioso mestiere di programmazione :)
  • Organizzazione della tua base di codice per includere il codice di prova senza rovinare il tuo codice di produzione.

PS: Se desideri collegamenti a aspetti positivi, ti ho chiesto e risposto a diverse domande al riguardo, dai un'occhiata al mio profilo .

54
Rob Cooper

Nei pochi anni in cui ho praticato Test Driven Development, dovrei dire che i maggiori svantaggi sono:

Vendendolo alla direzione

Il TDD è fatto meglio in coppia. Per uno, è difficile resistere all'impulso di scrivere l'implementazione quando CONOSCI come scrivere un if/else istruzione. Ma una coppia ti terrà in attività perché lo tieni in attività. Purtroppo, molte aziende/manager non pensano che questo sia un buon uso delle risorse. Perché pagare per due persone per scrivere una funzione, quando ho due funzioni che devono essere fatte contemporaneamente?

Vendendolo ad altri sviluppatori

Alcune persone semplicemente non hanno la pazienza di scrivere unit test. Alcuni sono molto orgogliosi del loro lavoro. Oppure, alcuni proprio come vedere metodi/funzioni contorti eliminano la fine dello schermo. TDD non è per tutti, ma vorrei davvero che lo fosse. Renderebbe il mantenimento delle cose molto più semplice per quelle povere anime che ereditano il codice.

Mantenimento del codice di prova insieme al codice di produzione

Idealmente, i test si interrompono solo quando si prende una decisione sbagliata sul codice. Cioè, hai pensato che il sistema funzionasse in un modo, e si scopre che non ha funzionato. Interrompendo un test o un (piccolo) set di test, questa è in realtà una buona notizia. Sai esattamente come il tuo nuovo codice influenzerà il sistema. Tuttavia, se i tuoi test sono scritti male, strettamente accoppiati o, peggio ancora, generati ( tosse VS Test), mantenere i tuoi test può diventare rapidamente un coro . E, dopo che un numero sufficiente di test inizia a causare più lavoro del valore percepito che stanno creando, i test saranno la prima cosa da eliminare quando le pianificazioni vengono compresse (ad es. Arriva a ridurre il tempo)

Scrivere test in modo da coprire tutto (copertura del codice al 100%)

Idealmente, ancora una volta, se aderisci alla metodologia, il tuo codice sarà testato al 100% per impostazione predefinita. In genere, ho pensato, finisco con una copertura del codice fino al 90%. Questo di solito accade quando ho un'architettura in stile modello e la base viene testata e provo a tagliare gli angoli e non testare le personalizzazioni del modello. Inoltre, ho scoperto che quando incontro una nuova barriera che non avevo mai incontrato in precedenza, ho una curva di apprendimento nel testarla. Ammetterò di scrivere alcune righe di codice alla vecchia maniera skool, ma mi piace davvero avere quel 100%. (Immagino di essere stato un grande successo a scuola, er skool).

Tuttavia, con ciò direi che i vantaggi di TDD superano di gran lunga i negativi per la semplice idea che se riesci a ottenere una buona serie di test che coprono la tua applicazione ma non sono così fragili che una modifica li rompe tutti, lo farai essere in grado di continuare ad aggiungere nuove funzionalità nel giorno 300 del progetto come nel giorno 1. Questo non accade con tutti coloro che provano TDD pensando che sia un proiettile magico a tutto il loro codice pieno di bug, e quindi pensano che possa lavoro, punto.

Personalmente ho scoperto che con TDD scrivo codice più semplice, passo meno tempo a discutere se una particolare soluzione di codice funzionerà o meno e che non ho paura di cambiare nessuna riga di codice che non soddisfa i criteri stabiliti da Il gruppo.

TDD è una disciplina difficile da padroneggiare, e ci sono stato per alcuni anni, e continuo a imparare nuove tecniche di test in ogni momento. È un enorme investimento in termini di tempo, ma, a lungo termine, la tua sostenibilità sarà molto maggiore rispetto a se non avessi test unitari automatizzati. Ora, se solo i miei capi potessero capirlo.

49
casademora

Nel tuo primo progetto TDD ci sono due grandi perdite, tempo e libertà personale

Perdi tempo perché:

  • La creazione di una suite completa di unità di misura e di prove di collaudo accettabili aggiunge molto tempo alla prima iterazione del progetto. Questo può essere un risparmio di tempo a lungo termine, ma allo stesso modo può essere tempo che non devi risparmiare.
  • Devi scegliere e diventare esperto in un set di strumenti di base. Uno strumento di unit test deve essere integrato da una sorta di framework di derisione ed entrambi devono entrare a far parte del sistema di build automatizzato. Vuoi anche scegliere e generare metriche appropriate.

Perdi la libertà personale perché:

  • TDD è un modo molto disciplinato di scrivere codice che tende a sfregare contro quelli nella parte superiore e inferiore della scala delle competenze. Scrivere sempre il codice di produzione in un certo modo e sottoporre il proprio lavoro a una continua revisione tra pari può spaventare i tuoi peggiori e migliori sviluppatori e persino portare alla perdita di personale.
  • La maggior parte dei metodi Agili che incorporano TDD richiedono che si parli continuamente con il cliente su ciò che si propone di realizzare (in questa storia/giorno/qualunque cosa) e quali sono i compromessi. Ancora una volta questa non è la tazza di tè di tutti, sia sul lato degli sviluppatori della recinzione che sui clienti.

Spero che sia di aiuto

24
Garth Gilmour

TDD richiede che tu pianifichi come funzioneranno le tue classi prima di scrivere il codice per superare quei test. Questo è sia un vantaggio che un aspetto negativo.

Trovo difficile scrivere i test in un "vuoto", prima che qualsiasi codice sia stato scritto. Nella mia esperienza, tendo a superare i miei test ogni volta che penso inevitabilmente a qualcosa mentre scrivo le mie lezioni che ho dimenticato mentre scrivevo i miei test iniziali. Quindi è tempo non solo di riformattare le mie classi, ma anche i miei test. Ripeti l'operazione tre o quattro volte e può essere frustrante.

Preferisco scrivere prima una bozza delle mie lezioni, quindi scrivere (e mantenere) una batteria di test unitari. Dopo che ho una bozza, TDD funziona bene per me. Ad esempio, se viene segnalato un bug, scriverò un test per sfruttare quel bug e quindi correggere il codice in modo che il test passi.

14
Chrass

La prototipazione può essere molto difficile con TDD: quando non si è sicuri della strada da percorrere per una soluzione, scrivere i test in anticipo può essere difficile (oltre a quelli molto ampi). Questo può essere un dolore.

Onestamente non penso che per lo "sviluppo di base" per la stragrande maggioranza dei progetti ci sia un vero aspetto negativo; è discusso molto più di quanto dovrebbe essere, di solito da persone che credono che il loro codice sia abbastanza buono da non aver bisogno di test (non lo è mai) e le persone che semplicemente non possono essere disturbate a scriverle.

12
Calum

Bene, e questo allungamento, è necessario eseguire il debug dei test. Inoltre, c'è un certo costo in termini di tempo per scrivere i test, anche se la maggior parte delle persone concorda sul fatto che si tratta di un investimento iniziale che ripaga nel corso della vita dell'applicazione sia in termini di debug risparmiati in termini di tempo che di stabilità.

Il problema più grande che ho avuto personalmente con esso, tuttavia, è alzare la disciplina per scrivere effettivamente i test. In una squadra, in particolare una squadra consolidata, può essere difficile convincerli che il tempo trascorso è utile.

9
Tim Sullivan

L'aspetto negativo di TDD è che di solito è strettamente associato alla metodologia "Agile", che pone no importanza sulla documentazione di un sistema, piuttosto la comprensione dietro perché un test "dovrebbe" restituire un valore specifico piuttosto che qualsiasi altro risiede solo nella testa dello sviluppatore.

Non appena lo sviluppatore lascia o dimentica il motivo per cui il test restituisce un valore specifico e non un altro, sei fregato. TDD va bene SE è adeguatamente documentato e circondato da documentazione leggibile dall'uomo (ad es. Manager dai capelli a punta) a cui si può fare riferimento in 5 anni quando il mondo cambia e anche l'app deve farlo.

Quando parlo di documentazione, questo non è un errore nel codice, questa è la scrittura ufficiale che esiste all'esterno dell'applicazione, come casi d'uso e informazioni di base a cui possono fare riferimento manager, avvocati e la povera linfa che deve aggiornare il tuo codice nel 2011.

7
Ron McMahon

Se i tuoi test non sono molto accurati, potresti cadere in un falso senso di "tutto funziona" solo perché i test superano. Teoricamente se i tuoi test superano, il codice funziona; ma se potessimo scrivere perfettamente il codice la prima volta non avremmo bisogno di test. La morale qui è assicurarsi di fare un controllo di integrità da soli prima di chiamare qualcosa di completo, non limitarsi a fare affidamento sui test.

In quella nota, se il tuo controllo di integrità trova qualcosa che non è stato testato, assicurati di tornare indietro e scrivere un test per questo.

7
Aaron Lee

Ho incontrato diverse situazioni in cui TDD mi fa impazzire. Per citarne alcuni:

  • Manutenibilità del test case:

    Se sei in una grande impresa, molte probabilità sono che non devi scrivere tu stesso i casi di test o almeno la maggior parte di essi sono scritti da qualcun altro quando entri in azienda. Le funzionalità di un'applicazione cambiano di volta in volta e se non si dispone di un sistema, come HP Quality Center, per seguirle, diventerai pazzo in pochissimo tempo.

    Ciò significa anche che i nuovi membri del team impiegheranno un bel po 'di tempo per capire cosa succede con i casi di test. A sua volta, questo può essere tradotto in più soldi necessari.

  • Test complessità automazione:

    Se si automatizzano alcuni o tutti i casi di test in script di test eseguibili dalla macchina, sarà necessario assicurarsi che questi script di test siano sincronizzati con i corrispondenti casi di test manuali e in linea con le modifiche dell'applicazione.

    Inoltre, impiegherai del tempo per eseguire il debug dei codici che ti aiutano a rilevare i bug. A mio avviso, la maggior parte di questi bug proviene dall'incapacità del team di test di riflettere le modifiche dell'applicazione nello script di test di automazione. I cambiamenti nella logica di business, nella GUI e in altri elementi interni possono far interrompere l'esecuzione o l'esecuzione in modo non gradevole degli script. A volte i cambiamenti sono molto sottili e difficili da rilevare. Una volta tutti i miei script riportano errori perché hanno basato il loro calcolo sulle informazioni dalla tabella 1 mentre la tabella 1 era ora la tabella 2 (perché qualcuno ha scambiato il nome degli oggetti della tabella nel codice dell'applicazione).

6
Martin08

Il problema più grande sono le persone che non sanno come scrivere test unitari adeguati. Scrivono test che dipendono l'uno dall'altro (e funzionano alla grande con Ant, ma poi all'improvviso falliscono quando li eseguo da Eclipse, solo perché corrono in un ordine diverso). Scrivono test che non testano nulla in particolare: eseguono il debug del codice, controllano il risultato e lo cambiano in test, chiamandolo "test1". Ampliano l'ambito di classi e metodi, solo perché sarà più facile scrivere test unitari per loro. Il codice dei test unitari è terribile, con tutti i classici problemi di programmazione (accoppiamento pesante, metodi lunghi 500 righe, valori codificati, duplicazione del codice) ed è un inferno da mantenere. Per qualche strana ragione le persone trattano i test unitari come qualcosa di inferiore al codice "reale" e non si preoccupano affatto della loro qualità. :-(

5
rmaruszewski

Perdi molto tempo a scrivere test. Ovviamente, questo potrebbe essere salvato entro la fine del progetto catturando più rapidamente i bug.

4
Joel Coehoorn

Perdi la possibilità di dire che hai "finito" prima di testare tutto il tuo codice.

Si perde la capacità di scrivere centinaia o migliaia di righe di codice prima di eseguirlo.

Perdi l'opportunità di imparare tramite il debug.

Perdi la flessibilità di spedire il codice di cui non sei sicuro.

Perdi la libertà di accoppiare strettamente i tuoi moduli.

Si perde la possibilità di saltare la scrittura di documentazione di progettazione di basso livello.

Si perde la stabilità fornita con il codice che tutti hanno paura di cambiare.

Perdi il titolo di "hacker".

4
Uncle Bob

Il più grande svantaggio è che se vuoi davvero fare correttamente il TDD dovrai fallire molto prima di riuscire. Dato il numero di aziende produttrici di software (dollaro per KLOC), alla fine verrai licenziato. Anche se il tuo codice è più veloce, più pulito, più facile da mantenere e ha meno bug.

Se lavori in un'azienda che ti paga con i KLOC (o requisiti implementati - anche se non testati) stai lontano da TDD (o revisioni del codice, o accoppia la programmazione, o l'integrazione continua, ecc. Ecc.).

3
Vasco Duarte

Rifocalizzare su requisiti difficili e imprevisti è la rovina costante del programmatore. Lo sviluppo guidato dai test ti costringe a concentrarti sui requisiti già noti e banali e limita il tuo sviluppo a ciò che è già stato immaginato.

Pensaci, probabilmente finirai per progettare casi di test specifici, quindi non sarai creativo e inizi a pensare "sarebbe bello se l'utente potesse fare X, Y e Z". Pertanto, quando l'utente inizia a entusiasmarsi per i potenziali requisiti interessanti X, Y e Z, il progetto potrebbe essere troppo rigido per casi di test già specificati e sarà difficile da regolare.

Questa, ovviamente, è un'arma a doppio taglio. Se passi tutto il tuo tempo a progettare per ogni immaginabile, immaginabile, X, Y e Z che un utente possa desiderare, inevitabilmente non completerai mai nulla. Se fai qualcosa, sarà impossibile per chiunque (incluso te stesso) avere idea di cosa stai facendo nel tuo codice/design.

2
Doug T.

Secondo la risposta sui tempi di sviluppo iniziale. Si perde anche la capacità di lavorare comodamente senza la sicurezza dei test. Sono stato anche descritto come un nutbar TDD, quindi potresti perdere alcuni amici;)

2
Chris Canal

È percepito come più lento. A lungo termine non è vero in termini di dolore che ti farà risparmiare lungo la strada, ma finirai per scrivere più codice, quindi probabilmente stai spendendo tempo per "testare non codificare". È un argomento imperfetto, ma te l'hai chiesto!

2
MarcE

Può essere difficile e dispendioso in termini di tempo scrivere test per dati "casuali" come feed e database XML (non così difficile). Ultimamente ho trascorso del tempo a lavorare con i feed di dati meteorologici. È abbastanza confuso scrivere test per questo, almeno perché non ho troppa esperienza con TDD.

1
Vargen

Ci vuole un po 'di tempo per entrarci e un po' di tempo per iniziare a farlo in un progetto ma ... mi pento sempre di non aver seguito un approccio Test Driven quando trovo bug stupidi che un test automatico avrebbe potuto trovare molto velocemente. Inoltre, TDD migliora la qualità del codice.

1
aerlijman

Buone risposte a tutti. Aggiungerei alcuni modi per evitare il lato oscuro del TDD:

  • Ho scritto app per fare il proprio autotest randomizzato. Il problema con la scrittura di test specifici è che anche se ne scrivi molti coprono solo i casi che pensi. I generatori di test casuali trovano problemi a cui non hai pensato.

  • L'intero concetto di numerosi test unitari implica la presenza di componenti che possono entrare in stati non validi, come strutture dati complesse. Se stai lontano da strutture dati complesse, c'è molto meno da testare.

  • Nella misura in cui la tua applicazione lo consente, sii timido rispetto al design che si basa sul corretto ordinamento di notifiche, eventi ed effetti collaterali. Questi possono essere facilmente lasciati cadere o rimescolati quindi hanno bisogno di molti test.

1
Mike Dunlavey
  • unit test sono più codice da scrivere, quindi un costo iniziale di sviluppo più elevato
  • è più codice da mantenere
  • apprendimento aggiuntivo richiesto
1
Bob Dizzle

Perderai grandi lezioni con più responsabilità. Probabilmente perderai anche grandi metodi con responsabilità multiple. Potresti perdere qualche capacità di refactoring, ma perderai anche parte della necessità di refactoring.

Jason Cohen ha detto qualcosa del tipo: TDD richiede una certa organizzazione per il tuo codice. Questo potrebbe essere architettonicamente sbagliato; ad esempio, poiché i metodi privati ​​non possono essere chiamati al di fuori di una classe, è necessario rendere i metodi non privati ​​per renderli verificabili.

Dico che questo indica un'astrazione mancata: se il codice privato deve davvero essere testato, dovrebbe probabilmente essere in una classe separata.

Dave Mann

1
Dave Mann

Devi scrivere le applicazioni in un modo diverso: quello che le rende testabili. Saresti sorpreso di quanto sia difficile all'inizio.

Alcune persone trovano l'idea di pensare a ciò che scriveranno prima di scriverlo troppo. Concetti come il deridere possono anche essere difficili per alcuni. Il TDD nelle app legacy può essere molto difficile se non sono state progettate per i test. Anche il TDD in contesti non compatibili con il TDD può essere una lotta.

TDD è un'abilità quindi gli sviluppatori più giovani possono inizialmente lottare (principalmente perché non gli è stato insegnato a lavorare in questo modo).

Nel complesso, però, i contro vengono risolti man mano che le persone diventano abili e finisci per sottrarre il codice "puzzolente" e avere un sistema più stabile.

1

La persona che ha insegnato allo sviluppo agile del mio team non ha creduto nella pianificazione, hai scritto solo per il più piccolo requisito.

Il suo motto era refattore, refattore, refattore. Ho capito che refactor significava "non pianificare in anticipo".

0
Jack B Nimble

Consentitemi di aggiungere che se si applicano i principi BDD a un progetto TDD, è possibile alleviare alcuni dei principali inconvenienti elencati qui (confusione, incomprensioni, ecc.). Se non hai familiarità con BDD, dovresti leggere l'introduzione di Dan North. Ha elaborato il concetto in risposta ad alcune delle questioni emerse dall'applicazione del TDD sul posto di lavoro. L'introduzione di Dan su BDD può essere trovata qui .

Faccio solo questo suggerimento perché BDD affronta alcuni di questi aspetti negativi e funge da gap-stop. Ti consigliamo di considerare questo quando raccogli il tuo feedback.

0
Kilhoffer

TDD richiede una determinata organizzazione per il tuo codice. Questo potrebbe essere inefficiente o difficile da leggere. O anche architettonicamente sbagliato; ad esempio, poiché i metodi private non possono essere chiamati al di fuori di una classe, è necessario rendere i metodi non privati ​​per renderli verificabili, il che è semplicemente sbagliato.

Quando il codice cambia, è necessario modificare anche i test. Con il refactoring questo può richiedere molto lavoro extra.

0
Jason Cohen

Devi assicurarti che i tuoi test siano sempre aggiornati, il momento in cui inizi a ignorare le luci rosse è il momento in cui i test diventano insignificanti.

Devi anche assicurarti che i test siano completi, o nel momento in cui appare un grosso bug, il tipo di gestione soffocante che hai finalmente convinto di farti passare del tempo a scrivere più codice si lamenterà.

0
qui