it-swarm.it

Quali sono gli svantaggi della programmazione test-first?

Oggi è di gran moda. "Tutti" lo consiglia. Questo di per sé mi rende sospettoso.

Quali sono alcuni svantaggi che hai riscontrato durante lo sviluppo test-first (test-driven)? Sto cercando esperienze personali da professionisti esperti - posso leggere le ipotetiche riflessioni di un centinaio di aspiranti altrove su Internet.

Non chiedo perché sto cercando di odiare il TDD, ma perché il mio compito è migliorare il processo di sviluppo del software e più possiamo conoscere i problemi che le persone incontrano, maggiori sono le possibilità che abbiamo di migliorare il processo.

48
Alex Feinman

Ce ne sono parecchi, ma i vantaggi di gran lunga superano gli svantaggi.

C'è una ripida curva di apprendimento.

Molti sviluppatori sembrano aspettarsi di poter essere efficienti con la programmazione test-first fin dal primo giorno. Purtroppo ci vuole molto tempo per acquisire esperienza e programmare alla stessa velocità di prima. Non puoi aggirarlo.

Per essere più specifici, è molto facile sbagliarsi. Puoi facilmente (con ottime intenzioni) finire per scrivere un sacco di test che sono difficili da mantenere o testare cose sbagliate. È difficile fornire esempi qui: questo tipo di problemi richiede semplicemente esperienza per risolverli. Devi avere una buona idea di separare le preoccupazioni e progettare per la testabilità. Il mio miglior consiglio qui sarebbe di programmare la coppia con qualcuno che conosca davvero bene TDD.

Fai più codice all'inizio.

Test-first significa che non puoi saltare i test (il che è buono) e significa che finirai per scrivere più codice in anticipo. Questo significa più tempo. Ancora una volta, non puoi aggirarlo. Vieni premiato con un codice che è più facile da mantenere, estendere e generalmente meno bug, ma richiede tempo.

Può essere una vendita difficile ai gestori.

I gestori di software si occupano generalmente solo delle scadenze. Se passi alla programmazione test-first e all'improvviso stai impiegando 2 settimane per completare una funzione anziché una, non piacerà. Questa è sicuramente una battaglia che vale la pena combattere e molti manager sono abbastanza illuminati da ottenerla, ma può essere una vendita difficile.

Può essere una vendita difficile ai colleghi sviluppatori.

Dal momento che c'è una ripida curva di apprendimento, non tutti gli sviluppatori amano la programmazione test-first. In effetti, immagino che alla maggior parte degli sviluppatori all'inizio non piaccia. Puoi fare cose come la programmazione in coppia per aiutarli ad accelerare, ma può essere una vendita difficile.

Alla fine, i vantaggi superano gli svantaggi, ma non aiuta se si ignorano solo gli svantaggi. Sapere con cosa hai a che fare fin dall'inizio ti aiuta a negoziare alcuni, se non tutti, gli svantaggi.

41
Jaco Pretorius

Test-first presuppone che tu stia scrivendo un codice che è:

  • testabile in modo unit-test
  • che quello che stai sviluppando ha un approccio ovvio e non richiederà prototipi o sperimentazioni approfondite
  • che non sarà necessario eseguire il refactoring eccessivo o che si ha il tempo di riscrivere ripetutamente centinaia o migliaia di casi di test
  • nulla è sigillato
  • tutto è modulare
  • tutto è iniettabile o beffardo
  • che la tua organizzazione attribuisce un valore sufficientemente alto ai difetti bassi per giustificare il sink di risorse
  • che c'è qualcosa di utile da testare a livello di unit test

Se il tuo progetto non soddisfa tali requisiti, avrai difficoltà. I promotori di TDD non hanno buone risposte a questo altro per suggerire di ridisegnare il prodotto per rientrare al meglio in quelle linee. Ci sono situazioni in cui ciò è impossibile o indesiderabile.

In pratica, posso anche riscontrare un grosso problema con le persone che pensano che i test test-first dimostrino effettivamente qualcosa sulla corretta funzione del programma. In molti casi questo non è vero, ma anche nei casi in cui è vero è ben lungi dall'essere un quadro completo della correttezza. Le persone vedono centinaia di test superati e presumono che sia sicuro testare meno poiché prima del TDD hanno fatto comunque solo poche centinaia di casi di test. Nella mia esperienza TDD significa che devi avere ancora più test di integrazione poiché gli sviluppatori avranno anche la falsa sicurezza e il dolore di cambiare tutti i test per fare un grande redattore può portare gli sviluppatori a fare interessanti soluzioni.

Esempi:

Il mio miglior esempio personale è quando scrivo il codice di sicurezza per asp.net. Se sono pensati per funzionare in un ambiente ostile dalla configurazione della macchina, vengono bombardati, firmati e sigillati e poiché stanno correndo contro IIS oggetti divini sono molto difficili da deridere molto molto correttamente. Aggiungete alcuni vincoli per le prestazioni e l'uso della memoria e perdete molto rapidamente la flessibilità di utilizzare oggetti segnaposto nelle restanti aree.

Qualsiasi tipo di microcontrollore o altro codice di ambiente con risorse limitate potrebbe non essere possibile eseguire veramente OO design in stile poiché le astrazioni non si ottimizzano e si hanno bassi limiti di risorse. Lo stesso si può dire per routine ad alte prestazioni anche in molti casi.

36
Bill

Il più grande svantaggio che ho visto non è con TDD stesso ma con i praticanti. Adottano un approccio dogmatico e zelante in cui tutto deve essere testato . A volte (molte volte), non è necessario. Inoltre, potrebbe non essere pratico (.ie. Introdurre un'organizzazione al TDD.)

Un buon ingegnere trova dei compromessi e applica il giusto equilibrio tra quando/dove/come applicare il test prima. Inoltre, se ti ritrovi a dedicare costantemente molto più tempo allo sviluppo di test anziché al codice effettivo (con un fattore di 2-3 o più), sei nei guai.

In altre parole, sii pragmatico e ragionevole con TDD (o qualsiasi altra cosa nello sviluppo di software per quella materia).

26
luis.espinal

Ho iniziato a fare TDD all'inizio di agosto 2009 e ho convinto tutta la mia compagnia a passare ad essa a settembre/ottobre 2009. Attualmente, tutto il team di sviluppo è completamente convertito, e commettere codice non testato nel repository è considerato una cosa negativa e lanciato. Ha funzionato alla grande per noi, e non riesco a immaginare di tornare alla programmazione da cowboy.

Tuttavia, ci sono due problemi che sono abbastanza evidenti.

La suite di test deve essere mantenuta

Quando prendi sul serio TDD, finirai per scrivere lotti di test. Inoltre, ci vuole un po 'di tempo ed esperienza per capire qual è la granularità dei test corretta (esagerare è quasi altrettanto grave che esagerare). Questi test sono anche codice e sono sensibili ai bitrot. Ciò significa che devi mantenerli come tutto il resto: aggiornalo quando aggiorni le librerie da cui dipendono, fai il refactor di volta in volta ... Quando apporti grandi modifiche al tuo codice, molti test diventeranno improvvisamente obsoleti o anche chiaramente sbagliato. Se sei fortunato, puoi semplicemente cancellarli, ma molte volte finirai per estrarre i bit utili e adattarli alla nuova architettura.

Test di astrazione perdite di volta in volta

Stiamo usando Django, che ha un framework di test davvero eccezionale. Tuttavia, a volte fa ipotesi che sono leggermente in contrasto con la realtà. Ad esempio, alcuni middleware potrebbero interrompere i test. Oppure, alcuni test fanno ipotesi su un backend di cache. Inoltre, se si utilizza un db "reale" (non SQLite3), la preparazione del db per i test richiederà molto tempo. Certo, puoi (e dovresti) usare SQLite3 e un db in memoria per i test che esegui localmente, ma alcuni codici si comporteranno in modo diverso a seconda del database che utilizzi. La configurazione di un server di integrazione continua che viene eseguita in una configurazione realistica è un must.

(Alcune persone ti diranno che dovresti prendere in giro tutte le cose come il database, o i tuoi test non sono "puri", ma è solo ideologia. Se commetti errori nel tuo codice beffardo (e credimi, lo farai), la tua suite di test sarà inutile.)

Detto questo, i problemi che ho descritto iniziano ad essere evidenti solo quando sei abbastanza avanzato con TDD ... Quando inizi con TDD (o lavori su progetti più piccoli) il refactoring dei test non sarà un problema.

6
Ryszard Szopa

Per me c'è qualche profondo problema psicologico con i test ogni volta che provo ad applicarli ampiamente, come in TDD: se sono lì, scrivo in modo sciatto perché confido che i test colmino eventuali problemi. Ma se non ci sono test per fornire una rete di sicurezza, scrivo attentamente il codice e il risultato è invariabilmente migliore rispetto ai test.

Forse sono solo io. Ma ho anche letto da qualche parte che le auto con tutti i tipi di campane e fischietti di sicurezza tendono a schiantarsi di più (perché i conducenti sanno che le caratteristiche di sicurezza sono lì), quindi forse questo è qualcosa da riconoscere; TDD può essere incompatibile con alcuni individui.

4
Joonas Pulakka

Una situazione in cui test-first è davvero sulla mia strada è quando voglio provare rapidamente qualche idea e vedere se può funzionare prima di scrivere una corretta implementazione.

Il mio approccio è normalmente:

  1. Implementa qualcosa che funziona (proof of concept).
  2. Se funziona, consolidare aggiungendo test, migliorando la progettazione, il refactoring.

A volte non riesco a passare al punto 2.

In questo caso, l'utilizzo di TDD si è rivelato avere più svantaggi che vantaggi per me:

  • Scrivere test durante l'implementazione della proof of concept mi ​​rallenta e interrompe il mio flusso di pensieri: voglio capire un'idea e non voglio perdere tempo a testare i dettagli della mia prima implementazione approssimativa.
  • Potrebbe volerci più tempo per scoprire se la mia idea vale o no.
  • Se si scopre che l'idea era inutile, devo buttare via sia il mio codice che i miei test di unità ben scritti.

Quindi, quando devo esplorare alcune nuove idee, non uso TDD e introduco test unitari solo quando ho la sensazione che il nuovo codice stia arrivando da qualche parte.

2
Giorgio

Svantaggi o costi del TDD

Nota: esiste una gamma di diversi tipi di TDD. Indipendentemente da unità, BDD, ATDD o altre varianti rimangono molte difficoltà

Effetti collaterali

Che si tratti di derisione, dispositivi o test funzionali, le dipendenze da stati o sistemi esterni sono spesso la fonte della maggior complessità nei test, la confusione nel modo di testare e il rischio maggiore di sbagliarli. Alcuni problemi che ho visto:

  • Beffardo: dimentica di far valere l'ordine delle chiamate
  • Derisione: la derisione non corrisponde alla chiamata o alla risposta reale
  • Apparecchio: il test si basa su dati non realistici, mascherando altri problemi
  • Apparecchio: prova uno stato impossibile in produzione
  • Funzionale: false build si interrompe a causa della temporanea indisponibilità del sistema dipendente
  • Funzionale: la velocità del test è molto lenta

Dovrai cambiare il tuo approccio alla programmazione, per alcuni sarà un drastico cambiamento.

Diverse persone codificano in modi selvaggiamente diversi. In TDD è necessario iniziare con un test che asserisce un comportamento specifico e quindi implementare in modo che il test passi. Ho visto ed era un programmatore la cui programmazione non era favorevole a TDD. Mi ci sono voluti circa 2 mesi quando inizialmente ho iniziato ad abituarmi a cambiare il mio approccio di sviluppo.

Ci vuole tempo per capire cosa ti interessa dei test e cosa non ti interessa dei test.

Ogni squadra dovrebbe prendere una decisione esplicita su dove vuole tracciare la linea nei test. Quali cose apprezzano che vogliono testare e cosa no. Spesso è un processo doloroso imparare a scrivere buoni test e cosa ti interessa davvero dei test. Nel frattempo il codice continuerà ad essere in uno stato di flusso fino a quando non ci sarà coerenza sia nello stile che nell'approccio.

Specifico per unit test: refactor di grandi dimensioni

Un refactor grande o fondamentale di una base di codice significativa con decine di migliaia di unit test genererà un costo enorme per aggiornare tutti i test. Ciò si manifesterà spesso nel respingere il fare un refattore anche se è la cosa giusta da fare semplicemente perché i costi associati a farlo.

1
dietbuddha

La mia analogia sono le barriere su una traccia Scalextric. Se li indossi, diventi molto meno cauto.

Le persone ottengono anche un po 'di spazio sui loro test - poiché funzionano bene, credono che il codice sia completamente testato mentre è solo l'inizio del processo di test.

Secondo me TDD è un trampolino di lancio per BDD. Una serie di test eseguiti non aiuta davvero gli sviluppatori senza sapere cosa fanno i test. Con BDD, l'output del test è in inglese che documenta il test e quindi migliora la comprensione del sistema.

0
Robbie Dee