Quali sono gli svantaggi della programmazione test-first?

46

Al giorno d'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 riflessioni ipotetiche di cento aspiranti altrove su Internet.

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

    
posta Alex Feinman 20.09.2010 - 15:24
fonte

9 risposte

41

Ce ne sono alcuni, ma i vantaggi lontano superano gli svantaggi.

C'è una curva di apprendimento ripida.

Molti sviluppatori sembrano aspettarsi che possano essere efficienti con la programmazione prima del test fin dal primo giorno. Sfortunatamente ci vuole un sacco di tempo per acquisire esperienza e programmare alla stessa velocità di prima. Non puoi aggirarlo.

Per essere più specifici, è molto facile sbagliare. Puoi facilmente (con ottime intenzioni) finire a scrivere un sacco di test che sono difficili da mantenere o testare le cose sbagliate. È difficile dare esempi qui - questi tipi di problemi richiedono semplicemente esperienza per risolvere. È necessario avere una buona sensazione di separare le preoccupazioni e progettare per testabilità. Il mio miglior consiglio qui sarebbe di fare la programmazione della coppia con qualcuno che conosce molto bene il TDD.

Fai più codice in anticipo.

Test-first significa che non puoi saltare i test (che è buono) e significa che finirai a scrivere più codice in anticipo. Questo significa più tempo. Di nuovo, non puoi aggirarlo. Sei ricompensato con un codice che è più facile da mantenere, estendere e in genere meno bug, ma ci vuole tempo.

Può essere una vendita difficile per i gestori.

I gestori di software sono generalmente interessati solo dalle scadenze. Se passi alla programmazione di prova e ti stai improvvisamente impiegando 2 settimane per completare una funzione invece di una, a loro non piacerà. Questa è sicuramente una battaglia che vale la pena combattere e molti manager sono abbastanza illuminati per ottenerlo, ma può essere una vendita difficile.

Può essere una dura vendita per gli altri sviluppatori.

Poiché c'è una curva di apprendimento ripida, non tutti gli sviluppatori preferiscono la programmazione prima del test. In effetti, immagino che all'inizio non piaccia agli sviluppatori più . Puoi fare cose come la programmazione delle coppie per aiutarle a diventare più veloci, ma può essere una vendita difficile.

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

    
risposta data 20.09.2010 - 15:27
fonte
35

In primo luogo si presuppone che si stia scrivendo il codice che è:

  • verificabile in modalità unità di test
  • che ciò che stai sviluppando ha un approccio ovvio e non richiederà una prototipazione o sperimentazione estesa
  • che non hai bisogno di refactoring troppo pesante o che hai il tempo di riscrivere ripetutamente centinaia o migliaia di casi di test
  • niente è sigillato
  • tutto è modulare
  • tutto è iniettabile o mockable
  • 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 test unitario

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

In pratica posso anche avere un grosso problema con le persone che pensano che i primi test test dimostrino in realtà qualcosa sulla funzione corretta del programma. In molti casi questo non è vero, ma anche nei casi in cui è vero non è affatto un quadro completo della correttezza. Le persone vedono centinaia di test che passano e si presume che sia sicuro testare meno dal momento che prima del TDD hanno fatto solo alcune centinaia di test case comunque. Nella mia esperienza TDD significa che è necessario avere ancora più test di integrazione in quanto gli sviluppatori avranno anche la falsa sicurezza e il dolore di cambiare tutti i test per fare un grande redactor può portare gli sviluppatori a fare cose interessanti.

Esempi:

Il mio miglior esempio personale è quando si scrive codice di sicurezza per asp.net. Se sono pensati per essere eseguiti in un ambiente ostile dalla configurazione della macchina, sono fatti gac, firmati e sigillati e, poiché sono in esecuzione contro gli oggetti di IIS, sono molto difficili da simulare in modo corretto. Aggiungi alcuni vincoli per l'utilizzo delle prestazioni e della memoria e perdi molto rapidamente la flessibilità di utilizzare oggetti segnaposto nelle aree rimanenti.

Qualsiasi tipo di microcontrollore o altro codice di ambiente con risorse limitate potrebbe non essere possibile eseguire un design di stile OO in quanto le astrazioni non vengono ottimizzate e si hanno limiti di risorse bassi. Lo stesso vale per le routine ad alte prestazioni anche in molti casi.

    
risposta data 20.09.2010 - 15:54
fonte
25

Il più grande inconveniente che ho visto non è con TDD ma con i professionisti. Prendono un approccio dogmatico e zelante dove tutto deve essere testato . A volte (molte volte), non è necessario. Inoltre, potrebbe non essere pratico (introducendo un'organizzazione a TDD.)

Un buon ingegnere trova dei compromessi e applica il giusto equilibrio di quando / dove / come applicare il test-first. Inoltre, se ti trovi costantemente a spendere molto più tempo a sviluppare test anziché codice effettivo (di un fattore 2-3 o più), sei nei guai.

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

    
risposta data 14.10.2010 - 18:32
fonte
6

Ho iniziato a fare TDD all'inizio di agosto 2009 e ho convinto tutta la mia azienda a passare a settembre / ottobre 2009. Attualmente, l'intero team di sviluppo è completamente convertito e l'inserimento di codice non verificato nel repository è considerato una cosa brutta e generata su. Ha funzionato benissimo per noi, e non posso immaginare di tornare alla codifica dei cowboy.

Tuttavia, ci sono due problemi che sono piuttosto evidenti.

La suite di test deve essere mantenuta

Quando sei serio riguardo a TDD, finirai per scrivere lotti di test. Inoltre, ci vuole un po 'di tempo e di esperienza per capire quale sia la giusta granularità dei test (l'overdoing è quasi tanto difficile quanto sottovalutarlo). Questi test sono anche code e sono suscettibili al bitrot. Ciò significa che devi mantenerli come tutto il resto: aggiornalo quando aggiorni le librerie da cui dipendono, refactor di tanto in tanto ... Quando fai grandi cambiamenti nel tuo codice, molti test diventeranno improvvisamente obsoleti o anche semplicemente sbagliato. Se sei fortunato, puoi semplicemente eliminarli, ma molte volte finirai per estrarre i bit utili e adattarli alla nuova architettura.

Le estensioni di test si verificano di tanto in tanto

Usiamo Django, che ha un framework di test piuttosto interessante. 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 fai localmente, ma alcuni codici si comportano in modo diverso a seconda del database che usi. La configurazione di un server di integrazione continua che viene eseguito in una configurazione realistica è un must.

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

Tutto ciò detto, i problemi che ho descritto cominciano a essere evidenti solo quando sei abbastanza avanzato con TDD ... Quando inizi a lavorare con TDD (o lavori su progetti più piccoli) il refactoring dei test non sarà un problema.

    
risposta data 09.10.2010 - 19:05
fonte
4

Per me c'è qualche problema psicologico profondo con i test ogni volta che cerco di applicarli estesamente, come nel TDD: se sono lì, codice a malincuore perché ho fiducia che i test cattureranno qualsiasi problema. Ma se non ci sono test per fornire una rete di sicurezza, codice attentamente, 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 di sicurezza e amp; i fischietti tendono a schiantarsi di più (perché i piloti sanno che ci sono le caratteristiche di sicurezza), quindi forse questo è qualcosa da riconoscere; TDD può essere incompatibile con alcuni individui.

    
risposta data 14.10.2010 - 19:04
fonte
2

Una situazione in cui il test-first si mette davvero in mezzo è quando voglio provare rapidamente un'idea e vedere se può funzionare prima di scrivere una corretta implementazione.

Il mio approccio è normalmente:

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

A volte non arrivo al punto 2.

In questo caso, l'uso di TDD ha avuto per me più svantaggi che vantaggi:

  • Scrivere i test durante l'implementazione della dimostrazione del concetto mi rallenta e interrompe il mio flusso di pensieri: voglio capire un'idea e non voglio perdere tempo a verificare i dettagli della mia prima implementazione approssimativa.
  • Potrebbe essere necessario più tempo per scoprire se la mia idea vale qualcosa o no.
  • Se si scopre che l'idea era inutile, devo buttare via sia il mio codice che i miei test unitari ben scritti.

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

    
risposta data 06.10.2014 - 08:53
fonte
1

Svantaggi o costi di TDD

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

Effetti collaterali

Che si tratti di beffe, infissi o test funzionali, le dipendenze da stati o sistemi esterni sono spesso la fonte della maggior complessità nei test, confusione nella modalità di test e maggior rischio di sbagliare. Alcuni problemi che ho riscontrato:

  • Mocking: dimentica di confermare l'ordine delle chiamate
  • Mocking: mock non corrisponde alla vera chiamata o risposta
  • Fixture: il test si basa su dati non realistici, mascherando altri problemi
  • Fixture: prova uno stato impossibile in produzione
  • Funzionale: false interruzioni di build a causa del fatto che il sistema dipendente non è temporaneamente disponibile
  • Funzionale: la velocità del test è molto lenta

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

Codice di persone diverse in modi completamente diversi. In TDD è necessario iniziare con un test che asserisce un comportamento specifico e quindi implementarlo in modo che il test passi. Ho visto ed ero un programmatore la cui programmazione non era favorevole al TDD. Mi ci sono voluti circa 2 mesi quando ho iniziato ad abituarmi a cambiare il mio approccio allo 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 durante i test. Quali cose apprezzano che vogliono testate 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.

Unit Test specifico: refactori di grandi dimensioni

Un refactore grande o fondamentale di una base di codice significativa con decine di migliaia di test unitari genererà un costo enorme per aggiornare tutti i test. Questo si manifesterà spesso nel pushback contro il refactoring anche se è la cosa giusta da fare semplicemente perché il costo associato a farlo.

    
risposta data 06.10.2014 - 10:38
fonte
0

La mia analogia è costituita da barriere su una traccia Scalextric. Se li metti su, diventi molto meno cauto.

Le persone hanno anche un po 'di spazio in cadenza sui loro test - perché corrono bene, credono che il codice sia completamente testato mentre è solo l'inizio del processo di test.

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

    
risposta data 06.10.2014 - 13:52
fonte
-1

I vantaggi di TDD sono che ti costringe a proteggere il tuo codice contro le persone che non lo capiscono. Sì, questo spesso include te stesso. Ma cosa succede quando il codice non vale la pena di essere guardato? C'è un sacco di codice che non dovrebbe nemmeno essere lì in primo luogo! Quindi il problema con TDD è quando si tratta di sviluppatori che scrivono codice errato. Probabilmente TDD non li aiuterà a scrivere un buon codice, è molto più probabile che scriveranno anche test orribili. Quindi nel loro caso TDD aggiungerà solo un casino; I test scritti male e / o ridondanti non sono più divertenti di altre forme di codice errato.

    
risposta data 06.10.2014 - 09:46
fonte

Leggi altre domande sui tag